[evolution/wip/webkit2] 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/wip/webkit2] EHTMLEditorView - Implement undo and redo on text operations in table
- Date: Wed, 22 Apr 2015 13:17:57 +0000 (UTC)
commit 727652068d330ceeb234ec6e4b8cb8ca15f8eb95
Author: Tomas Popela <tpopela redhat com>
Date: Wed Apr 22 14:00:17 2015 +0200
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-view.c | 7 +
web-extensions/e-html-editor-history-event.h | 1 +
.../e-html-editor-selection-dom-functions.c | 7 +
web-extensions/e-html-editor-undo-redo-manager.c | 50 ++++++++
web-extensions/e-html-editor-view-dom-functions.c | 119 +++++++++++++++++++-
5 files changed, 178 insertions(+), 6 deletions(-)
---
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 5da9b4e..9417e7e 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -2510,6 +2510,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"
diff --git a/web-extensions/e-html-editor-history-event.h b/web-extensions/e-html-editor-history-event.h
index 6050765..872f2b5 100644
--- a/web-extensions/e-html-editor-history-event.h
+++ b/web-extensions/e-html-editor-history-event.h
@@ -52,6 +52,7 @@ enum EHTMLEditorHistoryEventType {
HISTORY_START, /* Start of history */
HISTORY_STRIKETHROUGH,
HISTORY_TABLE_DIALOG,
+ HISTORY_TABLE_INPUT,
HISTORY_UNDERLINE,
HISTORY_WRAP
};
diff --git a/web-extensions/e-html-editor-selection-dom-functions.c
b/web-extensions/e-html-editor-selection-dom-functions.c
index 9ff7c6c..c3da54d 100644
--- a/web-extensions/e-html-editor-selection-dom-functions.c
+++ b/web-extensions/e-html-editor-selection-dom-functions.c
@@ -1459,6 +1459,13 @@ dom_selection_save (WebKitDOMDocument *document)
webkit_dom_node_get_next_sibling (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 {
/* Insert the selection marker on the right position in
* an empty paragraph in the quoted content */
diff --git a/web-extensions/e-html-editor-undo-redo-manager.c
b/web-extensions/e-html-editor-undo-redo-manager.c
index 02847ad..d298e38 100644
--- a/web-extensions/e-html-editor-undo-redo-manager.c
+++ b/web-extensions/e-html-editor-undo-redo-manager.c
@@ -257,6 +257,7 @@ print_history_event (EHTMLEditorHistoryEvent *event)
case HISTORY_IMAGE_DIALOG:
case HISTORY_CELL_DIALOG:
case HISTORY_TABLE_DIALOG:
+ case HISTORY_TABLE_DIALOG:
case HISTORY_PAGE_DIALOG:
print_node_inner_html (event->data.dom.from);
print_node_inner_html (event->data.dom.to);
@@ -930,6 +931,48 @@ undo_redo_table_dialog (WebKitDOMDocument *document,
}
static void
+undo_redo_table_input (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ EHTMLEditorHistoryEvent *event,
+ gboolean undo)
+{
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *element;
+ WebKitDOMNode *node;
+ WebKitDOMRange *range;
+
+ if (undo)
+ restore_selection_to_history_event_state (document, event->after);
+
+ 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);
+
+ dom_selection_restore (document);
+}
+
+static void
undo_redo_paste (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension,
EHTMLEditorHistoryEvent *event,
@@ -1420,6 +1463,7 @@ free_history_event_content (EHTMLEditorHistoryEvent *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);
@@ -1684,6 +1728,9 @@ e_html_editor_undo_redo_manager_undo (EHTMLEditorUndoRedoManager *manager)
case HISTORY_TABLE_DIALOG:
undo_redo_table_dialog (document, extension, event, TRUE);
break;
+ case HISTORY_TABLE_INPUT:
+ undo_redo_table_input (document, extension, event, TRUE);
+ break;
case HISTORY_PAGE_DIALOG:
undo_redo_page_dialog (document, extension, event, TRUE);
break;
@@ -1795,6 +1842,9 @@ e_html_editor_undo_redo_manager_redo (EHTMLEditorUndoRedoManager *manager)
case HISTORY_TABLE_DIALOG:
undo_redo_table_dialog (document, extension, event, FALSE);
break;
+ case HISTORY_TABLE_INPUT:
+ undo_redo_table_input (document, extension, event, FALSE);
+ break;
case HISTORY_PAGE_DIALOG:
undo_redo_page_dialog (document, extension, event, FALSE);
break;
diff --git a/web-extensions/e-html-editor-view-dom-functions.c
b/web-extensions/e-html-editor-view-dom-functions.c
index 80ddf98..73009ef 100644
--- a/web-extensions/e-html-editor-view-dom-functions.c
+++ b/web-extensions/e-html-editor-view-dom-functions.c
@@ -1623,13 +1623,15 @@ surround_text_with_paragraph_if_needed (WebKitDOMDocument *document,
{
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 = dom_put_node_into_paragraph (document, extension, node, TRUE);
if (WEBKIT_DOM_IS_HTML_BR_ELEMENT (next_sibling))
@@ -1668,6 +1670,50 @@ body_keydown_event_cb (WebKitDOMElement *element,
e_html_editor_web_extension_set_dont_save_history_in_body_input (extension, TRUE);
}
+static gboolean
+save_history_before_event_in_table (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension,
+ 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)) {
+ EHTMLEditorUndoRedoManager *manager;
+ EHTMLEditorHistoryEvent *ev;
+
+ ev = g_new0 (EHTMLEditorHistoryEvent, 1);
+ ev->type = HISTORY_TABLE_INPUT;
+
+ if (block) {
+ dom_selection_save (document);
+ ev->data.dom.from = webkit_dom_node_clone_node (WEBKIT_DOM_NODE (block), TRUE);
+ dom_selection_restore (document);
+ } else
+ ev->data.dom.from = NULL;
+
+ dom_selection_get_coordinates (
+ document,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ e_html_editor_undo_redo_manager_insert_history_event (manager, ev);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
body_keypress_event_cb (WebKitDOMElement *element,
WebKitDOMUIEvent *event,
@@ -1693,6 +1739,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 (document, extension, range))
+ return;
+
if (!webkit_dom_range_get_collapsed (range, NULL)) {
EHTMLEditorHistoryEvent *ev;
EHTMLEditorUndoRedoManager *manager;
@@ -1715,6 +1764,57 @@ body_keypress_event_cb (WebKitDOMElement *element,
}
}
+static gboolean
+save_history_after_event_in_table (WebKitDOMDocument *document,
+ EHTMLEditorWebExtension *extension)
+{
+ EHTMLEditorHistoryEvent *ev;
+ EHTMLEditorUndoRedoManager *manager;
+ WebKitDOMDOMWindow *dom_window;
+ WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *element;
+ WebKitDOMNode *node;
+ WebKitDOMRange *range;
+
+ 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);
+
+ manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+ /* If writing to table we have to create different history event. */
+ if (WEBKIT_DOM_IS_HTML_TABLE_CELL_ELEMENT (element)) {
+ ev = e_html_editor_undo_redo_manager_get_current_history_event (manager);
+ if (ev->type != HISTORY_TABLE_INPUT)
+ return FALSE;
+ } else
+ return FALSE;
+
+ dom_selection_save (document);
+
+ dom_selection_get_coordinates (
+ document,
+ &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);
+
+ dom_selection_restore (document);
+
+ return TRUE;
+}
+
static void
save_history_for_input (WebKitDOMDocument *document,
EHTMLEditorWebExtension *extension)
@@ -1814,10 +1914,12 @@ body_input_event_cb (WebKitDOMElement *element,
return;
}
- if (!e_html_editor_web_extension_get_dont_save_history_in_body_input (extension))
- save_history_for_input (document, extension);
- else
- dom_force_spell_check_for_current_paragraph (document, extension);
+ if (!save_history_after_event_in_table (document, extension)) {
+ if (!e_html_editor_web_extension_get_dont_save_history_in_body_input (extension))
+ save_history_for_input (document, extension);
+ else
+ dom_force_spell_check_for_current_paragraph (document, extension);
+ }
/* Don't try to look for smileys if we are deleting text. */
if (!e_html_editor_web_extension_get_dont_save_history_in_body_input (extension))
@@ -1866,7 +1968,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 (html_mode) {
WebKitDOMElement *parent = webkit_dom_node_get_parent_element (node);
@@ -6653,6 +6755,11 @@ save_history_for_delete_or_backspace (WebKitDOMDocument *document,
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 (document, extension, range))
+ return;
+
ev = g_new0 (EHTMLEditorHistoryEvent, 1);
ev->type = HISTORY_DELETE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]