[evolution/webkit-composer: 31/54] Make bold, italic, underline and strike-through buttons work



commit 421ffe9a4d05ef479d84e24ce2fea6a0ce2cb87b
Author: Dan VrÃtil <dvratil redhat com>
Date:   Wed Aug 1 11:49:36 2012 +0200

    Make bold, italic, underline and strike-through buttons work
    
    This is done by binding their 'activate' property with
    EEditorSelection's properties for each style, so that
    when selection changes, the buttons are notified about
    style property change and their activate state is toggled
    if neccessary.
    
    This does not fully work for Monospaced button, as removing
    of the formatting must be implemented manually.

 widgets/editor/e-editor-actions.c   |  118 ++++++++---------------------------
 widgets/editor/e-editor-private.h   |    3 +-
 widgets/editor/e-editor-selection.c |  117 +++++++++++++++++++++++++++++-----
 widgets/editor/e-editor-selection.h |    6 ++
 widgets/editor/e-editor-widget.c    |   15 ++++-
 widgets/editor/e-editor.c           |    1 +
 6 files changed, 147 insertions(+), 113 deletions(-)
---
diff --git a/widgets/editor/e-editor-actions.c b/widgets/editor/e-editor-actions.c
index 09c2994..c1ec31b 100644
--- a/widgets/editor/e-editor-actions.c
+++ b/widgets/editor/e-editor-actions.c
@@ -111,18 +111,6 @@ insert_text_file_ready_cb (GFile *file,
  * Action Callbacks
  *****************************************************************************/
 
-static void
-action_bold_cb (GtkToggleAction *action,
-                EEditor *editor)
-{
-	EEditorSelection *selection;
-
-	selection = e_editor_widget_get_selection (
-			e_editor_get_editor_widget (editor));
-	e_editor_selection_set_bold (
-		selection, gtk_toggle_action_get_active (action));
-}
-
 static WebKitDOMNode *
 find_parent_element_by_type (WebKitDOMNode *node, GType type)
 {
@@ -786,18 +774,6 @@ action_insert_text_file_cb (GtkAction *action,
 }
 
 static void
-action_italic_cb (GtkToggleAction *action,
-                  EEditor *editor)
-{
-	EEditorSelection *selection;
-
-	selection = e_editor_widget_get_selection (
-			e_editor_get_editor_widget (editor));
-	e_editor_selection_set_italic (
-		selection, gtk_toggle_action_get_active (action));
-}
-
-static void
 action_justify_cb (GtkRadioAction *action,
                    GtkRadioAction *current,
                    EEditor *editor)
@@ -985,32 +961,6 @@ action_mode_cb (GtkRadioAction *action,
 }
 
 static void
-action_monospaced_cb (GtkToggleAction *action,
-                      EEditor *editor)
-{
-	/* FIXME WEBKIT */
-	/*
-	GtkHTML *html;
-	GtkHTMLFontStyle and_mask;
-	GtkHTMLFontStyle or_mask;
-
-	if (editor->priv->ignore_style_change)
-		return;
-
-	if (gtk_toggle_action_get_active (action)) {
-		and_mask = GTK_HTML_FONT_STYLE_MAX;
-		or_mask = GTK_HTML_FONT_STYLE_FIXED;
-	} else {
-		and_mask = ~GTK_HTML_FONT_STYLE_FIXED;
-		or_mask = 0;
-	}
-
-	html = gtkhtml_editor_get_html (editor);
-	gtk_html_set_font_style (html, and_mask, or_mask);
-	*/
-}
-
-static void
 action_paste_cb (GtkAction *action,
                  EEditor *editor)
 {
@@ -1094,10 +1044,6 @@ action_style_cb (GtkRadioAction *action,
 {
 	EEditorSelection *selection;
 
-	/* FIXME WEBKIT What's this good for? */
-	if (editor->priv->ignore_style_change)
-		return;
-
 	selection = e_editor_widget_get_selection (
 			e_editor_get_editor_widget (editor));
 	e_editor_selection_set_block_format (
@@ -1163,9 +1109,6 @@ action_size_cb (GtkRadioAction *action,
 {
 	EEditorSelection *selection;
 
-	if (editor->priv->ignore_style_change)
-		return;
-
 	selection = e_editor_widget_get_selection (
 			e_editor_get_editor_widget (editor));
 	e_editor_selection_set_font_size (
@@ -1182,21 +1125,6 @@ action_spell_check_cb (GtkAction *action,
 }
 
 static void
-action_strikethrough_cb (GtkToggleAction *action,
-                         EEditor *editor)
-{
-	EEditorSelection *selection;
-
-	if (editor->priv->ignore_style_change)
-		return;
-
-	selection = e_editor_widget_get_selection (
-			e_editor_get_editor_widget (editor));
-	e_editor_selection_set_italic (
-		selection, gtk_toggle_action_get_active (action));
-}
-
-static void
 action_test_url_cb (GtkAction *action,
                     EEditor *editor)
 {
@@ -1217,21 +1145,6 @@ action_test_url_cb (GtkAction *action,
 }
 
 static void
-action_underline_cb (GtkToggleAction *action,
-                     EEditor *editor)
-{
-	EEditorSelection *selection;
-
-	if (editor->priv->ignore_style_change)
-		return;
-
-	selection = e_editor_widget_get_selection (
-			e_editor_get_editor_widget (editor));
-	e_editor_selection_set_underline (
-		selection, gtk_toggle_action_get_active (action));
-}
-
-static void
 action_undo_cb (GtkAction *action,
                 EEditor *editor)
 {
@@ -1687,7 +1600,7 @@ static GtkToggleActionEntry html_toggle_entries[] = {
 	  N_("_Bold"),
 	  "<Control>b",
 	  N_("Bold"),
-	  G_CALLBACK (action_bold_cb),
+	  NULL,
 	  FALSE },
 
 	{ "italic",
@@ -1695,7 +1608,7 @@ static GtkToggleActionEntry html_toggle_entries[] = {
 	  N_("_Italic"),
 	  "<Control>i",
 	  N_("Italic"),
-	  G_CALLBACK (action_italic_cb),
+	  NULL,
 	  FALSE },
 
 	{ "monospaced",
@@ -1703,7 +1616,7 @@ static GtkToggleActionEntry html_toggle_entries[] = {
 	  N_("_Plain Text"),
 	  "<Control>t",
 	  N_("Plain Text"),
-	  G_CALLBACK (action_monospaced_cb),
+	  NULL,
 	  FALSE },
 
 	{ "strikethrough",
@@ -1711,7 +1624,7 @@ static GtkToggleActionEntry html_toggle_entries[] = {
 	  N_("_Strikethrough"),
 	  NULL,
 	  N_("Strikethrough"),
-	  G_CALLBACK (action_strikethrough_cb),
+	  NULL,
 	  FALSE },
 
 	{ "underline",
@@ -1719,7 +1632,7 @@ static GtkToggleActionEntry html_toggle_entries[] = {
 	  N_("_Underline"),
 	  "<Control>u",
 	  N_("Underline"),
-	  G_CALLBACK (action_underline_cb),
+	  NULL,
 	  FALSE }
 };
 
@@ -2287,4 +2200,25 @@ editor_actions_init (EEditor *editor)
 		ACTION (PASTE), "sensitive",
 		G_BINDING_SYNC_CREATE);
 
+	g_object_bind_property (
+		editor->priv->selection, "bold",
+		ACTION (BOLD), "active",
+		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+	g_object_bind_property (
+		editor->priv->selection, "italic",
+		ACTION (ITALIC), "active",
+		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+	g_object_bind_property (
+		editor->priv->selection, "monospaced",
+		ACTION (MONOSPACED), "active",
+		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+	g_object_bind_property (
+		editor->priv->selection, "strike-through",
+		ACTION (STRIKETHROUGH), "active",
+		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+	g_object_bind_property (
+		editor->priv->selection, "underline",
+		ACTION (UNDERLINE), "active",
+		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
 }
diff --git a/widgets/editor/e-editor-private.h b/widgets/editor/e-editor-private.h
index cdb2379..c736add 100644
--- a/widgets/editor/e-editor-private.h
+++ b/widgets/editor/e-editor-private.h
@@ -64,8 +64,7 @@ struct _EEditorPrivate {
 	GtkWidget *scrolled_window;
 
 	EEditorWidget *editor_widget;
-
-	guint ignore_style_change : 1;
+	EEditorSelection *selection;
 
 	gchar *filename;
 };
diff --git a/widgets/editor/e-editor-selection.c b/widgets/editor/e-editor-selection.c
index 579dc3f..0fdd4d3 100644
--- a/widgets/editor/e-editor-selection.c
+++ b/widgets/editor/e-editor-selection.c
@@ -58,6 +58,7 @@ enum {
 	PROP_FONT_COLOR,
 	PROP_BLOCK_FORMAT,
 	PROP_ITALIC,
+	PROP_MONOSPACED,
 	PROP_STRIKE_THROUGH,
 	PROP_SUBSCRIPT,
 	PROP_SUPERSCRIPT,
@@ -82,31 +83,47 @@ editor_selection_get_current_range (EEditorSelection *selection)
 }
 
 static gboolean
-get_has_style_property (EEditorSelection *selection,
-			const gchar *style,
-			const gchar *value)
+get_has_style (EEditorSelection *selection,
+	       const gchar *style_tag)
 {
 	WebKitDOMNode *node;
 	WebKitDOMElement *element;
 	WebKitDOMRange *range;
-	WebKitDOMCSSStyleDeclaration *css;
-	gchar *style_value;
 	gboolean result;
+	gint tag_len;
+
 
 	range = editor_selection_get_current_range (selection);
-	node = webkit_dom_range_get_common_ancestor_container (range, NULL);
+	if (!range) {
+		return FALSE;
+	}
+
+	node = webkit_dom_range_get_start_container (range, NULL);
 	if (!WEBKIT_DOM_IS_ELEMENT (node)) {
 		element = webkit_dom_node_get_parent_element (node);
 	} else {
 		element = WEBKIT_DOM_ELEMENT (node);
 	}
 
-	css = webkit_dom_element_get_style (element);
-	style_value = webkit_dom_css_style_declaration_get_property_value (
-			css, style);
+	tag_len = strlen (style_tag);
+	result = FALSE;
+	while (!result && element) {
+		gchar *element_tag;
+
+		element_tag = webkit_dom_element_get_tag_name (element);
+
+		result = ((tag_len == strlen (element_tag)) &&
+				(g_ascii_strncasecmp (element_tag, style_tag, tag_len) == 0));
 
-	result = (g_ascii_strncasecmp (style_value, value, strlen (value)) == 0);
-	g_free (style_value);
+		g_free (element_tag);
+
+		if (result) {
+			break;
+		}
+
+		element = webkit_dom_node_get_parent_element (
+				WEBKIT_DOM_NODE (element));
+	}
 
 	return result;
 }
@@ -122,6 +139,7 @@ webview_selection_changed (WebKitWebView *webview,
 	g_object_notify (G_OBJECT (selection), "font-color");
 	g_object_notify (G_OBJECT (selection), "block-format");
 	g_object_notify (G_OBJECT (selection), "italic");
+	g_object_notify (G_OBJECT (selection), "monospaced");
 	g_object_notify (G_OBJECT (selection), "strike-through");
 	g_object_notify (G_OBJECT (selection), "subscript");
 	g_object_notify (G_OBJECT (selection), "superscript");
@@ -134,8 +152,9 @@ editor_selection_set_webview (EEditorSelection *selection,
 			      WebKitWebView *webview)
 {
 	selection->priv->webview = g_object_ref (webview);
-	g_signal_connect (webview, "selection-changed",
-			  G_CALLBACK (webview_selection_changed), selection);
+	g_signal_connect (
+		webview, "selection-changed",
+		G_CALLBACK (webview_selection_changed), selection);
 }
 
 
@@ -184,6 +203,11 @@ e_editor_selection_get_property (GObject *object,
 				e_editor_selection_get_italic (selection));
 			return;
 
+		case PROP_MONOSPACED:
+			g_value_set_boolean (value,
+				e_editor_selection_get_monospaced (selection));
+			return;
+
 		case PROP_STRIKE_THROUGH:
 			g_value_set_boolean (value,
 				e_editor_selection_get_strike_through (selection));
@@ -257,6 +281,11 @@ e_editor_selection_set_property (GObject *object,
 				selection, g_value_get_boolean (value));
 			return;
 
+		case PROP_MONOSPACED:
+			e_editor_selection_set_monospaced (
+				selection, g_value_get_boolean (value));
+			return;
+
 		case PROP_STRIKE_THROUGH:
 			e_editor_selection_set_strike_through (
 				selection, g_value_get_boolean (value));
@@ -390,6 +419,16 @@ e_editor_selection_class_init (EEditorSelectionClass *klass)
 
 	g_object_class_install_property (
 		object_class,
+		PROP_MONOSPACED,
+		g_param_spec_boolean (
+			"monospaced",
+			NULL,
+			NULL,
+			FALSE,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
 		PROP_STRIKE_THROUGH,
 		g_param_spec_boolean (
 			"strike-through",
@@ -635,8 +674,7 @@ e_editor_selection_get_bold (EEditorSelection *selection)
 {
 	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
 
-	return (get_has_style_property (selection, "fontWeight", "bold") ||
-	       get_has_style_property (selection, "fontWeight", "700"));
+	return get_has_style (selection, "b");
 }
 
 void
@@ -772,7 +810,7 @@ e_editor_selection_get_italic (EEditorSelection *selection)
 {
 	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
 
-	return get_has_style_property (selection, "fontStyle", "italic");
+	return get_has_style (selection, "i");
 }
 
 void
@@ -795,11 +833,54 @@ e_editor_selection_set_italic (EEditorSelection *selection,
 }
 
 gboolean
+e_editor_selection_get_monospaced (EEditorSelection *selection)
+{
+	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
+
+	return get_has_style (selection, "tt");
+}
+
+void
+e_editor_selection_set_monospaced (EEditorSelection *selection,
+				   gboolean monospaced)
+{
+	WebKitDOMDocument *document;
+	WebKitDOMRange *range;
+
+	g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+	if ((e_editor_selection_get_monospaced (selection) ? TRUE : FALSE)
+				== (monospaced ? TRUE : FALSE)) {
+		return;
+	}
+
+	document = webkit_web_view_get_dom_document (selection->priv->webview);
+
+	range = editor_selection_get_current_range (selection);
+	if (!range) {
+		return;
+	}
+
+	if (monospaced) {
+		WebKitDOMElement *tt;
+
+		tt = webkit_dom_document_create_element (document, "TT", NULL);
+		webkit_dom_range_surround_contents (
+			range, WEBKIT_DOM_NODE (tt), NULL);
+
+	} else {
+		/* FIXME WEBKIT: this does not work yet :)
+	}
+
+	g_object_notify (G_OBJECT (selection), "monospaced");
+}
+
+gboolean
 e_editor_selection_get_strike_through (EEditorSelection *selection)
 {
 	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
 
-	return get_has_style_property (selection, "textDecoration", "overline");
+	return get_has_style (selection, "strike");
 }
 
 void
@@ -920,7 +1001,7 @@ e_editor_selection_get_underline (EEditorSelection *selection)
 {
 	g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE);
 
-	return get_has_style_property (selection, "textDecoration", "underline");
+	return get_has_style (selection, "u");
 }
 
 void
diff --git a/widgets/editor/e-editor-selection.h b/widgets/editor/e-editor-selection.h
index 1a641f7..ce3732f 100644
--- a/widgets/editor/e-editor-selection.h
+++ b/widgets/editor/e-editor-selection.h
@@ -134,6 +134,12 @@ void			e_editor_selection_set_italic	(EEditorSelection *selection,
 							 gboolean italic);
 gboolean		e_editor_selection_get_italic	(EEditorSelection *selection);
 
+void			e_editor_selection_set_monospaced
+							(EEditorSelection *selection,
+							 gboolean monospaced);
+gboolean		e_editor_selection_get_monospaced
+							(EEditorSelection *selection);
+
 void			e_editor_selection_set_strike_through
 							(EEditorSelection *selection,
 							 gboolean strike_through);
diff --git a/widgets/editor/e-editor-widget.c b/widgets/editor/e-editor-widget.c
index a3b886a..9341c54 100644
--- a/widgets/editor/e-editor-widget.c
+++ b/widgets/editor/e-editor-widget.c
@@ -36,6 +36,8 @@ struct _EEditorWidgetPrivate {
 	gint can_redo		: 1;
 	gint can_undo		: 1;
 
+	EEditorSelection *selection;
+
 	EEditorWidgetMode mode;
 
 	/* FIXME WEBKIT Is this in widget's competence? */
@@ -237,6 +239,12 @@ e_editor_widget_set_property (GObject *object,
 static void
 e_editor_widget_finalize (GObject *object)
 {
+	EEditorWidgetPrivate *priv = E_EDITOR_WIDGET (object)->priv;
+
+	g_clear_object (&priv->selection);
+
+	/* Chain up to parent's implementation */
+	G_OBJECT_CLASS (e_editor_widget_parent_class)->finalize (object);
 }
 
 static void
@@ -399,6 +407,9 @@ e_editor_widget_init (EEditorWidget *editor)
 		G_CALLBACK (editor_widget_user_changed_contents_cb), NULL);
 	g_signal_connect (editor, "selection-changed",
 		G_CALLBACK (editor_widget_selection_changed_cb), NULL);
+
+	editor->priv->selection = e_editor_selection_new (
+					WEBKIT_WEB_VIEW (editor));
 }
 
 EEditorWidget *
@@ -410,7 +421,9 @@ e_editor_widget_new (void)
 EEditorSelection *
 e_editor_widget_get_selection (EEditorWidget *widget)
 {
-	return e_editor_selection_new (WEBKIT_WEB_VIEW (widget));
+	g_return_val_if_fail (E_IS_EDITOR_WIDGET (widget), NULL);
+
+	return widget->priv->selection;
 }
 
 gboolean
diff --git a/widgets/editor/e-editor.c b/widgets/editor/e-editor.c
index 61bfdd9..c558e52 100644
--- a/widgets/editor/e-editor.c
+++ b/widgets/editor/e-editor.c
@@ -361,6 +361,7 @@ e_editor_init (EEditor *editor)
 	priv->spell_check_actions = gtk_action_group_new ("spell-check");
 	priv->suggestion_actions = gtk_action_group_new ("suggestion");
 	priv->editor_widget = e_editor_widget_new ();
+	priv->selection = e_editor_widget_get_selection (priv->editor_widget);
 
 	filename = editor_find_ui_file ("e-editor-manager.ui");
 



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