[evolution/webkit-composer] Implement indentation of elements when no selection is active in composer.
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/webkit-composer] Implement indentation of elements when no selection is active in composer.
- Date: Tue, 24 Sep 2013 14:50:03 +0000 (UTC)
commit 7909d14efe20e40ceb118865c8fcc3a48c705e02
Author: Tomas Popela <tpopela redhat com>
Date: Tue Sep 24 16:24:01 2013 +0200
Implement indentation of elements when no selection is active in composer.
e-util/e-editor-selection.c | 225 +++++++++++++++++++++++++++++++++++++++++--
e-util/e-editor-widget.c | 180 +++++++++++++++++++++++++---------
2 files changed, 347 insertions(+), 58 deletions(-)
---
diff --git a/e-util/e-editor-selection.c b/e-util/e-editor-selection.c
index 4b8ee8a..3d976dc 100644
--- a/e-util/e-editor-selection.c
+++ b/e-util/e-editor-selection.c
@@ -1718,14 +1718,68 @@ e_editor_selection_indent (EEditorSelection *selection)
editor_widget = e_editor_selection_ref_editor_widget (selection);
g_return_if_fail (editor_widget != NULL);
- command = E_EDITOR_WIDGET_COMMAND_INDENT;
- e_editor_widget_exec_command (editor_widget, command, NULL);
+ if (g_strcmp0 (e_editor_selection_get_string (selection), "") == 0) {
+ WebKitDOMDocument *document;
+ WebKitDOMRange *range;
+ WebKitDOMNode *node;
+ WebKitDOMNode *clone;
+ WebKitDOMElement *element;
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
+
+ e_editor_selection_save_caret_position (selection);
+
+ range = editor_selection_get_current_range (selection);
+ if (!range) {
+ g_object_unref (editor_widget);
+ return;
+ }
+
+ node = webkit_dom_range_get_end_container (range, NULL);
+ if (!WEBKIT_DOM_IS_ELEMENT (node))
+ node = WEBKIT_DOM_NODE (webkit_dom_node_get_parent_element (node));
+
+ element = webkit_dom_node_get_parent_element (node);
+
+ clone = webkit_dom_node_clone_node (node, TRUE);
+ element = webkit_dom_document_create_element (document, "BLOCKQUOTE", NULL);
+ element_add_class (element, "-x-evo-indented");
+ /* We don't want vertical space bellow and above blockquote inserted by
+ * WebKit's User Agent Stylesheet. We have to override it through style attribute. */
+ webkit_dom_element_set_attribute (
+ element,
+ "style",
+ "-webkit-margin-before: 0em; -webkit-margin-after: 0em;",
+ NULL);
+
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (element),
+ clone,
+ NULL);
+
+ webkit_dom_node_replace_child (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (element),
+ node,
+ NULL);
+
+ e_editor_selection_restore_caret_position (selection);
+ } else {
+ command = E_EDITOR_WIDGET_COMMAND_INDENT;
+ e_editor_widget_exec_command (editor_widget, command, NULL);
+ }
g_object_unref (editor_widget);
g_object_notify (G_OBJECT (selection), "indented");
}
+static gboolean
+is_caret_position_node (WebKitDOMNode *node)
+{
+ return element_has_id (WEBKIT_DOM_ELEMENT (node), "-x-evo-caret-position");
+}
+
/**
* e_editor_selection_unindent:
* @selection: an #EEditorSelection
@@ -1743,8 +1797,148 @@ e_editor_selection_unindent (EEditorSelection *selection)
editor_widget = e_editor_selection_ref_editor_widget (selection);
g_return_if_fail (editor_widget != NULL);
- command = E_EDITOR_WIDGET_COMMAND_OUTDENT;
- e_editor_widget_exec_command (editor_widget, command, NULL);
+ if (g_strcmp0 (e_editor_selection_get_string (selection), "") == 0) {
+ WebKitDOMDocument *document;
+ WebKitDOMElement *element;
+ WebKitDOMElement *prev_blockquote = NULL;
+ WebKitDOMElement *next_blockquote = NULL;
+ WebKitDOMNode *node;
+ WebKitDOMNode *clone;
+ WebKitDOMNode *node_clone;
+ WebKitDOMNode *caret_node;
+ WebKitDOMRange *range;
+ gboolean before_node = TRUE;
+ gboolean reinsert_caret_position = FALSE;
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
+
+ e_editor_selection_save_caret_position (selection);
+
+ range = editor_selection_get_current_range (selection);
+ if (!range) {
+ g_object_unref (editor_widget);
+ return;
+ }
+
+ node = webkit_dom_range_get_end_container (range, NULL);
+ if (!WEBKIT_DOM_IS_ELEMENT (node))
+ node = WEBKIT_DOM_NODE (webkit_dom_node_get_parent_element (node));
+
+ element = webkit_dom_node_get_parent_element (node);
+
+ if (!element || !element_has_tag (element, "blockquote")) {
+ return;
+ }
+
+ clone = WEBKIT_DOM_NODE (webkit_dom_node_clone_node (WEBKIT_DOM_NODE (element), TRUE));
+
+ /* Look if we have previous siblings, if so, we have to
+ * create new blockquote that will include them */
+ if (webkit_dom_node_get_previous_sibling (node)) {
+ prev_blockquote = webkit_dom_document_create_element (document, "BLOCKQUOTE", NULL);
+ /* We don't want vertical space bellow and above blockquote inserted by
+ * WebKit's User Agent Stylesheet. We have to override it through style attribute. */
+ element_add_class (prev_blockquote, "-x-evo-indented");
+ webkit_dom_element_set_attribute (
+ prev_blockquote,
+ "style",
+ "-webkit-margin-before: 0em; -webkit-margin-after: 0em;",
+ NULL);
+ }
+
+ /* Look if we have next siblings, if so, we have to
+ * create new blockquote that will include them */
+ if (webkit_dom_node_get_next_sibling (node)) {
+ next_blockquote = webkit_dom_document_create_element (document, "BLOCKQUOTE", NULL);
+ /* We don't want vertical space bellow and above blockquote inserted by
+ * WebKit's User Agent Stylesheet. We have to override it through style attribute. */
+ element_add_class (next_blockquote, "-x-evo-indented");
+ webkit_dom_element_set_attribute (
+ next_blockquote,
+ "style",
+ "-webkit-margin-before: 0em; -webkit-margin-after: 0em;",
+ NULL);
+ }
+
+ /* Copy nodes that are before / after the element that we want to unindent */
+ while (webkit_dom_node_has_child_nodes (clone)) {
+ WebKitDOMNode *child;
+
+ child = webkit_dom_node_get_first_child (clone);
+
+ if (is_caret_position_node (child)) {
+ reinsert_caret_position = TRUE;
+ caret_node = webkit_dom_node_clone_node (child, TRUE);
+ webkit_dom_node_remove_child (clone, child, NULL);
+ continue;
+ }
+
+ if (webkit_dom_node_is_equal_node (child, node)) {
+ before_node = FALSE;
+ node_clone = webkit_dom_node_clone_node (child, TRUE);
+ webkit_dom_node_remove_child (clone, child, NULL);
+ continue;
+ }
+
+ webkit_dom_node_append_child (
+ before_node ?
+ WEBKIT_DOM_NODE (prev_blockquote) :
+ WEBKIT_DOM_NODE (next_blockquote),
+ child,
+ NULL);
+
+ webkit_dom_node_remove_child (clone, child, NULL);
+ }
+
+ /* Insert blockqoute with nodes that were before the element that we want to unindent */
+ if (prev_blockquote) {
+ if (webkit_dom_node_has_child_nodes (WEBKIT_DOM_NODE (prev_blockquote))) {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ WEBKIT_DOM_NODE (prev_blockquote),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+ }
+
+ /* Reinsert the caret position */
+ if (reinsert_caret_position) {
+ webkit_dom_node_insert_before (
+ node_clone,
+ caret_node,
+ webkit_dom_node_get_first_child (node_clone),
+ NULL);
+ }
+
+ /* Insert the unindented element */
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ node_clone,
+ WEBKIT_DOM_NODE (element),
+ NULL);
+
+ /* Insert blockqoute with nodes that were after the element that we want to unindent */
+ if (next_blockquote) {
+ if (webkit_dom_node_has_child_nodes (WEBKIT_DOM_NODE (prev_blockquote))) {
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ WEBKIT_DOM_NODE (next_blockquote),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+ }
+
+ /* Remove old blockquote */
+ webkit_dom_node_remove_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+
+ e_editor_selection_restore_caret_position (selection);
+ } else {
+ command = E_EDITOR_WIDGET_COMMAND_OUTDENT;
+ e_editor_widget_exec_command (editor_widget, command, NULL);
+ }
g_object_unref (editor_widget);
@@ -2782,6 +2976,11 @@ e_editor_selection_restore_caret_position (EEditorSelection *selection)
element = webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position");
if (element) {
+ WebKitDOMDOMWindow *window;
+ WebKitDOMDOMSelection *window_selection;
+
+ window = webkit_dom_document_get_default_view (document);
+ window_selection = webkit_dom_dom_window_get_selection (window);
/* If parent is BODY element, we try to restore the position on the
* element that is next to us */
if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (
@@ -2800,6 +2999,12 @@ e_editor_selection_restore_caret_position (EEditorSelection *selection)
move_caret_into_element (document, WEBKIT_DOM_ELEMENT (next_sibling));
+ /* FIXME If caret position is restored and afterwards the position is saved
+ * it is not on the place where it supposed to be (it is in the beginning of
+ * parent's element. It can be avoided by moving with the caret. */
+ webkit_dom_dom_selection_modify (window_selection, "move", "right",
"character");
+ webkit_dom_dom_selection_modify (window_selection, "move", "left",
"character");
+
return;
}
}
@@ -2809,6 +3014,12 @@ e_editor_selection_restore_caret_position (EEditorSelection *selection)
webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
WEBKIT_DOM_NODE (element),
NULL);
+
+ /* FIXME If caret position is restored and afterwards the position is saved
+ * it is not on the place where it supposed to be (it is in the beginning of
+ * parent's element. It can be avoided by moving with the caret. */
+ webkit_dom_dom_selection_modify (window_selection, "move", "right", "character");
+ webkit_dom_dom_selection_modify (window_selection, "move", "left", "character");
}
}
@@ -2890,12 +3101,6 @@ find_where_to_break_line (WebKitDOMNode *node,
return ret_val;
}
-static gboolean
-is_caret_position_node (WebKitDOMNode *node)
-{
- return element_has_id (WEBKIT_DOM_ELEMENT (node), "-x-evo-caret-position");
-}
-
static void
wrap_lines (EEditorSelection *selection,
WebKitDOMNode *paragraph,
diff --git a/e-util/e-editor-widget.c b/e-util/e-editor-widget.c
index dc4f2c8..3bc5271 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -1967,6 +1967,123 @@ e_editor_widget_get_html_mode (EEditorWidget *widget)
}
static void
+process_blockquote (WebKitDOMElement *blockquote)
+{
+ WebKitDOMNodeList *list;
+ int jj, length;
+
+ /* First replace wrappers */
+ list = webkit_dom_element_query_selector_all (
+ blockquote,
+ "span.-x-evo-temp-text-wrapper",
+ NULL);
+
+ length = webkit_dom_node_list_get_length (list);
+
+ for (jj = 0; jj < length; jj++) {
+ WebKitDOMNode *quoted_node;
+ gchar *text_content;
+
+ quoted_node = webkit_dom_node_list_item (list, jj);
+ text_content = webkit_dom_node_get_text_content (quoted_node);
+
+ webkit_dom_html_element_set_outer_html (
+ WEBKIT_DOM_HTML_ELEMENT (quoted_node),
+ text_content,
+ NULL);
+ g_free (text_content);
+ }
+
+ /* Afterwards replace quote nodes with symbols */
+ list = webkit_dom_element_query_selector_all (
+ blockquote,
+ "span.-x-evo-quoted",
+ NULL);
+
+ length = webkit_dom_node_list_get_length (list);
+
+ for (jj = 0; jj < length; jj++) {
+ WebKitDOMNode *quoted_node;
+ gchar *text_content;
+
+ quoted_node = webkit_dom_node_list_item (list, jj);
+ text_content = webkit_dom_node_get_text_content (quoted_node);
+
+ webkit_dom_html_element_set_outer_html (
+ WEBKIT_DOM_HTML_ELEMENT (quoted_node),
+ text_content,
+ NULL);
+ g_free (text_content);
+ }
+
+ if (element_has_class (blockquote, "-x-evo-indented")) {
+ WebKitDOMElement *parent;
+ WebKitDOMNode *child;
+ gint level = 1;
+ gchar *spaces;
+
+ webkit_dom_element_remove_attribute (blockquote, "style");
+ element_remove_class (blockquote, "-x-evo-indented");
+
+ parent = webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (blockquote));
+ /* Count level of indentation */
+ while (!WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) {
+ if (element_has_class (parent, "-x-evo-indented"))
+ level++;
+
+ parent = webkit_dom_node_get_parent_element (WEBKIT_DOM_NODE (parent));
+ }
+
+ spaces = g_strnfill (4 * level, ' ');
+
+ child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (blockquote));
+ while (child) {
+ /* If next sibling is indented blockqoute skip it,
+ * it will be processed afterwards */
+ if (WEBKIT_DOM_IS_ELEMENT (child) &&
+ element_has_class (WEBKIT_DOM_ELEMENT (child), "-x-evo-indented"))
+ child = webkit_dom_node_get_next_sibling (child);
+
+ if (WEBKIT_DOM_IS_TEXT (child)) {
+ gchar *text_content;
+ gchar *indented_text;
+
+ text_content = webkit_dom_text_get_whole_text (WEBKIT_DOM_TEXT (child));
+
+ /* FIXME Fix properly in wrapping => do not include space on the beginning of
the line */
+ if (g_str_has_prefix (text_content, " "))
+ indented_text = g_strconcat (spaces + 1, text_content, NULL);
+ else
+ indented_text = g_strconcat (spaces, text_content, NULL);
+
+ webkit_dom_text_replace_whole_text (
+ WEBKIT_DOM_TEXT (child),
+ indented_text,
+ NULL);
+
+ g_free (text_content);
+ g_free (indented_text);
+ }
+
+ /* Move to next node */
+ if (webkit_dom_node_has_child_nodes (child))
+ child = webkit_dom_node_get_first_child (child);
+ else if (webkit_dom_node_get_next_sibling (child))
+ child = webkit_dom_node_get_next_sibling (child);
+ else {
+ if (webkit_dom_node_is_equal_node (child, child))
+ break;
+
+ child = webkit_dom_node_get_parent_node (child);
+ if (child)
+ child = webkit_dom_node_get_next_sibling (child);
+ }
+ }
+ g_free (spaces);
+ }
+}
+
+static void
process_elements (WebKitDOMNode *node,
GString *buffer,
gboolean process_nodes)
@@ -2054,54 +2171,8 @@ process_elements (WebKitDOMNode *node,
g_string_append (buffer, content);
g_free (content);
skip_node = TRUE;
- } else {
- WebKitDOMNodeList *list;
- int jj, length;
-
- /* First replace wrappers */
- list = webkit_dom_element_query_selector_all (
- WEBKIT_DOM_ELEMENT (child),
- "span.-x-evo-temp-text-wrapper",
- NULL);
-
- length = webkit_dom_node_list_get_length (list);
-
- for (jj = 0; jj < length; jj++) {
- WebKitDOMNode *quoted_node;
- gchar *text_content;
-
- quoted_node = webkit_dom_node_list_item (list, jj);
- text_content = webkit_dom_node_get_text_content (quoted_node);
-
- webkit_dom_html_element_set_outer_html (
- WEBKIT_DOM_HTML_ELEMENT (quoted_node),
- text_content,
- NULL);
- g_free (text_content);
- }
-
- /* Afterwards replace quote nodes with symbols */
- list = webkit_dom_element_query_selector_all (
- WEBKIT_DOM_ELEMENT (child),
- "span.-x-evo-quoted",
- NULL);
-
- length = webkit_dom_node_list_get_length (list);
-
- for (jj = 0; jj < length; jj++) {
- WebKitDOMNode *quoted_node;
- gchar *text_content;
-
- quoted_node = webkit_dom_node_list_item (list, jj);
- text_content = webkit_dom_node_get_text_content (quoted_node);
-
- webkit_dom_html_element_set_outer_html (
- WEBKIT_DOM_HTML_ELEMENT (quoted_node),
- text_content,
- NULL);
- g_free (text_content);
- }
- }
+ } else
+ process_blockquote (WEBKIT_DOM_ELEMENT (child));
}
/* Leave wrapped paragraphs as they are */
@@ -2114,6 +2185,16 @@ process_elements (WebKitDOMNode *node,
}
}
+ /* Leave PRE elements untouched */
+ if (WEBKIT_DOM_IS_HTML_PRE_ELEMENT (child)) {
+ if (!process_nodes) {
+ content = webkit_dom_html_element_get_outer_html
(WEBKIT_DOM_HTML_ELEMENT (child));
+ g_string_append (buffer, content);
+ g_free (content);
+ skip_node = TRUE;
+ }
+ }
+
/* Insert new line when we hit BR element */
if (WEBKIT_DOM_IS_HTMLBR_ELEMENT (child))
g_string_append (buffer, process_nodes ? "\n" : "<br>");
@@ -2132,6 +2213,9 @@ process_elements (WebKitDOMNode *node,
if (!next_sibling)
add_br = FALSE;
+ if (element_has_class (webkit_dom_node_get_parent_element (node), "-x-evo-indented"))
+ add_br = TRUE;
+
if (next_sibling && WEBKIT_DOM_IS_HTML_DIV_ELEMENT (next_sibling)) {
if (webkit_dom_element_query_selector (WEBKIT_DOM_ELEMENT (next_sibling),
"span.-x-evolution-signature", NULL))
add_br = FALSE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]