[evolution] EHTMLEditorView - Improve the writing into quoted content



commit 61e260ac069b6c26c370d66a54c4e307c50ab922
Author: Tomas Popela <tpopela redhat com>
Date:   Thu Jun 19 15:15:56 2014 +0200

    EHTMLEditorView - Improve the writing into quoted content
    
    After this change when we start writing into quoted content it will
    automatically rewrap the paragraph and reinserts the quote marks if the
    block format is set to Normal. Also when the caret is in the beginning
    of the quoted line and BackSpace is pressed the quoted content is
    tooked out from the quote and inserted into body.

 e-util/e-html-editor-view.c |  418 +++++++++++++++++++++++++++++++++++--------
 1 files changed, 341 insertions(+), 77 deletions(-)
---
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 25b9bee..8467f12 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -83,6 +83,7 @@ struct _EHTMLEditorViewPrivate {
        GSettings *aliasing_settings;
 
        gboolean convertor_insert;
+       gboolean had_selection_before_key_press;
 
        WebKitWebView *convertor_web_view;
 
@@ -404,6 +405,104 @@ e_html_editor_view_force_spell_check (EHTMLEditorView *view)
        refresh_spell_check (view, TRUE);
 }
 
+static gint
+get_citation_level (WebKitDOMNode *node,
+                    gboolean set_plaintext_quoted)
+{
+       WebKitDOMNode *parent = node;
+       gint level = 0;
+
+       while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent) &&
+                   webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (parent), "type")) {
+                       level++;
+
+                       if (set_plaintext_quoted) {
+                               element_add_class (
+                                       WEBKIT_DOM_ELEMENT (parent),
+                                       "-x-evo-plaintext-quoted");
+                       }
+               }
+
+               parent = webkit_dom_node_get_parent_node (parent);
+       }
+
+       return level;
+}
+
+static WebKitDOMElement *
+insert_new_line_into_citation (EHTMLEditorView *view,
+                               const gchar *html_to_insert)
+{
+       gboolean html_mode, ret_val;
+       EHTMLEditorSelection *selection;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *element, *paragraph = NULL;
+       WebKitDOMNode *caret;
+
+       html_mode = e_html_editor_view_get_html_mode (view);
+       selection = e_html_editor_view_get_selection (view);
+
+       ret_val = e_html_editor_view_exec_command (
+               view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT, NULL);
+
+       if (!ret_val)
+               return NULL;
+
+       document = webkit_web_view_get_dom_document (
+                       WEBKIT_WEB_VIEW (view));
+
+       element = webkit_dom_document_query_selector (
+               document, "body>br", NULL);
+
+       if (!element)
+               return NULL;
+
+       if (!html_mode) {
+               WebKitDOMNode *next_sibling;
+
+               next_sibling = webkit_dom_node_get_next_sibling (
+                       WEBKIT_DOM_NODE (element));
+
+               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling)) {
+                       e_html_editor_view_quote_plain_text_element (
+                               view, WEBKIT_DOM_ELEMENT (next_sibling));
+
+                       e_html_editor_view_force_spell_check (view);
+               }
+       }
+
+       caret = e_html_editor_selection_get_caret_position_node (document);
+
+       paragraph = e_html_editor_selection_get_paragraph_element (
+               selection, document, -1, 0);
+
+       if (html_to_insert && *html_to_insert)
+               webkit_dom_html_element_set_inner_html (
+                       WEBKIT_DOM_HTML_ELEMENT (paragraph),
+                       html_to_insert,
+                       NULL);
+       else
+               webkit_dom_html_element_set_inner_text (
+                       WEBKIT_DOM_HTML_ELEMENT (paragraph),
+                       UNICODE_ZERO_WIDTH_SPACE,
+                       NULL);
+
+       webkit_dom_node_append_child (WEBKIT_DOM_NODE (paragraph), caret, NULL);
+
+       webkit_dom_node_insert_before (
+               webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+               WEBKIT_DOM_NODE (paragraph),
+               WEBKIT_DOM_NODE (element),
+               NULL);
+
+       remove_node (WEBKIT_DOM_NODE (element));
+
+       e_html_editor_selection_restore_caret_position (selection);
+
+       return paragraph;
+}
+
 static void
 body_input_event_cb (WebKitDOMElement *element,
                      WebKitDOMEvent *event,
@@ -501,6 +600,128 @@ body_input_event_cb (WebKitDOMElement *element,
                                e_html_editor_view_get_selection (view));
                }
        }
