[evolution/webkit-composer: 36/130] Initial support for custom context menu
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/webkit-composer: 36/130] Initial support for custom context menu
- Date: Sat, 19 Jan 2013 14:30:08 +0000 (UTC)
commit cb56fc8946405e66e4d3225086051bba157efd93
Author: Dan VrÃtil <dvratil redhat com>
Date: Mon Aug 13 14:45:42 2012 +0200
Initial support for custom context menu
e-util/e-editor-widget.c | 41 +++++++++++
e-util/e-editor-widget.h | 5 +-
e-util/e-editor.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++
e-util/e-editor.h | 3 +
4 files changed, 214 insertions(+), 1 deletions(-)
---
diff --git a/e-util/e-editor-widget.c b/e-util/e-editor-widget.c
index 6b648c0..eb6d78d 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -25,6 +25,7 @@
#include "e-emoticon-chooser.h"
#include <e-util/e-util.h>
+#include <e-util/e-marshal.h>
#include <glib/gi18n-lib.h>
#include <gdk/gdkkeysyms.h>
@@ -70,6 +71,13 @@ enum {
PROP_CAN_UNDO
};
+enum {
+ POPUP_EVENT,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
static WebKitDOMRange *
editor_widget_get_dom_range (EEditorWidget *widget)
{
@@ -152,6 +160,28 @@ editor_widget_selection_changed_cb (EEditorWidget *widget,
}
}
+static gboolean
+editor_widget_button_press_event (GtkWidget *gtk_widget,
+ GdkEventButton *event)
+{
+ gboolean event_handled;
+
+ if (event->button != 3) {
+ event_handled = FALSE;
+ } else {
+ g_signal_emit (
+ gtk_widget, signals[POPUP_EVENT],
+ 0, event, &event_handled);
+ }
+
+ if (event_handled) {
+ return TRUE;
+ }
+
+ /* Chain up to parent implementation */
+ return GTK_WIDGET_CLASS (e_editor_widget_parent_class)->button_press_event (gtk_widget, event);
+}
+
/* Based on original use_pictograms() from GtkHTML */
static const gchar *emoticons_chars =
/* 0 */ "DO)(|/PQ*!"
@@ -476,6 +506,7 @@ e_editor_widget_class_init (EEditorWidgetClass *klass)
object_class->finalize = e_editor_widget_finalize;
widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->button_press_event = editor_widget_button_press_event;
widget_class->key_release_event = editor_widget_key_release_event;
klass->paste_clipboard_quoted = editor_widget_paste_clipboard_quoted;
@@ -585,6 +616,16 @@ e_editor_widget_class_init (EEditorWidgetClass *klass)
NULL,
FALSE,
G_PARAM_READABLE));
+
+ signals[POPUP_EVENT] = g_signal_new (
+ "popup-event",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EEditorWidgetClass, popup_event),
+ g_signal_accumulator_true_handled, NULL,
+ e_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN, 1,
+ GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
}
static void
diff --git a/e-util/e-editor-widget.h b/e-util/e-editor-widget.h
index 487c1a0..1f08c4b 100644
--- a/e-util/e-editor-widget.h
+++ b/e-util/e-editor-widget.h
@@ -73,7 +73,10 @@ struct _EEditorWidget {
struct _EEditorWidgetClass {
WebKitWebViewClass parent_class;
- void (*paste_clipboard_quoted) (EEditorWidget *widget);
+ void (*paste_clipboard_quoted) (EEditorWidget *widget);
+
+ gboolean (*popup_event) (EEditorWidget *widget,
+ GdkEventButton *event);
};
GType e_editor_widget_get_type (void);
diff --git a/e-util/e-editor.c b/e-util/e-editor.c
index 238f166..892623f 100644
--- a/e-util/e-editor.c
+++ b/e-util/e-editor.c
@@ -21,6 +21,7 @@
#include "e-editor.h"
#include "e-editor-private.h"
+#include "e-editor-utils.h"
#include <glib/gi18n-lib.h>
@@ -34,6 +35,157 @@ enum {
PROP_FILENAME
};
+enum {
+ UPDATE_ACTIONS,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+editor_update_actions (EEditor *editor,
+ GdkEventButton *event)
+{
+ WebKitWebView *webview;
+ WebKitHitTestResult *hit_test;
+ WebKitHitTestResultContext context;
+ WebKitDOMNode *node;
+ EEditorWidget *widget;
+ GtkUIManager *manager;
+ GtkActionGroup *action_group;
+ GList *list;
+ gboolean visible;
+ guint merge_id;
+
+ widget = e_editor_get_editor_widget (editor);
+ webview = WEBKIT_WEB_VIEW (widget);
+ manager = e_editor_get_ui_manager (editor);
+
+ /* Update context menu item visibility. */
+ hit_test = webkit_web_view_get_hit_test_result (webview, event);
+ g_object_get (
+ G_OBJECT (hit_test),
+ "context", &context,
+ "inner-node", &node, NULL);
+
+ visible = (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE);
+ gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_IMAGE), visible);
+
+ visible = (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK);
+ gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_LINK), visible);
+
+ visible = (WEBKIT_DOM_IS_HTMLHR_ELEMENT (node));
+ gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_RULE), visible);
+
+ visible = (webkit_dom_node_get_node_type (node) == 3);
+ gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_TEXT), visible);
+
+ visible =
+ gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_IMAGE)) ||
+ gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_LINK)) ||
+ gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_TEXT));
+ gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_PARAGRAPH), visible);
+
+ /* Set to visible if any of these are true:
+ * - Selection is active and contains a link.
+ * - Cursor is on a link.
+ * - Cursor is on an image that has a URL or target.
+ */
+ visible = (e_editor_dom_node_get_parent_element (
+ node, WEBKIT_TYPE_DOM_HTML_ANCHOR_ELEMENT) != NULL);
+ gtk_action_set_visible (ACTION (CONTEXT_REMOVE_LINK), visible);
+
+
+ visible = (e_editor_dom_node_get_parent_element (
+ node, WEBKIT_TYPE_DOM_HTML_TABLE_CELL_ELEMENT) != NULL);
+ gtk_action_set_visible (ACTION (CONTEXT_DELETE_CELL), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_DELETE_COLUMN), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_DELETE_ROW), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_DELETE_TABLE), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_INSERT_COLUMN_AFTER), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_INSERT_COLUMN_BEFORE), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_INSERT_ROW_ABOVE), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_INSERT_ROW_BELOW), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_INSERT_TABLE), visible);
+ gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_CELL), visible);
+
+ /* Note the |= (cursor must be in a table cell). */
+ visible |= (e_editor_dom_node_get_parent_element (
+ node, WEBKIT_TYPE_DOM_HTML_TABLE_ELEMENT) != NULL);
+ gtk_action_set_visible (ACTION (CONTEXT_PROPERTIES_TABLE), visible);
+
+ /********************** Spell Check Suggestions **********************/
+
+ /* FIXME WEBKIT No spellcheching for now
+ object = html->engine->cursor->object;
+ action_group = editor->priv->suggestion_actions;
+
+ // Remove the old content from the context menu.
+ merge_id = editor->priv->spell_suggestions_merge_id;
+ if (merge_id > 0) {
+ gtk_ui_manager_remove_ui (manager, merge_id);
+ editor->priv->spell_suggestions_merge_id = 0;
+ }
+
+ // Clear the action group for spelling suggestions.
+ list = gtk_action_group_list_actions (action_group);
+ while (list != NULL) {
+ GtkAction *action = list->data;
+
+ gtk_action_group_remove_action (action_group, action);
+ list = g_list_delete_link (list, list);
+ }
+
+ // Decide if we should show spell checking items.
+ visible =
+ !html_engine_is_selection_active (html->engine) &&
+ object != NULL && html_object_is_text (object) &&
+ !html_engine_spell_word_is_valid (html->engine);
+ action_group = editor->priv->spell_check_actions;
+ gtk_action_group_set_visible (action_group, visible);
+
+ // Exit early if spell checking items are invisible.
+ if (!visible)
+ return;
+
+ list = editor->priv->active_spell_checkers;
+ merge_id = gtk_ui_manager_new_merge_id (manager);
+ editor->priv->spell_suggestions_merge_id = merge_id;
+
+ // Handle a single active language as a special case.
+ if (g_list_length (list) == 1) {
+ editor_inline_spelling_suggestions (editor, list->data);
+ return;
+ }
+
+ // Add actions and context menu content for active languages
+ g_list_foreach (list, (GFunc) editor_spell_checkers_foreach, editor);
+ */
+}
+
+static gboolean
+editor_show_popup (EEditor *editor,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ GtkWidget *menu;
+
+ menu = e_editor_get_managed_widget (editor, "/context-menu");
+
+ g_signal_emit(editor, signals[UPDATE_ACTIONS], 0, event);
+
+ if (event != NULL)
+ gtk_menu_popup (
+ GTK_MENU (menu), NULL, NULL, NULL,
+ user_data, event->button, event->time);
+ else
+ gtk_menu_popup (
+ GTK_MENU (menu), NULL, NULL, NULL,
+ user_data, 0, gtk_get_current_event_time ());
+
+ return TRUE;
+}
+
static gchar *
editor_find_ui_file (const gchar *basename)
{
@@ -145,6 +297,8 @@ editor_constructed (GObject *object)
widget = GTK_WIDGET (e_editor_get_editor_widget (editor));
gtk_container_add (GTK_CONTAINER (priv->scrolled_window), widget);
gtk_widget_show (widget);
+ g_signal_connect_swapped (widget, "popup-event",
+ G_CALLBACK (editor_show_popup), editor);
/* Add some combo boxes to the "edit" toolbar. */
@@ -333,6 +487,8 @@ e_editor_class_init (EEditorClass *klass)
object_class->constructed = editor_constructed;
object_class->dispose = editor_dispose;
+ klass->update_actions = editor_update_actions;
+
g_object_class_install_property (
object_class,
PROP_FILENAME,
@@ -342,6 +498,16 @@ e_editor_class_init (EEditorClass *klass)
NULL,
NULL,
G_PARAM_READWRITE));
+
+ signals[UPDATE_ACTIONS] = g_signal_new (
+ "update-actions",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EEditorClass, update_actions),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
}
static void
diff --git a/e-util/e-editor.h b/e-util/e-editor.h
index 9b878eb..b39e6a1 100644
--- a/e-util/e-editor.h
+++ b/e-util/e-editor.h
@@ -58,6 +58,9 @@ struct _EEditor {
struct _EEditorClass {
GtkBoxClass parent_class;
+
+ void (*update_actions) (EEditor *editor,
+ GdkEventButton *event);
};
GType e_editor_get_type (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]