aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/misc
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/misc')
-rw-r--r--widgets/misc/Makefile.am4
-rw-r--r--widgets/misc/e-focus-tracker.c859
-rw-r--r--widgets/misc/e-focus-tracker.h99
-rw-r--r--widgets/misc/e-selectable.c133
-rw-r--r--widgets/misc/e-selectable.h76
-rw-r--r--widgets/misc/e-signature-editor.c64
-rw-r--r--widgets/misc/e-signature-editor.h3
-rw-r--r--widgets/misc/e-web-view.c78
-rw-r--r--widgets/misc/e-web-view.h2
9 files changed, 1308 insertions, 10 deletions
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 33b9311d90..aa29f406df 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -46,6 +46,7 @@ widgetsinclude_HEADERS = \
e-colors.h \
e-combo-cell-editable.h \
e-dateedit.h \
+ e-focus-tracker.h \
e-gui-utils.h \
e-hinted-entry.h \
e-hsv-utils.h \
@@ -60,6 +61,7 @@ widgetsinclude_HEADERS = \
e-popup-menu.h \
e-preferences-window.h \
e-printable.h \
+ e-selectable.h \
e-selection-model.h \
e-selection-model-array.h \
e-selection-model-simple.h \
@@ -121,6 +123,7 @@ libemiscwidgets_la_SOURCES = \
e-colors.c \
e-combo-cell-editable.c \
e-dateedit.c \
+ e-focus-tracker.c \
e-gui-utils.c \
e-hinted-entry.c \
e-hsv-utils.c \
@@ -135,6 +138,7 @@ libemiscwidgets_la_SOURCES = \
e-popup-menu.c \
e-preferences-window.c \
e-printable.c \
+ e-selectable.c \
e-selection-model.c \
e-selection-model-array.c \
e-selection-model-simple.c \
diff --git a/widgets/misc/e-focus-tracker.c b/widgets/misc/e-focus-tracker.c
new file mode 100644
index 0000000000..d1cb32adde
--- /dev/null
+++ b/widgets/misc/e-focus-tracker.c
@@ -0,0 +1,859 @@
+/*
+ * e-focus-tracker.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-focus-tracker.h"
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <misc/e-selectable.h>
+
+#define E_FOCUS_TRACKER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_FOCUS_TRACKER, EFocusTrackerPrivate))
+
+struct _EFocusTrackerPrivate {
+ GtkWidget *focus; /* not referenced */
+ GtkWindow *window;
+
+ GtkAction *cut_clipboard;
+ GtkAction *copy_clipboard;
+ GtkAction *paste_clipboard;
+ GtkAction *delete_selection;
+ GtkAction *select_all;
+};
+
+enum {
+ PROP_0,
+ PROP_FOCUS,
+ PROP_WINDOW,
+ PROP_CUT_CLIPBOARD_ACTION,
+ PROP_COPY_CLIPBOARD_ACTION,
+ PROP_PASTE_CLIPBOARD_ACTION,
+ PROP_DELETE_SELECTION_ACTION,
+ PROP_SELECT_ALL_ACTION
+};
+
+static gpointer parent_class;
+
+static void
+focus_tracker_disable_actions (EFocusTracker *focus_tracker)
+{
+ GtkAction *action;
+
+ action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
+ if (action != NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
+ if (action != NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
+ if (action != NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_delete_selection_action (focus_tracker);
+ if (action != NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_select_all_action (focus_tracker);
+ if (action != NULL)
+ gtk_action_set_sensitive (action, FALSE);
+}
+
+static void
+focus_tracker_editable_update_actions (EFocusTracker *focus_tracker,
+ GtkEditable *editable,
+ GdkAtom *targets,
+ gint n_targets)
+{
+ GtkAction *action;
+ gboolean can_edit_text;
+ gboolean clipboard_has_text;
+ gboolean text_is_selected;
+ gboolean sensitive;
+
+ can_edit_text =
+ gtk_editable_get_editable (editable);
+
+ clipboard_has_text = (targets != NULL) &&
+ gtk_targets_include_text (targets, n_targets);
+
+ text_is_selected =
+ gtk_editable_get_selection_bounds (editable, NULL, NULL);
+
+ action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
+ if (action != NULL) {
+ sensitive = can_edit_text && text_is_selected;
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_tooltip (action, _("Cut the selection"));
+ }
+
+ action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
+ if (action != NULL) {
+ sensitive = text_is_selected;
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_tooltip (action, _("Copy the selection"));
+ }
+
+ action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
+ if (action != NULL) {
+ sensitive = can_edit_text && clipboard_has_text;
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_tooltip (action, _("Paste the clipboard"));
+ }
+
+ action = e_focus_tracker_get_delete_selection_action (focus_tracker);
+ if (action != NULL) {
+ sensitive = can_edit_text && text_is_selected;
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_tooltip (action, _("Delete the selection"));
+ }
+
+ action = e_focus_tracker_get_select_all_action (focus_tracker);
+ if (action != NULL) {
+ sensitive = TRUE; /* always enabled */
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_tooltip (action, _("Select all text"));
+ }
+}
+
+static void
+focus_tracker_selectable_update_actions (EFocusTracker *focus_tracker,
+ ESelectable *selectable,
+ GdkAtom *targets,
+ gint n_targets)
+{
+ ESelectableInterface *interface;
+ GtkAction *action;
+
+ interface = E_SELECTABLE_GET_INTERFACE (selectable);
+
+ e_selectable_update_actions (
+ selectable, focus_tracker, targets, n_targets);
+
+ /* Disable actions for which the corresponding method is not
+ * implemented. This allows update_actions() implementations
+ * to simply skip the actions they don't support, which in turn
+ * allows us to add new actions without disturbing the existing
+ * ESelectable implementations. */
+
+ action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
+ if (action != NULL && interface->cut_clipboard == NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
+ if (action != NULL && interface->copy_clipboard == NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
+ if (action != NULL && interface->paste_clipboard == NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_delete_selection_action (focus_tracker);
+ if (action != NULL && interface->delete_selection == NULL)
+ gtk_action_set_sensitive (action, FALSE);
+
+ action = e_focus_tracker_get_select_all_action (focus_tracker);
+ if (action != NULL && interface->select_all == NULL)
+ gtk_action_set_sensitive (action, FALSE);
+}
+
+static void
+focus_tracker_targets_received_cb (GtkClipboard *clipboard,
+ GdkAtom *targets,
+ gint n_targets,
+ EFocusTracker *focus_tracker)
+{
+ GtkWidget *focus;
+
+ focus = e_focus_tracker_get_focus (focus_tracker);
+
+ if (focus == NULL)
+ focus_tracker_disable_actions (focus_tracker);
+
+ else if (GTK_IS_EDITABLE (focus))
+ focus_tracker_editable_update_actions (
+ focus_tracker, GTK_EDITABLE (focus),
+ targets, n_targets);
+
+ else if (E_IS_SELECTABLE (focus))
+ focus_tracker_selectable_update_actions (
+ focus_tracker, E_SELECTABLE (focus),
+ targets, n_targets);
+
+ g_object_unref (focus_tracker);
+}
+
+static void
+focus_tracker_set_focus_cb (GtkWindow *window,
+ GtkWidget *focus,
+ EFocusTracker *focus_tracker)
+{
+ while (focus != NULL) {
+ if (GTK_IS_EDITABLE (focus))
+ break;
+
+ if (E_IS_SELECTABLE (focus))
+ break;
+
+ focus = gtk_widget_get_parent (focus);
+ }
+
+ if (focus == focus_tracker->priv->focus)
+ return;
+
+ focus_tracker->priv->focus = focus;
+ g_object_notify (G_OBJECT (focus_tracker), "focus");
+
+ e_focus_tracker_update_actions (focus_tracker);
+}
+
+static void
+focus_tracker_set_window (EFocusTracker *focus_tracker,
+ GtkWindow *window)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (focus_tracker->priv->window == NULL);
+
+ focus_tracker->priv->window = g_object_ref (window);
+
+ g_signal_connect (
+ window, "set-focus",
+ G_CALLBACK (focus_tracker_set_focus_cb), focus_tracker);
+}
+
+static void
+focus_tracker_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_WINDOW:
+ focus_tracker_set_window (
+ E_FOCUS_TRACKER (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_CUT_CLIPBOARD_ACTION:
+ e_focus_tracker_set_cut_clipboard_action (
+ E_FOCUS_TRACKER (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_COPY_CLIPBOARD_ACTION:
+ e_focus_tracker_set_copy_clipboard_action (
+ E_FOCUS_TRACKER (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_PASTE_CLIPBOARD_ACTION:
+ e_focus_tracker_set_paste_clipboard_action (
+ E_FOCUS_TRACKER (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_DELETE_SELECTION_ACTION:
+ e_focus_tracker_set_delete_selection_action (
+ E_FOCUS_TRACKER (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_SELECT_ALL_ACTION:
+ e_focus_tracker_set_select_all_action (
+ E_FOCUS_TRACKER (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+focus_tracker_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_FOCUS:
+ g_value_set_object (
+ value,
+ e_focus_tracker_get_focus (
+ E_FOCUS_TRACKER (object)));
+ return;
+
+ case PROP_WINDOW:
+ g_value_set_object (
+ value,
+ e_focus_tracker_get_window (
+ E_FOCUS_TRACKER (object)));
+ return;
+
+ case PROP_CUT_CLIPBOARD_ACTION:
+ g_value_set_object (
+ value,
+ e_focus_tracker_get_cut_clipboard_action (
+ E_FOCUS_TRACKER (object)));
+ return;
+
+ case PROP_COPY_CLIPBOARD_ACTION:
+ g_value_set_object (
+ value,
+ e_focus_tracker_get_copy_clipboard_action (
+ E_FOCUS_TRACKER (object)));
+ return;
+
+ case PROP_PASTE_CLIPBOARD_ACTION:
+ g_value_set_object (
+ value,
+ e_focus_tracker_get_paste_clipboard_action (
+ E_FOCUS_TRACKER (object)));
+ return;
+
+ case PROP_DELETE_SELECTION_ACTION:
+ g_value_set_object (
+ value,
+ e_focus_tracker_get_delete_selection_action (
+ E_FOCUS_TRACKER (object)));
+ return;
+
+ case PROP_SELECT_ALL_ACTION:
+ g_value_set_object (
+ value,
+ e_focus_tracker_get_select_all_action (
+ E_FOCUS_TRACKER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+focus_tracker_dispose (GObject *object)
+{
+ EFocusTrackerPrivate *priv;
+
+ priv = E_FOCUS_TRACKER_GET_PRIVATE (object);
+
+ g_signal_handlers_disconnect_matched (
+ gtk_clipboard_get (GDK_SELECTION_PRIMARY),
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object);
+
+ if (priv->window != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->window, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->window);
+ priv->window = NULL;
+ }
+
+ if (priv->cut_clipboard != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->cut_clipboard, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->cut_clipboard);
+ priv->cut_clipboard = NULL;
+ }
+
+ if (priv->copy_clipboard != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->copy_clipboard, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->copy_clipboard);
+ priv->copy_clipboard = NULL;
+ }
+
+ if (priv->paste_clipboard != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->paste_clipboard, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->paste_clipboard);
+ priv->paste_clipboard = NULL;
+ }
+
+ if (priv->delete_selection != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->delete_selection, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->delete_selection);
+ priv->delete_selection = NULL;
+ }
+
+ if (priv->select_all != NULL) {
+ g_signal_handlers_disconnect_matched (
+ priv->select_all, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (priv->select_all);
+ priv->select_all = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+focus_tracker_constructed (GObject *object)
+{
+ GtkClipboard *clipboard;
+
+ /* Listen for "owner-change" signals from the primary selection
+ * clipboard to learn when text selections change in GtkEditable
+ * widgets. It's a bit of an overkill, but I don't know of any
+ * other notification mechanism. */
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+
+ g_signal_connect_swapped (
+ clipboard, "owner-change",
+ G_CALLBACK (e_focus_tracker_update_actions), object);
+}
+
+static void
+focus_tracker_class_init (EFocusTrackerClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EFocusTrackerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = focus_tracker_set_property;
+ object_class->get_property = focus_tracker_get_property;
+ object_class->dispose = focus_tracker_dispose;
+ object_class->constructed = focus_tracker_constructed;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FOCUS,
+ g_param_spec_object (
+ "focus",
+ "Focus",
+ NULL,
+ GTK_TYPE_WIDGET,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_WINDOW,
+ g_param_spec_object (
+ "window",
+ "Window",
+ NULL,
+ GTK_TYPE_WINDOW,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CUT_CLIPBOARD_ACTION,
+ g_param_spec_object (
+ "cut-clipboard-action",
+ "Cut Clipboard Action",
+ NULL,
+ GTK_TYPE_ACTION,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_COPY_CLIPBOARD_ACTION,
+ g_param_spec_object (
+ "copy-clipboard-action",
+ "Copy Clipboard Action",
+ NULL,
+ GTK_TYPE_ACTION,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PASTE_CLIPBOARD_ACTION,
+ g_param_spec_object (
+ "paste-clipboard-action",
+ "Paste Clipboard Action",
+ NULL,
+ GTK_TYPE_ACTION,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_DELETE_SELECTION_ACTION,
+ g_param_spec_object (
+ "delete-selection-action",
+ "Delete Selection Action",
+ NULL,
+ GTK_TYPE_ACTION,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_SELECT_ALL_ACTION,
+ g_param_spec_object (
+ "select-all-action",
+ "Select All Action",
+ NULL,
+ GTK_TYPE_ACTION,
+ G_PARAM_READWRITE));
+}
+
+static void
+focus_tracker_init (EFocusTracker *focus_tracker)
+{
+ focus_tracker->priv = E_FOCUS_TRACKER_GET_PRIVATE (focus_tracker);
+}
+
+GType
+e_focus_tracker_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EFocusTrackerClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) focus_tracker_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EFocusTracker),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) focus_tracker_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_OBJECT, "EFocusTracker", &type_info, 0);
+ }
+
+ return type;
+}
+
+EFocusTracker *
+e_focus_tracker_new (GtkWindow *window)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+ return g_object_new (E_TYPE_FOCUS_TRACKER, "window", window, NULL);
+}
+
+GtkWidget *
+e_focus_tracker_get_focus (EFocusTracker *focus_tracker)
+{
+ g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
+
+ return focus_tracker->priv->focus;
+}
+
+GtkWindow *
+e_focus_tracker_get_window (EFocusTracker *focus_tracker)
+{
+ g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
+
+ return focus_tracker->priv->window;
+}
+
+GtkAction *
+e_focus_tracker_get_cut_clipboard_action (EFocusTracker *focus_tracker)
+{
+ g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
+
+ return focus_tracker->priv->cut_clipboard;
+}
+
+void
+e_focus_tracker_set_cut_clipboard_action (EFocusTracker *focus_tracker,
+ GtkAction *cut_clipboard)
+{
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ if (cut_clipboard != NULL) {
+ g_return_if_fail (GTK_IS_ACTION (cut_clipboard));
+ g_object_ref (cut_clipboard);
+ }
+
+ if (focus_tracker->priv->cut_clipboard != NULL) {
+ g_signal_handlers_disconnect_matched (
+ focus_tracker->priv->cut_clipboard,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
+ focus_tracker);
+ g_object_unref (focus_tracker->priv->cut_clipboard);
+ }
+
+ focus_tracker->priv->cut_clipboard = cut_clipboard;
+
+ if (cut_clipboard != NULL)
+ g_signal_connect_swapped (
+ cut_clipboard, "activate",
+ G_CALLBACK (e_focus_tracker_cut_clipboard),
+ focus_tracker);
+
+ g_object_notify (G_OBJECT (focus_tracker), "cut-clipboard-action");
+}
+
+GtkAction *
+e_focus_tracker_get_copy_clipboard_action (EFocusTracker *focus_tracker)
+{
+ g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
+
+ return focus_tracker->priv->copy_clipboard;
+}
+
+void
+e_focus_tracker_set_copy_clipboard_action (EFocusTracker *focus_tracker,
+ GtkAction *copy_clipboard)
+{
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ if (copy_clipboard != NULL) {
+ g_return_if_fail (GTK_IS_ACTION (copy_clipboard));
+ g_object_ref (copy_clipboard);
+ }
+
+ if (focus_tracker->priv->copy_clipboard != NULL) {
+ g_signal_handlers_disconnect_matched (
+ focus_tracker->priv->copy_clipboard,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
+ focus_tracker);
+ g_object_unref (focus_tracker->priv->copy_clipboard);
+ }
+
+ focus_tracker->priv->copy_clipboard = copy_clipboard;
+
+ if (copy_clipboard != NULL)
+ g_signal_connect_swapped (
+ copy_clipboard, "activate",
+ G_CALLBACK (e_focus_tracker_copy_clipboard),
+ focus_tracker);
+
+ g_object_notify (G_OBJECT (focus_tracker), "copy-clipboard-action");
+}
+
+GtkAction *
+e_focus_tracker_get_paste_clipboard_action (EFocusTracker *focus_tracker)
+{
+ g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
+
+ return focus_tracker->priv->paste_clipboard;
+}
+
+void
+e_focus_tracker_set_paste_clipboard_action (EFocusTracker *focus_tracker,
+ GtkAction *paste_clipboard)
+{
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ if (paste_clipboard != NULL) {
+ g_return_if_fail (GTK_IS_ACTION (paste_clipboard));
+ g_object_ref (paste_clipboard);
+ }
+
+ if (focus_tracker->priv->paste_clipboard != NULL) {
+ g_signal_handlers_disconnect_matched (
+ focus_tracker->priv->paste_clipboard,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
+ focus_tracker);
+ g_object_unref (focus_tracker->priv->paste_clipboard);
+ }
+
+ focus_tracker->priv->paste_clipboard = paste_clipboard;
+
+ if (paste_clipboard != NULL)
+ g_signal_connect_swapped (
+ paste_clipboard, "activate",
+ G_CALLBACK (e_focus_tracker_paste_clipboard),
+ focus_tracker);
+
+ g_object_notify (G_OBJECT (focus_tracker), "paste-clipboard-action");
+}
+
+GtkAction *
+e_focus_tracker_get_delete_selection_action (EFocusTracker *focus_tracker)
+{
+ g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
+
+ return focus_tracker->priv->delete_selection;
+}
+
+void
+e_focus_tracker_set_delete_selection_action (EFocusTracker *focus_tracker,
+ GtkAction *delete_selection)
+{
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ if (delete_selection != NULL) {
+ g_return_if_fail (GTK_IS_ACTION (delete_selection));
+ g_object_ref (delete_selection);
+ }
+
+ if (focus_tracker->priv->delete_selection != NULL) {
+ g_signal_handlers_disconnect_matched (
+ focus_tracker->priv->delete_selection,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
+ focus_tracker);
+ g_object_unref (focus_tracker->priv->delete_selection);
+ }
+
+ focus_tracker->priv->delete_selection = delete_selection;
+
+ if (delete_selection != NULL)
+ g_signal_connect_swapped (
+ delete_selection, "activate",
+ G_CALLBACK (e_focus_tracker_delete_selection),
+ focus_tracker);
+
+ g_object_notify (G_OBJECT (focus_tracker), "delete-selection-action");
+}
+
+GtkAction *
+e_focus_tracker_get_select_all_action (EFocusTracker *focus_tracker)
+{
+ g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
+
+ return focus_tracker->priv->select_all;
+}
+
+void
+e_focus_tracker_set_select_all_action (EFocusTracker *focus_tracker,
+ GtkAction *select_all)
+{
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ if (select_all != NULL) {
+ g_return_if_fail (GTK_IS_ACTION (select_all));
+ g_object_ref (select_all);
+ }
+
+ if (focus_tracker->priv->select_all != NULL) {
+ g_signal_handlers_disconnect_matched (
+ focus_tracker->priv->select_all,
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
+ focus_tracker);
+ g_object_unref (focus_tracker->priv->select_all);
+ }
+
+ focus_tracker->priv->select_all = select_all;
+
+ if (select_all != NULL)
+ g_signal_connect_swapped (
+ select_all, "activate",
+ G_CALLBACK (e_focus_tracker_select_all),
+ focus_tracker);
+
+ g_object_notify (G_OBJECT (focus_tracker), "select-all-action");
+}
+
+void
+e_focus_tracker_update_actions (EFocusTracker *focus_tracker)
+{
+ GtkClipboard *clipboard;
+
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ /* Request clipboard targets asynchronously. */
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+
+ gtk_clipboard_request_targets (
+ clipboard, (GtkClipboardTargetsReceivedFunc)
+ focus_tracker_targets_received_cb,
+ g_object_ref (focus_tracker));
+}
+
+void
+e_focus_tracker_cut_clipboard (EFocusTracker *focus_tracker)
+{
+ GtkWidget *focus;
+
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ focus = e_focus_tracker_get_focus (focus_tracker);
+
+ if (GTK_IS_EDITABLE (focus))
+ gtk_editable_cut_clipboard (GTK_EDITABLE (focus));
+
+ else if (E_IS_SELECTABLE (focus))
+ e_selectable_cut_clipboard (E_SELECTABLE (focus));
+}
+
+void
+e_focus_tracker_copy_clipboard (EFocusTracker *focus_tracker)
+{
+ GtkWidget *focus;
+
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ focus = e_focus_tracker_get_focus (focus_tracker);
+
+ if (GTK_IS_EDITABLE (focus))
+ gtk_editable_copy_clipboard (GTK_EDITABLE (focus));
+
+ else if (E_IS_SELECTABLE (focus))
+ e_selectable_copy_clipboard (E_SELECTABLE (focus));
+}
+
+void
+e_focus_tracker_paste_clipboard (EFocusTracker *focus_tracker)
+{
+ GtkWidget *focus;
+
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ focus = e_focus_tracker_get_focus (focus_tracker);
+
+ if (GTK_IS_EDITABLE (focus))
+ gtk_editable_paste_clipboard (GTK_EDITABLE (focus));
+
+ else if (E_IS_SELECTABLE (focus))
+ e_selectable_paste_clipboard (E_SELECTABLE (focus));
+}
+
+void
+e_focus_tracker_delete_selection (EFocusTracker *focus_tracker)
+{
+ GtkWidget *focus;
+
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ focus = e_focus_tracker_get_focus (focus_tracker);
+
+ if (GTK_IS_EDITABLE (focus))
+ gtk_editable_delete_selection (GTK_EDITABLE (focus));
+
+ else if (E_IS_SELECTABLE (focus))
+ e_selectable_delete_selection (E_SELECTABLE (focus));
+}
+
+void
+e_focus_tracker_select_all (EFocusTracker *focus_tracker)
+{
+ GtkWidget *focus;
+
+ g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
+
+ focus = e_focus_tracker_get_focus (focus_tracker);
+
+ if (GTK_IS_EDITABLE (focus))
+ gtk_editable_select_region (GTK_EDITABLE (focus), 0, -1);
+
+ else if (E_IS_SELECTABLE (focus))
+ e_selectable_select_all (E_SELECTABLE (focus));
+}
diff --git a/widgets/misc/e-focus-tracker.h b/widgets/misc/e-focus-tracker.h
new file mode 100644
index 0000000000..679cc4b655
--- /dev/null
+++ b/widgets/misc/e-focus-tracker.h
@@ -0,0 +1,99 @@
+/*
+ * e-focus-tracker.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_FOCUS_TRACKER_H
+#define E_FOCUS_TRACKER_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_FOCUS_TRACKER \
+ (e_focus_tracker_get_type ())
+#define E_FOCUS_TRACKER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_FOCUS_TRACKER, EFocusTracker))
+#define E_FOCUS_TRACKER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_FOCUS_TRACKER, EFocusTrackerClass))
+#define E_IS_FOCUS_TRACKER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_FOCUS_TRACKER))
+#define E_IS_FOCUS_TRACKER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_FOCUS_TRACKER))
+#define E_FOCUS_TRACKER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_FOCUS_TRACKER, EFocusTrackerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EFocusTracker EFocusTracker;
+typedef struct _EFocusTrackerClass EFocusTrackerClass;
+typedef struct _EFocusTrackerPrivate EFocusTrackerPrivate;
+
+struct _EFocusTracker {
+ GObject parent;
+ EFocusTrackerPrivate *priv;
+};
+
+struct _EFocusTrackerClass {
+ GObjectClass parent_class;
+};
+
+GType e_focus_tracker_get_type (void);
+EFocusTracker * e_focus_tracker_new (GtkWindow *window);
+GtkWidget * e_focus_tracker_get_focus (EFocusTracker *focus_tracker);
+GtkWindow * e_focus_tracker_get_window (EFocusTracker *focus_tracker);
+GtkAction * e_focus_tracker_get_cut_clipboard_action
+ (EFocusTracker *focus_tracker);
+void e_focus_tracker_set_cut_clipboard_action
+ (EFocusTracker *focus_tracker,
+ GtkAction *cut_clipboard);
+GtkAction * e_focus_tracker_get_copy_clipboard_action
+ (EFocusTracker *focus_tracker);
+void e_focus_tracker_set_copy_clipboard_action
+ (EFocusTracker *focus_tracker,
+ GtkAction *copy_clipboard);
+GtkAction * e_focus_tracker_get_paste_clipboard_action
+ (EFocusTracker *focus_tracker);
+void e_focus_tracker_set_paste_clipboard_action
+ (EFocusTracker *focus_tracker,
+ GtkAction *paste_clipboard);
+GtkAction * e_focus_tracker_get_delete_selection_action
+ (EFocusTracker *focus_tracker);
+void e_focus_tracker_set_delete_selection_action
+ (EFocusTracker *focus_tracker,
+ GtkAction *delete_selection);
+GtkAction * e_focus_tracker_get_select_all_action
+ (EFocusTracker *focus_tracker);
+void e_focus_tracker_set_select_all_action
+ (EFocusTracker *focus_tracker,
+ GtkAction *select_all);
+void e_focus_tracker_update_actions (EFocusTracker *focus_tracker);
+void e_focus_tracker_cut_clipboard (EFocusTracker *focus_tracker);
+void e_focus_tracker_copy_clipboard (EFocusTracker *focus_tracker);
+void e_focus_tracker_paste_clipboard (EFocusTracker *focus_tracker);
+void e_focus_tracker_delete_selection(EFocusTracker *focus_tracker);
+void e_focus_tracker_select_all (EFocusTracker *focus_tracker);
+
+G_END_DECLS
+
+#endif /* E_FOCUS_TRACKER_H */
diff --git a/widgets/misc/e-selectable.c b/widgets/misc/e-selectable.c
new file mode 100644
index 0000000000..95cd2bb06f
--- /dev/null
+++ b/widgets/misc/e-selectable.c
@@ -0,0 +1,133 @@
+/*
+ * e-selectable.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-selectable.h"
+
+GType
+e_selectable_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (ESelectableInterface),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) NULL,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ 0, /* instance_size */
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ G_TYPE_INTERFACE, "ESelectable", &type_info, 0);
+
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+void
+e_selectable_update_actions (ESelectable *selectable,
+ EFocusTracker *focus_tracker,
+ GdkAtom *clipboard_targets,
+ gint n_clipboard_targets)
+{
+ ESelectableInterface *interface;
+
+ g_return_if_fail (E_IS_SELECTABLE (selectable));
+
+ interface = E_SELECTABLE_GET_INTERFACE (selectable);
+ g_return_if_fail (interface->update_actions != NULL);
+
+ return interface->update_actions (
+ selectable, focus_tracker,
+ clipboard_targets, n_clipboard_targets);
+}
+
+void
+e_selectable_cut_clipboard (ESelectable *selectable)
+{
+ ESelectableInterface *interface;
+
+ g_return_if_fail (E_IS_SELECTABLE (selectable));
+
+ interface = E_SELECTABLE_GET_INTERFACE (selectable);
+
+ if (interface->cut_clipboard != NULL)
+ interface->cut_clipboard (selectable);
+}
+
+void
+e_selectable_copy_clipboard (ESelectable *selectable)
+{
+ ESelectableInterface *interface;
+
+ g_return_if_fail (E_IS_SELECTABLE (selectable));
+
+ interface = E_SELECTABLE_GET_INTERFACE (selectable);
+
+ if (interface->copy_clipboard != NULL)
+ interface->copy_clipboard (selectable);
+}
+
+void
+e_selectable_paste_clipboard (ESelectable *selectable)
+{
+ ESelectableInterface *interface;
+
+ g_return_if_fail (E_IS_SELECTABLE (selectable));
+
+ interface = E_SELECTABLE_GET_INTERFACE (selectable);
+
+ if (interface->paste_clipboard != NULL)
+ interface->paste_clipboard (selectable);
+}
+
+void
+e_selectable_delete_selection (ESelectable *selectable)
+{
+ ESelectableInterface *interface;
+
+ g_return_if_fail (E_IS_SELECTABLE (selectable));
+
+ interface = E_SELECTABLE_GET_INTERFACE (selectable);
+
+ if (interface->delete_selection != NULL)
+ interface->delete_selection (selectable);
+}
+
+void
+e_selectable_select_all (ESelectable *selectable)
+{
+ ESelectableInterface *interface;
+
+ g_return_if_fail (E_IS_SELECTABLE (selectable));
+
+ interface = E_SELECTABLE_GET_INTERFACE (selectable);
+
+ if (interface->select_all != NULL)
+ interface->select_all (selectable);
+}
diff --git a/widgets/misc/e-selectable.h b/widgets/misc/e-selectable.h
new file mode 100644
index 0000000000..fca400ce65
--- /dev/null
+++ b/widgets/misc/e-selectable.h
@@ -0,0 +1,76 @@
+/*
+ * e-selectable.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_SELECTABLE_H
+#define E_SELECTABLE_H
+
+#include <gtk/gtk.h>
+#include <misc/e-focus-tracker.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SELECTABLE \
+ (e_selectable_get_type ())
+#define E_SELECTABLE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SELECTABLE, ESelectable))
+#define E_IS_SELECTABLE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SELECTABLE))
+#define E_SELECTABLE_GET_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE \
+ ((obj), E_TYPE_SELECTABLE, ESelectableInterface))
+
+G_BEGIN_DECLS
+
+typedef struct _ESelectable ESelectable;
+typedef struct _ESelectableInterface ESelectableInterface;
+
+struct _ESelectableInterface {
+ GTypeInterface parent_iface;
+
+ /* Required Methods */
+ void (*update_actions) (ESelectable *selectable,
+ EFocusTracker *focus_tracker,
+ GdkAtom *clipboard_targets,
+ gint n_clipboard_targets);
+
+ /* Optional Methods */
+ void (*cut_clipboard) (ESelectable *selectable);
+ void (*copy_clipboard) (ESelectable *selectable);
+ void (*paste_clipboard) (ESelectable *selectable);
+ void (*delete_selection) (ESelectable *selectable);
+ void (*select_all) (ESelectable *selectable);
+};
+
+GType e_selectable_get_type (void);
+void e_selectable_update_actions (ESelectable *selectable,
+ EFocusTracker *focus_tracker,
+ GdkAtom *clipboard_targets,
+ gint n_clipboard_targets);
+void e_selectable_cut_clipboard (ESelectable *selectable);
+void e_selectable_copy_clipboard (ESelectable *selectable);
+void e_selectable_paste_clipboard (ESelectable *selectable);
+void e_selectable_delete_selection (ESelectable *selectable);
+void e_selectable_select_all (ESelectable *selectable);
+
+G_END_DECLS
+
+#endif /* E_SELECTABLE_H */
diff --git a/widgets/misc/e-signature-editor.c b/widgets/misc/e-signature-editor.c
index 9266425494..91a4d81c8d 100644
--- a/widgets/misc/e-signature-editor.c
+++ b/widgets/misc/e-signature-editor.c
@@ -26,6 +26,7 @@
#include <e-util/e-alert-dialog.h>
#include <e-util/e-signature-utils.h>
+#include <misc/e-web-view.h>
#define E_SIGNATURE_EDITOR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -33,11 +34,13 @@
enum {
PROP_0,
+ PROP_FOCUS_TRACKER,
PROP_SIGNATURE
};
struct _ESignatureEditorPrivate {
GtkActionGroup *action_group;
+ EFocusTracker *focus_tracker;
ESignature *signature;
GtkWidget *entry;
gchar *original_name;
@@ -255,6 +258,12 @@ signature_editor_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_FOCUS_TRACKER:
+ g_value_set_object (
+ value, e_signature_editor_get_focus_tracker (
+ E_SIGNATURE_EDITOR (object)));
+ return;
+
case PROP_SIGNATURE:
g_value_set_object (
value, e_signature_editor_get_signature (
@@ -277,6 +286,11 @@ signature_editor_dispose (GObject *object)
priv->action_group = NULL;
}
+ if (priv->focus_tracker != NULL) {
+ g_object_unref (priv->focus_tracker);
+ priv->focus_tracker = NULL;
+ }
+
if (priv->signature != NULL) {
g_object_unref (priv->signature);
priv->signature = NULL;
@@ -320,6 +334,16 @@ signature_editor_class_init (ESignatureEditorClass *class)
g_object_class_install_property (
object_class,
+ PROP_FOCUS_TRACKER,
+ g_param_spec_object (
+ "focus-tracker",
+ NULL,
+ NULL,
+ E_TYPE_FOCUS_TRACKER,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (
+ object_class,
PROP_SIGNATURE,
g_param_spec_object (
"signature",
@@ -333,7 +357,10 @@ static void
signature_editor_init (ESignatureEditor *editor)
{
GtkActionGroup *action_group;
+ EFocusTracker *focus_tracker;
+ GtkhtmlEditor *gtkhtml_editor;
GtkUIManager *ui_manager;
+ GtkAction *action;
GtkWidget *container;
GtkWidget *widget;
GtkWidget *vbox;
@@ -342,7 +369,8 @@ signature_editor_init (ESignatureEditor *editor)
editor->priv = E_SIGNATURE_EDITOR_GET_PRIVATE (editor);
vbox = GTKHTML_EDITOR (editor)->vbox;
- ui_manager = gtkhtml_editor_get_ui_manager (GTKHTML_EDITOR (editor));
+ gtkhtml_editor = GTKHTML_EDITOR (editor);
+ ui_manager = gtkhtml_editor_get_ui_manager (gtkhtml_editor);
gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
handle_error (&error);
@@ -383,6 +411,28 @@ signature_editor_init (ESignatureEditor *editor)
G_CALLBACK (signature_editor_delete_event_cb), NULL);
e_signature_editor_set_signature (editor, NULL);
+
+ /* Configure an EFocusTracker to manage selection actions.
+ *
+ * XXX GtkhtmlEditor does not manage its own selection actions,
+ * which is technically a bug but works in our favor here
+ * because it won't cause any conflicts with EFocusTracker. */
+
+ focus_tracker = e_focus_tracker_new (GTK_WINDOW (editor));
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "cut");
+ e_focus_tracker_set_cut_clipboard_action (focus_tracker, action);
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "copy");
+ e_focus_tracker_set_copy_clipboard_action (focus_tracker, action);
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "paste");
+ e_focus_tracker_set_paste_clipboard_action (focus_tracker, action);
+
+ action = gtkhtml_editor_get_action (gtkhtml_editor, "select-all");
+ e_focus_tracker_set_select_all_action (focus_tracker, action);
+
+ editor->priv->focus_tracker = focus_tracker;
}
GType
@@ -415,7 +465,17 @@ e_signature_editor_get_type (void)
GtkWidget *
e_signature_editor_new (void)
{
- return g_object_new (E_TYPE_SIGNATURE_EDITOR, NULL);
+ return g_object_new (
+ E_TYPE_SIGNATURE_EDITOR,
+ "html", e_web_view_new (), NULL);
+}
+
+EFocusTracker *
+e_signature_editor_get_focus_tracker (ESignatureEditor *editor)
+{
+ g_return_val_if_fail (E_IS_SIGNATURE_EDITOR (editor), NULL);
+
+ return editor->priv->focus_tracker;
}
ESignature *
diff --git a/widgets/misc/e-signature-editor.h b/widgets/misc/e-signature-editor.h
index 1e8b88a909..6d9f4a9b61 100644
--- a/widgets/misc/e-signature-editor.h
+++ b/widgets/misc/e-signature-editor.h
@@ -24,6 +24,7 @@
#include <gtkhtml-editor.h>
#include <e-util/e-signature.h>
+#include <misc/e-focus-tracker.h>
/* Standard GObject macros */
#define E_TYPE_SIGNATURE_EDITOR \
@@ -61,6 +62,8 @@ struct _ESignatureEditorClass {
GType e_signature_editor_get_type (void);
GtkWidget * e_signature_editor_new (void);
+EFocusTracker * e_signature_editor_get_focus_tracker
+ (ESignatureEditor *editor);
ESignature * e_signature_editor_get_signature (ESignatureEditor *editor);
void e_signature_editor_set_signature (ESignatureEditor *editor,
ESignature *signature);
diff --git a/widgets/misc/e-web-view.c b/widgets/misc/e-web-view.c
index f52d7399eb..a873731014 100644
--- a/widgets/misc/e-web-view.c
+++ b/widgets/misc/e-web-view.c
@@ -33,6 +33,7 @@
#include "e-util/e-plugin-ui.h"
#include "e-popup-action.h"
+#include "e-selectable.h"
#define E_WEB_VIEW_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -89,7 +90,7 @@ static guint signals[LAST_SIGNAL];
static const gchar *ui =
"<ui>"
" <popup name='context'>"
-" <menuitem action='clipboard-copy'/>"
+" <menuitem action='copy-clipboard'/>"
" <separator/>"
" <placeholder name='custom-actions-1'>"
" <menuitem action='open'/>"
@@ -240,10 +241,10 @@ web_view_request_read_cb (GFile *file,
}
static void
-action_clipboard_copy_cb (GtkAction *action,
+action_copy_clipboard_cb (GtkAction *action,
EWebView *web_view)
{
- e_web_view_clipboard_copy (web_view);
+ e_web_view_copy_clipboard (web_view);
}
static void
@@ -372,12 +373,12 @@ static GtkActionEntry mailto_entries[] = {
static GtkActionEntry selection_entries[] = {
- { "clipboard-copy",
+ { "copy-clipboard",
GTK_STOCK_COPY,
NULL,
NULL,
- N_("Copy the selection to the clipboard"),
- G_CALLBACK (action_clipboard_copy_cb) },
+ N_("Copy the selection"),
+ G_CALLBACK (action_copy_clipboard_cb) },
};
static GtkActionEntry standard_entries[] = {
@@ -859,6 +860,52 @@ web_view_update_actions (EWebView *web_view)
}
static void
+web_view_selectable_update_actions (ESelectable *selectable,
+ EFocusTracker *focus_tracker,
+ GdkAtom *clipboard_targets,
+ gint n_clipboard_targets)
+{
+ EWebView *web_view;
+ GtkAction *action;
+ const gchar *tooltip;
+ gboolean sensitive;
+
+ web_view = E_WEB_VIEW (selectable);
+
+ /* Copy Clipboard */
+
+ action = e_web_view_get_action (web_view, "copy-clipboard");
+ sensitive = gtk_action_get_sensitive (action);
+ tooltip = gtk_action_get_tooltip (action);
+
+ action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_tooltip (action, tooltip);
+
+ /* Select All */
+
+ action = e_web_view_get_action (web_view, "select-all");
+ sensitive = gtk_action_get_sensitive (action);
+ tooltip = gtk_action_get_tooltip (action);
+
+ action = e_focus_tracker_get_select_all_action (focus_tracker);
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_tooltip (action, tooltip);
+}
+
+static void
+web_view_selectable_copy_clipboard (ESelectable *selectable)
+{
+ e_web_view_copy_clipboard (E_WEB_VIEW (selectable));
+}
+
+static void
+web_view_selectable_select_all (ESelectable *selectable)
+{
+ e_web_view_select_all (E_WEB_VIEW (selectable));
+}
+
+static void
web_view_class_init (EWebViewClass *class)
{
GObjectClass *object_class;
@@ -1010,6 +1057,14 @@ web_view_class_init (EWebViewClass *class)
}
static void
+web_view_selectable_init (ESelectableInterface *interface)
+{
+ interface->update_actions = web_view_selectable_update_actions;
+ interface->copy_clipboard = web_view_selectable_copy_clipboard;
+ interface->select_all = web_view_selectable_select_all;
+}
+
+static void
web_view_init (EWebView *web_view)
{
GtkUIManager *ui_manager;
@@ -1140,8 +1195,17 @@ e_web_view_get_type (void)
NULL /* value_table */
};
+ static const GInterfaceInfo selectable_info = {
+ (GInterfaceInitFunc) web_view_selectable_init,
+ (GInterfaceFinalizeFunc) NULL,
+ NULL /* interface_data */
+ };
+
type = g_type_register_static (
GTK_TYPE_HTML, "EWebView", &type_info, 0);
+
+ g_type_add_interface_static (
+ type, E_TYPE_SELECTABLE, &selectable_info);
}
return type;
@@ -1411,7 +1475,7 @@ e_web_view_extract_uri (EWebView *web_view,
}
void
-e_web_view_clipboard_copy (EWebView *web_view)
+e_web_view_copy_clipboard (EWebView *web_view)
{
g_return_if_fail (E_IS_WEB_VIEW (web_view));
diff --git a/widgets/misc/e-web-view.h b/widgets/misc/e-web-view.h
index 4a30b4bd80..123965c7d0 100644
--- a/widgets/misc/e-web-view.h
+++ b/widgets/misc/e-web-view.h
@@ -118,7 +118,7 @@ GtkActionGroup *e_web_view_get_action_group (EWebView *web_view,
gchar * e_web_view_extract_uri (EWebView *web_view,
GdkEventButton *event,
GtkHTML *frame);
-void e_web_view_clipboard_copy (EWebView *web_view);
+void e_web_view_copy_clipboard (EWebView *web_view);
gboolean e_web_view_is_selection_active (EWebView *web_view);
gboolean e_web_view_scroll_forward (EWebView *web_view);
gboolean e_web_view_scroll_backward (EWebView *web_view);