+
+       /* Writing into quoted content */
+       if (!view->priv->html_mode && !view->priv->had_selection_before_key_press) {
+               gint citation_level, length, word_wrap_length;
+               EHTMLEditorSelection *selection;
+               WebKitDOMElement *element;
+               WebKitDOMDocument *document;
+               WebKitDOMNode *parent;
+
+               document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+
+               selection = e_html_editor_view_get_selection (view);
+               word_wrap_length = e_html_editor_selection_get_word_wrap_length (selection);
+
+               element = webkit_dom_document_query_selector (
+                       document, "span#-x-evo-selection-start-marker", NULL);
+               if (element)
+                       return;
+
+               e_html_editor_selection_save (selection);
+               element = webkit_dom_document_query_selector (
+                       document, "span#-x-evo-selection-start-marker", NULL);
+
+               /* If the selection was not saved, move it into the first child of body */
+               if (!element) {
+                       WebKitDOMHTMLElement *body;
+
+                       body = webkit_dom_document_get_body (document);
+                       element = webkit_dom_document_create_element (
+                               document, "SPAN", NULL);
+                       webkit_dom_element_set_id (
+                               element, "-x-evo-selection-end-marker");
+                       webkit_dom_node_insert_before (
+                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
+                               WEBKIT_DOM_NODE (element),
+                               webkit_dom_node_get_first_child (
+                                       webkit_dom_node_get_first_child (
+                                               WEBKIT_DOM_NODE (body))),
+                               NULL);
+                       element = webkit_dom_document_create_element (
+                               document, "SPAN", NULL);
+                       webkit_dom_element_set_id (
+                               element, "-x-evo-selection-start-marker");
+                       webkit_dom_node_insert_before (
+                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
+                               WEBKIT_DOM_NODE (element),
+                               webkit_dom_node_get_first_child (
+                                       webkit_dom_node_get_first_child (
+                                               WEBKIT_DOM_NODE (body))),
+                               NULL);
+               }
+
+               /* We have to process elements only inside normal block */
+               parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
+               if (WEBKIT_DOM_IS_HTML_PRE_ELEMENT (parent)) {
+                       e_html_editor_selection_restore (selection);
+                       return;
+               }
+
+               citation_level = get_citation_level (WEBKIT_DOM_NODE (element), FALSE);
+               length = word_wrap_length - 2 * citation_level;
+
+               if (element && citation_level > 0) {
+                       WebKitDOMElement *block;
+                       gboolean remove_quoting = FALSE;
+
+                       block = webkit_dom_node_get_parent_element (
+                               WEBKIT_DOM_NODE (element));
+                       if (webkit_dom_element_query_selector (
+                               WEBKIT_DOM_ELEMENT (block), ".-x-evo-quoted", NULL)) {
+                               WebKitDOMNode *prev_sibling;
+                               WebKitDOMElement *selection_end_marker;
+
+                               selection_end_marker = webkit_dom_document_query_selector (
+                                       document, "span#-x-evo-selection-end-marker", NULL);
+                               prev_sibling = webkit_dom_node_get_previous_sibling (
+                                       WEBKIT_DOM_NODE (selection_end_marker));
+
+                               if (WEBKIT_DOM_IS_ELEMENT (prev_sibling))
+                                       remove_quoting = element_has_class (
+                                               WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-quoted");
+                       }
+
+                       if (element_has_class (block, "-x-evo-temp-text-wrapper"))
+                               block = webkit_dom_node_get_parent_element (
+                                       WEBKIT_DOM_NODE (block));
+
+                       /* Wrap and quote the line */
+                       if (!remove_quoting) {
+                               remove_quoting_from_element (block);
+
+                               block = e_html_editor_selection_wrap_paragraph_length (
+                                       selection, block, length);
+                               webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
+                               block = e_html_editor_view_quote_plain_text_element (view, block);
+                               element = webkit_dom_document_query_selector (
+                                       document, "span#-x-evo-selection-start-marker", NULL);
+                               if (!element) {
+                                       WebKitDOMElement *marker;
+
+                                       marker = webkit_dom_document_create_element (
+                                               document, "SPAN", NULL);
+                                       webkit_dom_element_set_id (
+                                               marker, "-x-evo-selection-start-marker");
+                                       webkit_dom_node_append_child (
+                                               WEBKIT_DOM_NODE (block),
+                                               WEBKIT_DOM_NODE (marker),
+                                               NULL);
+                                       marker = webkit_dom_document_create_element (
+                                               document, "SPAN", NULL);
+                                       webkit_dom_element_set_id (
+                                               marker, "-x-evo-selection-end-marker");
+                                       webkit_dom_node_append_child (
+                                               WEBKIT_DOM_NODE (block),
+                                               WEBKIT_DOM_NODE (marker),
+                                               NULL);
+                               }
+                       }
+                       e_html_editor_view_force_spell_check (view);
+               }
+               e_html_editor_selection_restore (selection);
+       }
 }
 
 static void
