[gtk/wip/matthiasc/context-menu: 4/4] label: Redo context menus
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/context-menu: 4/4] label: Redo context menus
- Date: Sun, 27 Jan 2019 21:46:37 +0000 (UTC)
commit a718d3e0a65dc3fda6a554209a8dac1c3289359a
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Jan 27 16:43:54 2019 -0500
label: Redo context menus
Drop the ::populate-popup signal and add
gtk_label_get_default_context_menu(), as was done
in GtkEntry.
gtk/gtklabel.c | 283 ++++++++++++++++++++++++++++++++++-----------------------
gtk/gtklabel.h | 8 +-
2 files changed, 174 insertions(+), 117 deletions(-)
---
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 57db38485b..1cec52dae5 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -260,6 +260,8 @@ struct _GtkLabelPrivate
PangoAttrList *markup_attrs;
PangoLayout *layout;
+ GActionMap *context_actions;
+
gchar *label;
gchar *text;
@@ -352,7 +354,6 @@ struct _GtkLabelSelectionInfo
enum {
MOVE_CURSOR,
COPY_CLIPBOARD,
- POPULATE_POPUP,
ACTIVATE_LINK,
ACTIVATE_CURRENT_LINK,
LAST_SIGNAL
@@ -545,6 +546,9 @@ static void gtk_label_drag_gesture_update (GtkGestureDrag *gesture,
gdouble offset_y,
GtkLabel *label);
+static void gtk_label_add_context_actions (GtkLabel *label);
+static void update_clipboard_actions (GtkLabel *label);
+
static GtkSizeRequestMode gtk_label_get_request_mode (GtkWidget *widget);
static void gtk_label_measure (GtkWidget *widget,
GtkOrientation orientation,
@@ -554,6 +558,8 @@ static void gtk_label_measure (GtkWidget *widget,
int *minimum_baseline,
int *natural_baseline);
+
+
static GtkBuildableIface *buildable_parent_iface = NULL;
G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_WIDGET,
@@ -674,28 +680,6 @@ gtk_label_class_init (GtkLabelClass *class)
NULL,
G_TYPE_NONE, 0);
- /**
- * GtkLabel::populate-popup:
- * @label: The label on which the signal is emitted
- * @menu: the menu that is being populated
- *
- * The ::populate-popup signal gets emitted before showing the
- * context menu of the label. Note that only selectable labels
- * have context menus.
- *
- * If you need to add items to the context menu, connect
- * to this signal and append your menuitems to the @menu.
- */
- signals[POPULATE_POPUP] =
- g_signal_new (I_("populate-popup"),
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkLabelClass, populate_popup),
- NULL, NULL,
- NULL,
- G_TYPE_NONE, 1,
- GTK_TYPE_MENU);
-
/**
* GtkLabel::activate-current-link:
* @label: The label on which the signal was emitted
@@ -1301,6 +1285,8 @@ gtk_label_init (GtkLabel *label)
priv->mnemonic_window = NULL;
priv->mnemonics_visible = TRUE;
+
+ gtk_label_add_context_actions (label);
}
@@ -3183,6 +3169,8 @@ gtk_label_finalize (GObject *object)
gtk_label_clear_links (label);
g_free (priv->select_info);
+ g_clear_object (&priv->context_actions);
+
G_OBJECT_CLASS (gtk_label_parent_class)->finalize (object);
}
@@ -5114,6 +5102,7 @@ gtk_label_set_selectable (GtkLabel *label,
g_object_notify_by_pspec (G_OBJECT (label), label_props[PROP_SELECTION_BOUND]);
g_object_thaw_notify (G_OBJECT (label));
gtk_widget_queue_draw (GTK_WIDGET (label));
+ update_clipboard_actions (label);
}
}
@@ -5291,6 +5280,7 @@ gtk_label_select_region_index (GtkLabel *label,
gtk_widget_queue_draw (GTK_WIDGET (label));
g_object_thaw_notify (G_OBJECT (label));
+ update_clipboard_actions (label);
}
}
@@ -5968,74 +5958,175 @@ gtk_label_select_all (GtkLabel *label)
gtk_label_select_region_index (label, 0, strlen (priv->text));
}
-/* Quick hack of a popup menu
- */
static void
-activate_cb (GtkWidget *menuitem,
- GtkLabel *label)
+popup_menu_detach (GtkWidget *attach_widget,
+ GtkMenu *menu)
{
- const gchar *signal = g_object_get_qdata (G_OBJECT (menuitem), quark_gtk_signal);
- g_signal_emit_by_name (label, signal);
+ GtkLabel *label = GTK_LABEL (attach_widget);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+
+ if (priv->select_info)
+ priv->select_info->popup_menu = NULL;
+}
+
+static gboolean
+gtk_label_popup_menu (GtkWidget *widget)
+{
+ gtk_label_do_popup (GTK_LABEL (widget), NULL);
+
+ return TRUE;
}
static void
-append_action_signal (GtkLabel *label,
- GtkWidget *menu,
- const gchar *text,
- const gchar *signal,
- gboolean sensitive)
+open_link_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- GtkWidget *menuitem = gtk_menu_item_new_with_mnemonic (text);
+ GtkLabel *label = GTK_LABEL (user_data);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GtkLabelLink *link = NULL;
+ int pos = g_variant_get_int32 (parameter);
- g_object_set_qdata (G_OBJECT (menuitem), quark_gtk_signal, (char *)signal);
- g_signal_connect (menuitem, "activate",
- G_CALLBACK (activate_cb), label);
+ link = g_list_nth_data (priv->select_info->links, pos);
+ if (link == NULL)
+ return;
- gtk_widget_set_sensitive (menuitem, sensitive);
-
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ emit_activate_link (label, link);
}
static void
-popup_menu_detach (GtkWidget *attach_widget,
- GtkMenu *menu)
+copy_link_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- GtkLabel *label = GTK_LABEL (attach_widget);
+ GtkLabel *label = GTK_LABEL (user_data);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GtkLabelLink *link = NULL;
+ int pos = g_variant_get_int32 (parameter);
+ GdkClipboard *clipboard;
- if (priv->select_info)
- priv->select_info->popup_menu = NULL;
+ link = g_list_nth_data (priv->select_info->links, pos);
+ if (link == NULL)
+ return;
+
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label));
+ gdk_clipboard_set_text (clipboard, link->uri);
}
static void
-open_link_activate_cb (GtkMenuItem *menuitem,
- GtkLabel *label)
+copy_clipboard_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- GtkLabelLink *link;
+ g_signal_emit_by_name (user_data, "copy-clipboard");
+}
- link = g_object_get_qdata (G_OBJECT (menuitem), quark_link);
- emit_activate_link (label, link);
+static void
+select_all_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ gtk_label_select_all (GTK_LABEL (user_data));
}
static void
-copy_link_activate_cb (GtkMenuItem *menuitem,
- GtkLabel *label)
+update_clipboard_actions (GtkLabel *label)
{
- GtkLabelLink *link;
- GdkClipboard *clipboard;
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ gboolean have_selection = FALSE;
+ GAction *action;
- link = g_object_get_qdata (G_OBJECT (menuitem), quark_link);
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label));
- gdk_clipboard_set_text (clipboard, link->uri);
+ if (priv->select_info)
+ have_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
+
+ action = g_action_map_lookup_action (priv->context_actions, "copy-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), have_selection);
+ action = g_action_map_lookup_action (priv->context_actions, "select-all");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), gtk_label_get_selectable (label));
}
-static gboolean
-gtk_label_popup_menu (GtkWidget *widget)
+static void
+gtk_label_add_context_actions (GtkLabel *label)
{
- gtk_label_do_popup (GTK_LABEL (widget), NULL);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- return TRUE;
+ GActionEntry entries[] = {
+ { "open-link", open_link_activated, "i", NULL, NULL },
+ { "copy-link", copy_link_activated, "i", NULL, NULL },
+ { "cut-clipboard", NULL, NULL, NULL, NULL },
+ { "copy-clipboard", copy_clipboard_activated, NULL, NULL, NULL },
+ { "paste-clipboard", NULL, NULL, NULL, NULL },
+ { "delete-selection", NULL, NULL, NULL, NULL },
+ { "select-all", select_all_activated, NULL, NULL, NULL },
+ };
+
+ GSimpleActionGroup *actions = g_simple_action_group_new ();
+ GAction *action;
+
+ priv->context_actions = G_ACTION_MAP (actions);
+
+ g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), label);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "cut-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "copy-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "paste-clipboard");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "delete-selection");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+ action = g_action_map_lookup_action (G_ACTION_MAP (actions), "select-all");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+
+ gtk_widget_insert_action_group (GTK_WIDGET (label), "context", G_ACTION_GROUP (actions));
+}
+
+GMenuModel *
+gtk_label_get_default_context_menu (GtkLabel *label)
+{
+ GMenu *menu, *section;
+
+ menu = g_menu_new ();
+
+ section = g_menu_new ();
+ g_menu_append (section, _("Cu_t"), "context.cut-clipboard");
+ g_menu_append (section, _("_Copy"), "context.copy-clipboard");
+ g_menu_append (section, _("_Paste"), "context.paste-clipboard");
+ g_menu_append (section, _("_Delete"), "context.delete-selection");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
+ g_object_unref (section);
+
+ section = g_menu_new ();
+ g_menu_append (section, _("Select _All"), "context.select-all");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
+ g_object_unref (section);
+
+ return G_MENU_MODEL (menu);
+}
+
+static GMenuModel *
+get_link_context_menu (GtkLabel *label,
+ GtkLabelLink *link)
+{
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
+ GMenu *menu;
+ GMenuItem *item;
+ int index;
+
+ index = g_list_index (priv->select_info->links, link);
+
+ menu = g_menu_new ();
+ item = g_menu_item_new (_("_Open Link"), "context.open-link");
+ g_menu_item_set_attribute (item, "target", "i", index);
+ g_menu_append_item (menu, item);
+ g_object_unref (item);
+
+ item = g_menu_item_new (_("_Copy Link Address"), "context.copy-link");
+ g_menu_item_set_attribute (item, "target", "i", index);
+ g_menu_append_item (menu, item);
+ g_object_unref (item);
+
+ return G_MENU_MODEL (menu);
}
static void
@@ -6043,10 +6134,10 @@ gtk_label_do_popup (GtkLabel *label,
const GdkEvent *event)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- GtkWidget *menuitem;
GtkWidget *menu;
- gboolean have_selection;
+ GMenuModel *model;
GtkLabelLink *link;
+ gboolean have_selection;
if (!priv->select_info)
return;
@@ -6054,15 +6145,7 @@ gtk_label_do_popup (GtkLabel *label,
if (priv->select_info->popup_menu)
gtk_widget_destroy (priv->select_info->popup_menu);
- priv->select_info->popup_menu = menu = gtk_menu_new ();
- gtk_style_context_add_class (gtk_widget_get_style_context (menu),
- GTK_STYLE_CLASS_CONTEXT_MENU);
-
- gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (label), popup_menu_detach);
-
- have_selection =
- priv->select_info->selection_anchor != priv->select_info->selection_end;
-
+ have_selection = priv->select_info->selection_anchor != priv->select_info->selection_end;
if (event)
{
if (priv->select_info->link_clicked)
@@ -6074,48 +6157,22 @@ gtk_label_do_popup (GtkLabel *label,
link = gtk_label_get_focus_link (label);
if (!have_selection && link)
- {
- /* Open Link */
- menuitem = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
- g_object_set_qdata (G_OBJECT (menuitem), quark_link, link);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- g_signal_connect (G_OBJECT (menuitem), "activate",
- G_CALLBACK (open_link_activate_cb), label);
-
- /* Copy Link Address */
- menuitem = gtk_menu_item_new_with_mnemonic (_("Copy _Link Address"));
- g_object_set_qdata (G_OBJECT (menuitem), quark_link, link);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- g_signal_connect (G_OBJECT (menuitem), "activate",
- G_CALLBACK (copy_link_activate_cb), label);
- }
+ model = get_link_context_menu (label, link);
else
- {
- append_action_signal (label, menu, _("Cu_t"), "cut-clipboard", FALSE);
- append_action_signal (label, menu, _("_Copy"), "copy-clipboard", have_selection);
- append_action_signal (label, menu, _("_Paste"), "paste-clipboard", FALSE);
-
- menuitem = gtk_menu_item_new_with_mnemonic (_("_Delete"));
- gtk_widget_set_sensitive (menuitem, FALSE);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- menuitem = gtk_separator_menu_item_new ();
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
- menuitem = gtk_menu_item_new_with_mnemonic (_("Select _All"));
- g_signal_connect_swapped (menuitem, "activate",
- G_CALLBACK (gtk_label_select_all), label);
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+ {
+ model = gtk_widget_get_context_menu (GTK_WIDGET (label));
+ if (model)
+ g_object_ref (model);
+ else
+ model = gtk_label_get_default_context_menu (label);
}
- g_signal_emit (label, signals[POPULATE_POPUP], 0, menu);
+ priv->select_info->popup_menu = menu = gtk_menu_new_from_model (model);
+
+ g_object_set_data (G_OBJECT (menu), "link", link);
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (menu), GTK_STYLE_CLASS_CONTEXT_MENU);
+ gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (label), popup_menu_detach);
if (event && gdk_event_triggers_context_menu (event))
gtk_menu_popup_at_pointer (GTK_MENU (menu), event);
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index 834caa1fc4..2b97e90f3c 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -64,10 +64,6 @@ struct _GtkLabelClass
gboolean extend_selection);
void (* copy_clipboard) (GtkLabel *label);
- /* Hook to customize right-click popup for selectable labels */
- void (* populate_popup) (GtkLabel *label,
- GtkMenu *menu);
-
gboolean (*activate_link) (GtkLabel *label,
const gchar *uri);
@@ -217,6 +213,10 @@ void gtk_label_set_yalign (GtkLabel *label,
GDK_AVAILABLE_IN_ALL
gfloat gtk_label_get_yalign (GtkLabel *label);
+GDK_AVAILABLE_IN_ALL
+GMenuModel * gtk_label_get_default_context_menu (GtkLabel *label);
+
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLabel, g_object_unref)
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]