[evolution] Composer - Undo/Redo on operations with selection could be wrong
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Composer - Undo/Redo on operations with selection could be wrong
- Date: Thu, 7 May 2015 11:30:42 +0000 (UTC)
commit 9db95526a64858563ab833236d3f39f61d72a12d
Author: Tomas Popela <tpopela redhat com>
Date: Thu May 7 11:55:40 2015 +0200
Composer - Undo/Redo on operations with selection could be wrong
Previously, i.e. when we selected some text and pressed the Enter the
selected text is removed and later the new line is inserted. In some of
these situations the removal of the selected text was not saved at all that
later led to inconsistent undo/redo operations. Also the HISTORY_AND event
was introduced to add a possibility to distinguish the history events that
are supposed to be processed as one.
e-util/e-html-editor-selection.c | 81 ++++++++++++++++++++++-
e-util/e-html-editor-view.c | 136 ++++++++++++++++++++++++++++++++-----
e-util/e-html-editor-view.h | 1 +
3 files changed, 198 insertions(+), 20 deletions(-)
---
diff --git a/e-util/e-html-editor-selection.c b/e-util/e-html-editor-selection.c
index d3893cc..6bd49be 100644
--- a/e-util/e-html-editor-selection.c
+++ b/e-util/e-html-editor-selection.c
@@ -5282,15 +5282,23 @@ e_html_editor_selection_insert_text (EHTMLEditorSelection *selection,
g_return_if_fail (view != NULL);
if (!e_html_editor_view_is_undo_redo_in_progress (view)) {
+ gboolean collapsed;
+
ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
ev->type = HISTORY_PASTE;
+ collapsed = e_html_editor_selection_is_collapsed (selection);
e_html_editor_selection_get_selection_coordinates (
selection,
&ev->before.start.x,
&ev->before.start.y,
&ev->before.end.x,
&ev->before.end.y);
+
+ if (!collapsed) {
+ ev->before.end.x = ev->before.start.x;
+ ev->before.end.y = ev->before.start.y;
+ }
ev->data.string.from = NULL;
ev->data.string.to = g_strdup (plain_text);
}
@@ -5333,21 +5341,61 @@ e_html_editor_selection_insert_html (EHTMLEditorSelection *selection,
g_return_if_fail (view != NULL);
if (!e_html_editor_view_is_undo_redo_in_progress (view)) {
+ gboolean collapsed;
+
ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
ev->type = HISTORY_INSERT_HTML;
+ collapsed = e_html_editor_selection_is_collapsed (selection);
e_html_editor_selection_get_selection_coordinates (
selection,
&ev->before.start.x,
&ev->before.start.y,
&ev->before.end.x,
&ev->before.end.y);
+ if (!collapsed) {
+ ev->before.end.x = ev->before.start.x;
+ ev->before.end.y = ev->before.start.y;
+ }
ev->data.string.from = NULL;
ev->data.string.to = g_strdup (html_text);
}
command = E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML;
if (e_html_editor_view_get_html_mode (view)) {
+ if (!e_html_editor_selection_is_collapsed (selection)) {
+ EHTMLEditorViewHistoryEvent *ev;
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMRange *range;
+
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_DELETE;
+
+ range = html_editor_selection_get_current_range (selection);
+ fragment = webkit_dom_range_clone_contents (range, NULL);
+ g_object_unref (range);
+ ev->data.fragment = fragment;
+
+ e_html_editor_selection_get_selection_coordinates (
+ selection,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->after.start.x = ev->before.start.x;
+ ev->after.start.y = ev->before.start.y;
+ ev->after.end.x = ev->before.start.x;
+ ev->after.end.y = ev->before.start.y;
+
+ e_html_editor_view_insert_new_history_event (view, ev);
+
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_AND;
+
+ e_html_editor_view_insert_new_history_event (view, ev);
+ }
+
e_html_editor_view_exec_command (view, command, html_text);
if (strstr (html_text, "id=\"-x-evo-selection-start-marker\""))
e_html_editor_selection_restore (selection);
@@ -5495,9 +5543,40 @@ insert_base64_image (EHTMLEditorSelection *selection,
e_html_editor_view_set_changed (view, TRUE);
- if (!e_html_editor_selection_is_collapsed (selection))
+ if (!e_html_editor_selection_is_collapsed (selection)) {
+ EHTMLEditorViewHistoryEvent *ev;
+ WebKitDOMDocumentFragment *fragment;
+ WebKitDOMRange *range;
+
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_DELETE;
+
+ range = html_editor_selection_get_current_range (selection);
+ fragment = webkit_dom_range_clone_contents (range, NULL);
+ g_object_unref (range);
+ ev->data.fragment = fragment;
+
+ e_html_editor_selection_get_selection_coordinates (
+ selection,
+ &ev->before.start.x,
+ &ev->before.start.y,
+ &ev->before.end.x,
+ &ev->before.end.y);
+
+ ev->after.start.x = ev->before.start.x;
+ ev->after.start.y = ev->before.start.y;
+ ev->after.end.x = ev->before.start.x;
+ ev->after.end.y = ev->before.start.y;
+
+ e_html_editor_view_insert_new_history_event (view, ev);
+
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_AND;
+
+ e_html_editor_view_insert_new_history_event (view, ev);
e_html_editor_view_exec_command (
view, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+ }
e_html_editor_selection_save (selection);
selection_start_marker = webkit_dom_document_query_selector (
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index b3439c5..440791e 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -280,6 +280,9 @@ print_history_event (EHTMLEditorViewHistoryEvent *event)
case HISTORY_START:
printf ("HISTORY START\n");
break;
+ case HISTORY_AND:
+ printf ("HISTORY AND\n");
+ break;
default:
printf ("Unknown history type\n");
}
@@ -1811,7 +1814,7 @@ insert_dash_history_event (EHTMLEditorView *view)
diff = event->after.start.x - item->after.start.x;
- /* We need to move the coordinater of the last
+ /* We need to move the coordinate of the last
* event by one character. */
last->after.start.x += diff;
last->after.end.x += diff;
@@ -1827,6 +1830,42 @@ insert_dash_history_event (EHTMLEditorView *view)
}
static void
+insert_delete_event (EHTMLEditorView *view,
+ WebKitDOMRange *range)
+{
+ EHTMLEditorViewHistoryEvent *ev;
+ WebKitDOMDocumentFragment *fragment;
+
+ if (view->priv->undo_redo_in_progress)
+ return;
+
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_DELETE;
+
+ fragment = webkit_dom_range_clone_contents (range, NULL);
+ ev->data.fragment = fragment;
+
+ 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);
+
+ ev->after.start.x = ev->before.start.x;
+ ev->after.start.y = ev->before.start.y;
+ ev->after.end.x = ev->before.start.x;
+ ev->after.end.y = ev->before.start.y;
+
+ e_html_editor_view_insert_new_history_event (view, ev);
+
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_AND;
+
+ e_html_editor_view_insert_new_history_event (view, ev);
+}
+
+static void
emoticon_insert_span (EHTMLEditorView *view,
EEmoticon *emoticon,
WebKitDOMElement *span)
@@ -1866,6 +1905,15 @@ emoticon_insert_span (EHTMLEditorView *view,
}
}
} else {
+ WebKitDOMRange *tmp_range;
+
+ tmp_range = html_editor_view_get_dom_range (view);
+ insert_delete_event (view, tmp_range);
+ g_object_unref (tmp_range);
+
+ e_html_editor_view_exec_command (
+ view, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
+
if (!view->priv->smiley_written) {
if (!e_html_editor_view_is_undo_redo_in_progress (view)) {
ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
@@ -1880,9 +1928,6 @@ emoticon_insert_span (EHTMLEditorView *view,
}
}
- e_html_editor_view_exec_command (
- view, E_HTML_EDITOR_VIEW_COMMAND_DELETE, NULL);
-
e_html_editor_selection_save (selection);
selection_start_marker = webkit_dom_document_get_element_by_id (
@@ -2494,15 +2539,16 @@ body_keypress_event_cb (WebKitDOMElement *element,
return;
}
- if (!webkit_dom_range_get_collapsed (range, NULL)) {
+ if (!webkit_dom_range_get_collapsed (range, NULL))
+ insert_delete_event (view, range);
+
+ if (view->priv->return_key_pressed) {
EHTMLEditorViewHistoryEvent *ev;
- WebKitDOMDocumentFragment *fragment;
+ /* Insert new hiisvent for Return to have the right coordinates.
+ * The fragment will be added later. */
ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
- ev->type = HISTORY_DELETE;
-
- fragment = webkit_dom_range_clone_contents (range, NULL);
- ev->data.fragment = fragment;
+ ev->type = HISTORY_INPUT;
e_html_editor_selection_get_selection_coordinates (
view->priv->selection,
@@ -2595,8 +2641,16 @@ save_history_for_input (EHTMLEditorView *view)
return;
}
- ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
- ev->type = HISTORY_INPUT;
+ if (view->priv->return_key_pressed) {
+ ev = view->priv->history->data;
+ if (ev->type != HISTORY_INPUT) {
+ g_object_unref (dom_selection);
+ return;
+ }
+ } else {
+ ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
+ ev->type = HISTORY_INPUT;
+ }
block_selection_changed_callbacks (view);
@@ -2700,7 +2754,8 @@ save_history_for_input (EHTMLEditorView *view)
unblock_selection_changed_callbacks (view);
ev->data.fragment = fragment;
- e_html_editor_view_insert_new_history_event (view, ev);
+ if (!view->priv->return_key_pressed)
+ e_html_editor_view_insert_new_history_event (view, ev);
}
static gboolean
@@ -3262,15 +3317,22 @@ clipboard_text_received_for_paste_as_text (GtkClipboard *clipboard,
selection = e_html_editor_view_get_selection (view);
if (!e_html_editor_view_is_undo_redo_in_progress (view)) {
+ gboolean collapsed;
+
ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
ev->type = HISTORY_PASTE_AS_TEXT;
+ collapsed = e_html_editor_selection_is_collapsed (selection);
e_html_editor_selection_get_selection_coordinates (
selection,
&ev->before.start.x,
&ev->before.start.y,
&ev->before.end.x,
&ev->before.end.y);
+ if (!collapsed) {
+ ev->before.end.x = ev->before.start.x;
+ ev->before.end.y = ev->before.start.y;
+ }
ev->data.string.from = NULL;
ev->data.string.to = g_strdup (text);
}
@@ -6911,6 +6973,13 @@ html_editor_view_insert_converted_html_into_selection (EHTMLEditorView *view,
g_free (inner_html);
has_selection = !e_html_editor_selection_is_collapsed (selection);
+ if (has_selection) {
+ WebKitDOMRange *range;
+
+ range = html_editor_view_get_dom_range (view);
+ insert_delete_event (view, range);
+ g_object_unref (range);
+ }
citation_level = get_citation_level (WEBKIT_DOM_NODE (selection_end_marker), FALSE);
/* Pasting into the citation */
@@ -11081,6 +11150,12 @@ restore_selection_to_history_event_state (EHTMLEditorView *view,
g_object_unref (dom_selection);
}
+static gboolean
+event_selection_was_collapsed (EHTMLEditorViewHistoryEvent *ev)
+{
+ return (ev->before.start.x == ev->before.end.x) && (ev->before.start.y == ev->before.end.y);
+}
+
static void
undo_delete (EHTMLEditorView *view,
EHTMLEditorViewHistoryEvent *event)
@@ -11276,12 +11351,6 @@ undo_delete (EHTMLEditorView *view,
g_object_unref (dom_selection);
}
-static gboolean
-event_selection_was_collapsed (EHTMLEditorViewHistoryEvent *ev)
-{
- return (ev->before.start.x == ev->before.end.x) && (ev->before.start.y == ev->before.end.y);
-}
-
static void
redo_delete (EHTMLEditorView *view,
EHTMLEditorViewHistoryEvent *event)
@@ -12392,6 +12461,13 @@ e_html_editor_view_redo (EHTMLEditorView *view)
break;
case HISTORY_INPUT:
undo_delete (view, event);
+ {
+ WebKitDOMRange *range;
+
+ range = html_editor_view_get_dom_range (view);
+ html_editor_view_check_magic_smileys (view, range);
+ g_object_unref (range);
+ }
break;
case HISTORY_REMOVE_LINK:
undo_redo_remove_link (view, event, FALSE);
@@ -12440,10 +12516,22 @@ e_html_editor_view_redo (EHTMLEditorView *view)
case HISTORY_UNQUOTE:
undo_redo_unquote (view, event, FALSE);
break;
+ case HISTORY_AND:
+ g_warning ("Unhandled HISTORY_AND event!");
+ break;
default:
return;
}
+ if (history->prev->prev) {
+ event = history->prev->prev->data;
+ if (event->type == HISTORY_AND) {
+ view->priv->history = history->prev->prev;
+ e_html_editor_view_redo (view);
+ return;
+ }
+ }
+
view->priv->history = view->priv->history->prev;
d (print_history (view));
@@ -12543,10 +12631,20 @@ e_html_editor_view_undo (EHTMLEditorView *view)
case HISTORY_UNQUOTE:
undo_redo_unquote (view, event, TRUE);
break;
+ case HISTORY_AND:
+ g_warning ("Unhandled HISTORY_AND event!");
+ break;
default:
return;
}
+ event = history->next->data;
+ if (event->type == HISTORY_AND) {
+ view->priv->history = history->next->next;
+ e_html_editor_view_undo (view);
+ return;
+ }
+
if (history->next)
view->priv->history = view->priv->history->next;
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index 83d86f6..bd61513 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -85,6 +85,7 @@ struct _EHTMLEditorViewClass {
enum EHTMLEditorViewHistoryEventType {
HISTORY_ALIGNMENT,
+ HISTORY_AND,
HISTORY_BLOCK_FORMAT,
HISTORY_BLOCKQUOTE,
HISTORY_BOLD,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]