@@ -1713,56 +1934,6 @@ html_editor_view_button_release_event (GtkWidget *widget,
 }
 
 static gboolean
-insert_new_line_into_citation (EHTMLEditorView *view)
-{
-       EHTMLEditorSelection *selection;
-       gboolean html_mode, ret_val;
-
-       html_mode = e_html_editor_view_get_html_mode (view);
-       selection = e_html_editor_view_get_selection (view);
-
-       ret_val = e_html_editor_view_exec_command (
-               view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_NEW_LINE_IN_QUOTED_CONTENT, NULL);
-
-       if (ret_val && !html_mode) {
-               WebKitDOMElement *element;
-               WebKitDOMDocument *document;
-               WebKitDOMNode *next_sibling;
-
-               document = webkit_web_view_get_dom_document (
-                       WEBKIT_WEB_VIEW (view));
-
-               element = webkit_dom_document_query_selector (
-                       document, "body>br", NULL);
-
-               next_sibling = webkit_dom_node_get_next_sibling (
-                       WEBKIT_DOM_NODE (element));
-
-               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (next_sibling)) {
-                       /* Quote content */
-                       next_sibling = WEBKIT_DOM_NODE (
-                               e_html_editor_view_quote_plain_text_element (
-                                       view, WEBKIT_DOM_ELEMENT (next_sibling)));
-                       /* Renew spellcheck */
-                       e_html_editor_view_force_spell_check (view);
-                       /* Insert caret node on right position */
-                       webkit_dom_node_insert_before (
-                               webkit_dom_node_get_parent_node (
-                                       WEBKIT_DOM_NODE (element)),
-                               e_html_editor_selection_get_caret_position_node (
-                                       document),
-                               WEBKIT_DOM_NODE (element),
-                               NULL);
-                       /* Restore caret position */
-                       e_html_editor_selection_restore_caret_position (
-                               selection);
-               }
-       }
-
-       return ret_val;
-}
-
-static gboolean
 prevent_from_deleting_last_element_in_body (EHTMLEditorView *view)
 {
        gboolean ret_val = FALSE;
@@ -1793,6 +1964,101 @@ prevent_from_deleting_last_element_in_body (EHTMLEditorView *view)
 }
 
 static gboolean
