[evolution] EHTMLEditorView - Implement undo and redo on text operations in table
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] EHTMLEditorView - Implement undo and redo on text operations in table
- Date: Sun, 15 Mar 2015 19:26:12 +0000 (UTC)
commit 07c1b218d9a943317c520227f8ee1157147412e1
Author: Tomas Popela <tpopela redhat com>
Date: Sun Mar 15 11:42:16 2015 +0100
EHTMLEditorView - Implement undo and redo on text operations in table
The problem here is that we can't use the same solution for other
operations as the webkit_dom_document_caret_range_from_point will
return range that will just contain the focused TD element and not the
exact caret position. This is the WebKit limitation (the same applies
for TEXTAREA elements) so we have to save the whole TD element instead
of just saving what was added or removed.
e-util/e-html-editor-selection.c | 7 ++
e-util/e-html-editor-view.c | 176 ++++++++++++++++++++++++++++++++++++--
e-util/e-html-editor-view.h | 1 +
3 files changed, 178 insertions(+), 6 deletions(-)
---
diff --git a/e-util/e-html-editor-selection.c b/e-util/e-html-editor-selection.c
index 190762a..0d99e78 100644
--- a/e-util/e-html-editor-selection.c
+++ b/e-util/e-html-editor-selection.c
@@ -6504,6 +6504,13 @@ e_html_editor_selection_save (EHTMLEditorSelection *selection)
webkit_dom_node_get_first_child (container),
NULL);
goto insert_end_marker;
+ } else if (WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (container)) {
+ marker_node = webkit_dom_node_insert_before (
+ container,
+ WEBKIT_DOM_NODE (start_marker),
+ webkit_dom_node_get_first_child (container),
+ NULL);
+ goto insert_end_marker;
} else if (element_has_class (WEBKIT_DOM_ELEMENT (container), "-x-evo-resizable-wrapper")) {
marker_node = webkit_dom_node_insert_before (
parent_node,
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index b974a5f..0f919cc 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -291,6 +291,7 @@ print_history_event (EHTMLEditorViewHistoryEvent *event)
case HISTORY_IMAGE_DIALOG:
case HISTORY_CELL_DIALOG:
case HISTORY_TABLE_DIALOG:
+ case HISTORY_TABLE_INPUT:
case HISTORY_PAGE_DIALOG:
print_node_inner_html (event->data.dom.from);
print_node_inner_html (event->data.dom.to);
@@ -2239,13 +2240,15 @@ surround_text_with_paragraph_if_needed (EHTMLEditorSelection *selection,
{
WebKitDOMNode *next_sibling = webkit_dom_node_get_next_sibling (node);
WebKitDOMNode *prev_sibling = webkit_dom_node_get_previous_sibling (node);
+ WebKitDOMNode *parent = webkit_dom_node_get_parent_node (node);
WebKitDOMElement *element;
/* All text in composer has to be written in div elements, so if
* we are writing something straight to the body, surround it with
* paragraph */
if (WEBKIT_DOM_IS_TEXT (node) &&
- WEBKIT_DOM_IS_HTML_BODY_ELEMENT (webkit_dom_node_get_parent_node (node))) {
+ (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent) ||
+ WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (parent))) {
element = e_html_editor_selection_put_node_into_paragraph (
selection, document, node, TRUE);
@@ -2284,6 +2287,47 @@ body_keydown_event_cb (WebKitDOMElement *element,
view->priv->dont_save_history_in_body_input = TRUE;
}
+static gboolean
+save_history_before_event_in_table (EHTMLEditorView *view,
+ WebKitDOMRange *range)
+{
+ WebKitDOMNode *node;
+ WebKitDOMElement *block;
+
+ node = webkit_dom_range_get_start_container (range, NULL);
+ if (WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (node))
+ block = WEBKIT_DOM_ELEMENT (node);
+ else
+ block = get_parent_block_element (node);
+
+ if (block && WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (block)) {
+ EHTMLEditorViewHistoryEvent *ev;
+
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_TABLE_INPUT;
+
+ if (block) {
+ e_html_editor_selection_save (view->priv->selection);
+ ev->data.dom.from = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (block), TRUE);
+ e_html_editor_selection_restore (view->priv->selection);
+ } else
+ ev->data.dom.from = NULL;
+
+ e_html_editor_selection_get_selection_coordinates (
+ view->priv->selection,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ e_html_editor_view_insert_new_history_event (view, ev);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
body_keypress_event_cb (WebKitDOMElement *element,
WebKitDOMUIEvent *event,
@@ -2309,6 +2353,9 @@ body_keypress_event_cb (WebKitDOMElement *element,
dom_selection = webkit_dom_dom_window_get_selection (dom_window);
range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+ if (save_history_before_event_in_table (view, range))
+ return;
+
if (!webkit_dom_range_get_collapsed (range, NULL)) {
EHTMLEditorViewHistoryEvent *ev;
WebKitDOMDocumentFragment *fragment;
@@ -2330,6 +2377,56 @@ body_keypress_event_cb (WebKitDOMElement *element,
}
}
+static gboolean
+save_history_after_event_in_table (EHTMLEditorView *view)
+{
+ EHTMLEditorViewHistoryEvent *ev;
+ WebKitDOMDocument *document;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *element;
+ WebKitDOMNode *node;
+ WebKitDOMRange *range;
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ if (!webkit_dom_dom_selection_get_range_count (dom_selection))
+ return FALSE;
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+ /* Find if writing into table. */
+ node = webkit_dom_range_get_start_container (range, NULL);
+ if (WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (node))
+ element = WEBKIT_DOM_ELEMENT (node);
+ else
+ element = get_parent_block_element (node);
+
+ /* If writing to table we have to create different history event. */
+ if (WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (element)) {
+ ev = view->priv->history->data;
+ if (ev->type != HISTORY_TABLE_INPUT)
+ return FALSE;
+ } else
+ return FALSE;
+
+ e_html_editor_selection_save (view->priv->selection);
+
+ e_html_editor_selection_get_selection_coordinates (
+ view->priv->selection,
+ &ev->after.start.x,
+ &ev->after.start.y,
+ &ev->after.end.x,
+ &ev->after.end.y);
+
+ ev->data.dom.to = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (element), TRUE);
+
+ e_html_editor_selection_restore (view->priv->selection);
+
+ return TRUE;
+}
+
static void
save_history_for_input (EHTMLEditorView *view)
{
@@ -2423,10 +2520,12 @@ body_input_event_cb (WebKitDOMElement *element,
return;
}
- if (!view->priv->dont_save_history_in_body_input)
- save_history_for_input (view);
- else
- e_html_editor_view_force_spell_check_for_current_paragraph (view);
+ if (!save_history_after_event_in_table (view)) {
+ if (!view->priv->dont_save_history_in_body_input)
+ save_history_for_input (view);
+ else
+ e_html_editor_view_force_spell_check_for_current_paragraph (view);
+ }
/* Don't try to look for smileys if we are deleting text. */
if (!view->priv->dont_save_history_in_body_input)
@@ -2475,7 +2574,7 @@ body_input_event_cb (WebKitDOMElement *element,
/* After toggling monospaced format, we are using UNICODE_ZERO_WIDTH_SPACE
* to move caret into right space. When this callback is called it is not
- * necassary anymore so remove it */
+ * necessary anymore so remove it */
if (view->priv->html_mode) {
WebKitDOMElement *parent = webkit_dom_node_get_parent_element (node);
@@ -3227,6 +3326,7 @@ free_history_event_content (EHTMLEditorViewHistoryEvent *event)
case HISTORY_IMAGE_DIALOG:
case HISTORY_CELL_DIALOG:
case HISTORY_TABLE_DIALOG:
+ case HISTORY_TABLE_INPUT:
case HISTORY_PAGE_DIALOG:
if (event->data.dom.from != NULL)
g_object_unref (event->data.dom.from);
@@ -3772,6 +3872,11 @@ save_history_for_delete_or_backspace (EHTMLEditorView *view,
if (!webkit_dom_dom_selection_get_range_count (dom_selection))
return;
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+ if (save_history_before_event_in_table (view, range))
+ return;
+
selection = e_html_editor_view_get_selection (view);
ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
@@ -9859,6 +9964,13 @@ e_html_editor_view_update_fonts (EHTMLEditorView *view)
g_string_append (
stylesheet,
+ "td > *"
+ "{\n"
+ " display : inline-block;\n"
+ "}\n");
+
+ g_string_append (
+ stylesheet,
"ul,ol "
"{\n"
" -webkit-padding-start: 7ch; \n"
@@ -10952,6 +11064,52 @@ undo_redo_table_dialog (EHTMLEditorView *view,
}
static void
+undo_redo_table_input (EHTMLEditorView *view,
+ EHTMLEditorViewHistoryEvent *event,
+ gboolean undo)
+{
+ EHTMLEditorSelection *selection;
+ WebKitDOMDocument *document;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *element;
+ WebKitDOMNode *node;
+ WebKitDOMRange *range;
+
+ selection = e_html_editor_view_get_selection (view);
+
+ if (undo)
+ restore_selection_to_history_event_state (view, event->after);
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+ dom_window = webkit_dom_document_get_default_view (document);
+ dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+ if (!webkit_dom_dom_selection_get_range_count (dom_selection))
+ return;
+ range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+ /* Find if writing into table. */
+ node = webkit_dom_range_get_start_container (range, NULL);
+ if (WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (node))
+ element = WEBKIT_DOM_ELEMENT (node);
+ else
+ element = get_parent_block_element (node);
+
+ /* If writing to table we have to create different history event. */
+ if (!WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (element))
+ return;
+
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ undo ? event->data.dom.from : event->data.dom.to,
+ WEBKIT_DOM_NODE (element),
+ NULL);
+
+ e_html_editor_selection_restore (selection);
+}
+
+static void
undo_redo_paste (EHTMLEditorView *view,
EHTMLEditorViewHistoryEvent *event,
gboolean undo)
@@ -11483,6 +11641,9 @@ e_html_editor_view_redo (EHTMLEditorView *view)
case HISTORY_TABLE_DIALOG:
undo_redo_table_dialog (view, event, FALSE);
break;
+ case HISTORY_TABLE_INPUT:
+ undo_redo_table_input (view, event, FALSE);
+ break;
case HISTORY_PAGE_DIALOG:
undo_redo_page_dialog (view, event, FALSE);
break;
@@ -11586,6 +11747,9 @@ e_html_editor_view_undo (EHTMLEditorView *view)
case HISTORY_TABLE_DIALOG:
undo_redo_table_dialog (view, event, TRUE);
break;
+ case HISTORY_TABLE_INPUT:
+ undo_redo_table_input (view, event, TRUE);
+ break;
case HISTORY_PAGE_DIALOG:
undo_redo_page_dialog (view, event, TRUE);
break;
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index 2eae05c..f0d719e 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -104,6 +104,7 @@ enum EHTMLEditorViewHistoryEventType {
HISTORY_START, /* Start of history */
HISTORY_STRIKETHROUGH,
HISTORY_TABLE_DIALOG,
+ HISTORY_TABLE_INPUT,
HISTORY_UNDERLINE,
HISTORY_WRAP
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]