+change_quoted_block_to_normal (EHTMLEditorView *view)
+{
+       gint citation_level, success = FALSE;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *selection_start_marker, *selection_end_marker, *block;
+
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+
+       selection_start_marker = webkit_dom_document_query_selector (
+               document, "span#-x-evo-selection-start-marker", NULL);
+       selection_end_marker = webkit_dom_document_query_selector (
+               document, "span#-x-evo-selection-end-marker", NULL);
+
+       if (!selection_start_marker || !selection_end_marker)
+               return FALSE;
+
+       block = webkit_dom_node_get_parent_element (
+               WEBKIT_DOM_NODE (selection_start_marker));
+
+       citation_level = get_citation_level (
+               WEBKIT_DOM_NODE (selection_start_marker), FALSE);
+
+       if (selection_start_marker && citation_level > 0) {
+               if (element_has_class (block, "-x-evo-temp-text-wrapper"))
+                       block = webkit_dom_node_get_parent_element (
+                               WEBKIT_DOM_NODE (block));
+
+               if (webkit_dom_element_query_selector (
+                       WEBKIT_DOM_ELEMENT (block), ".-x-evo-quoted", NULL)) {
+
+                       WebKitDOMNode *prev_sibling;
+
+                       webkit_dom_node_normalize (WEBKIT_DOM_NODE (block));
+
+                       prev_sibling = webkit_dom_node_get_previous_sibling (
+                               WEBKIT_DOM_NODE (selection_end_marker));
+
+                       if (WEBKIT_DOM_IS_ELEMENT (prev_sibling))
+                               success = element_has_class (
+                                       WEBKIT_DOM_ELEMENT (prev_sibling), "-x-evo-quoted");
+               }
+
+               if (view->priv->html_mode)
+                       success = WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (
+                               webkit_dom_node_get_parent_element (
+                                       WEBKIT_DOM_NODE (block)));
+
+               if (success) {
+                       gchar *inner_html;
+                       WebKitDOMElement *paragraph;
+
+                       inner_html = webkit_dom_html_element_get_inner_html (
+                               WEBKIT_DOM_HTML_ELEMENT (block));
+                       webkit_dom_element_set_id (
+                               WEBKIT_DOM_ELEMENT (block), "-x-evo-to-remove");
+
+                       paragraph = insert_new_line_into_citation (view, inner_html);
+                       g_free (inner_html);
+
+                       if (view->priv->html_mode) {
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (paragraph),
+                                       WEBKIT_DOM_NODE (selection_start_marker),
+                                       webkit_dom_node_get_first_child (
+                                               WEBKIT_DOM_NODE (paragraph)),
+                                       NULL);
+                               webkit_dom_node_insert_before (
+                                       WEBKIT_DOM_NODE (paragraph),
+                                       WEBKIT_DOM_NODE (selection_end_marker),
+                                       webkit_dom_node_get_first_child (
+                                               WEBKIT_DOM_NODE (paragraph)),
+                                       NULL);
+
+                       }
+
+                       remove_quoting_from_element (paragraph);
+                       remove_wrapping_from_element (paragraph);
+
+                       if (block)
+                               remove_node (WEBKIT_DOM_NODE (block));
+                       block = webkit_dom_document_get_element_by_id (
+                               document, "-x-evo-to-remove");
+                       if (block)
+                               remove_node (WEBKIT_DOM_NODE (block));
+                       remove_node_if_empty (
+                               webkit_dom_node_get_next_sibling (
+                                       WEBKIT_DOM_NODE (paragraph)));
+                       e_html_editor_view_force_spell_check (view);
+               }
+       }
+
+       return success;
+}
+
+static gboolean
 html_editor_view_key_press_event (GtkWidget *widget,
                                   GdkEventKey *event)
 {
@@ -1816,14 +2082,27 @@ html_editor_view_key_press_event (GtkWidget *widget,
                 * not break the citation automatically, so we need to use
                 * the special command to do it. */
                if (e_html_editor_selection_is_citation (selection))
-                       return insert_new_line_into_citation (view);
+                       return (insert_new_line_into_citation (view, "")) ? TRUE : FALSE;
        }
 
-       /* BackSpace in indented block decrease indent level by one */
        if (event->keyval == GDK_KEY_BackSpace) {
                EHTMLEditorSelection *selection;
 
                selection = e_html_editor_view_get_selection (view);
+
+               /* BackSpace pressed in the beginning of quoted content changes
+                * format to normal and inserts text into body */
+               if (g_strcmp0 (e_html_editor_selection_get_string (selection), "") == 0) {
+                       e_html_editor_selection_save (selection);
+                       if (change_quoted_block_to_normal (view)) {
+                               e_html_editor_selection_restore (selection);
+                               return TRUE;
+                       }
+                       e_html_editor_selection_restore (selection);
+               } else
+                       view->priv->had_selection_before_key_press = TRUE;
+
+               /* BackSpace in indented block decrease indent level by one */
                if (e_html_editor_selection_is_indented (selection)) {
                        WebKitDOMElement *caret;
 
@@ -1942,6 +2221,8 @@ html_editor_view_key_release_event (GtkWidget *widget,
        range = html_editor_view_get_dom_range (view);
        selection = e_html_editor_view_get_selection (view);
 
+       view->priv->had_selection_before_key_press = FALSE;
+
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
 
        if (view->priv->magic_smileys && view->priv->html_mode)
@@ -3001,6 +3282,7 @@ e_html_editor_view_init (EHTMLEditorView *view)
 
        g_free (comma_separated);
 
+       view->priv->had_selection_before_key_press = FALSE;
        view->priv->convertor_insert = FALSE;
 
        view->priv->convertor_web_view =
@@ -3662,31 +3944,6 @@ quote_plain_text_recursive (WebKitDOMDocument *document,
        }
 }
 
-static gint
-get_citation_level (WebKitDOMNode *node,
-                    gboolean set_plaintext_quoted)
-{
-       WebKitDOMNode *parent = node;
-       gint level = 0;
-
-       while (parent && !WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
-               if (WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (parent) &&
-                   webkit_dom_element_has_attribute (WEBKIT_DOM_ELEMENT (parent), "type")) {
-                       level++;
-
-                       if (set_plaintext_quoted) {
-                               element_add_class (
-                                       WEBKIT_DOM_ELEMENT (parent),
-                                       "-x-evo-plaintext-quoted");
-                       }
-               }
-
-               parent = webkit_dom_node_get_parent_node (parent);
-       }
-
-       return level;
-}
-
 WebKitDOMElement *
 e_html_editor_view_quote_plain_text_element (EHTMLEditorView *view,
                                              WebKitDOMElement *element)
@@ -5955,6 +6212,13 @@ e_html_editor_view_update_fonts (EHTMLEditorView *view)
                "  color: #737373 !important;\n"
                "}\n");
 
+       g_string_append (
+               stylesheet,
+               ".-x-evo-quoted "
+               "{\n"
+               "  -webkit-user-select: none;\n"
+               "}\n");
+
        g_string_append_printf (
                stylesheet,
                ".-x-evo-quote-character "


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]