[gtk/widget-class-actions] text: Use the new action machinery



commit ab086e4cbfbe6b6deb299c9dfe296b6f9e1759d5
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jun 14 16:43:42 2019 +0000

    text: Use the new action machinery
    
    Port GtkText to use widget class actions.
    
    Note that this also changes the names of
    the GtkText actions away from a generic
    "context" prefix.

 gtk/gtktext.c | 337 +++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 217 insertions(+), 120 deletions(-)
---
diff --git a/gtk/gtktext.c b/gtk/gtktext.c
index 94e9cab270..40dffaaa39 100644
--- a/gtk/gtktext.c
+++ b/gtk/gtktext.c
@@ -68,6 +68,8 @@
 #include "gtkwidgetprivate.h"
 #include "gtkwindow.h"
 #include "gtknative.h"
+#include "gtkactionmuxerprivate.h"
+#include "gtkwidgetactiongroupprivate.h"
 
 #include "a11y/gtktextaccessible.h"
 
@@ -174,7 +176,6 @@ struct _GtkTextPrivate
   GtkCssNode    *block_cursor_node;
   GtkCssNode    *undershoot_node[2];
 
-  GActionMap    *context_actions;
   GtkWidget     *popup_menu;
   GMenuModel    *extra_menu;
 
@@ -542,10 +543,41 @@ static void         begin_change                       (GtkText *self);
 static void         end_change                         (GtkText *self);
 static void         emit_changed                       (GtkText *self);
 
-static void         gtk_text_add_context_actions      (GtkText *self);
 static void         gtk_text_update_clipboard_actions (GtkText *self);
 static void         gtk_text_update_emoji_action      (GtkText *self);
 
+static void gtk_text_activate_clipboard_cut        (GtkWidget *widget,
+                                                    const char *action_name,
+                                                    GVariant  *parameter);
+static void gtk_text_activate_clipboard_copy       (GtkWidget *widget,
+                                                    const char *action_name,
+                                                    GVariant  *parameter);
+static void gtk_text_activate_clipboard_paste      (GtkWidget *widget,
+                                                    const char *action_name,
+                                                    GVariant  *parameter);
+static void gtk_text_activate_selection_delete     (GtkWidget *widget,
+                                                    const char *action_name,
+                                                    GVariant  *parameter);
+static void gtk_text_activate_selection_select_all (GtkWidget *widget,
+                                                    const char *action_name,
+                                                    GVariant  *parameter);
+static void gtk_text_activate_misc_insert_emoji    (GtkWidget *widget,
+                                                    const char *action_name,
+                                                    GVariant  *parameter);
+static void gtk_text_activate_misc_toggle_visibility (GtkWidget *widget,
+                                                      const char *action_name,
+                                                      GVariant  *parameter);
+static void gtk_text_change_misc_toggle_visibility   (GtkWidget *widget,
+                                                      const char *action_name,
+                                                      GVariant  *state);
+
+static gboolean gtk_text_query_action (GtkWidget           *widget,
+                                       const char          *action_name,
+                                       gboolean            *enabled,
+                                       const GVariantType **parameter_type,
+                                       const GVariantType **state_type,
+                                       GVariant           **state_hint,
+                                       GVariant           **state);
 
 /* GtkTextContent implementation
  */
@@ -706,7 +738,7 @@ gtk_text_class_init (GtkTextClass *class)
   class->toggle_overwrite = gtk_text_toggle_overwrite;
   class->insert_emoji = gtk_text_insert_emoji;
   class->activate = gtk_text_real_activate;
-  
+ 
   quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint");
   quark_gtk_signal = g_quark_from_static_string ("gtk-signal");
 
@@ -1336,6 +1368,36 @@ gtk_text_class_init (GtkTextClass *class)
 
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("text"));
+
+  gtk_widget_class_install_action (widget_class,
+                                   "clipboard.cut",
+                                   gtk_text_activate_clipboard_cut, gtk_text_query_action,
+                                   NULL);
+  gtk_widget_class_install_action (widget_class,
+                                   "clipboard.copy",
+                                   gtk_text_activate_clipboard_copy, gtk_text_query_action,
+                                   NULL);
+  gtk_widget_class_install_action (widget_class,
+                                   "clipboard.paste",
+                                   gtk_text_activate_clipboard_paste, gtk_text_query_action,
+                                   NULL);
+  gtk_widget_class_install_action (widget_class,
+                                   "selection.delete",
+                                   gtk_text_activate_selection_delete, gtk_text_query_action,
+                                   NULL);
+  gtk_widget_class_install_action (widget_class,
+                                   "selection.select-all",
+                                   gtk_text_activate_selection_select_all, gtk_text_query_action,
+                                   NULL);
+  gtk_widget_class_install_action (widget_class,
+                                   "misc.insert-emoji",
+                                   gtk_text_activate_misc_insert_emoji, gtk_text_query_action,
+                                   NULL);
+                                 
+  gtk_widget_class_install_action (widget_class,
+                                   "misc.toggle-visibility",
+                                   gtk_text_activate_misc_toggle_visibility, gtk_text_query_action,
+                                   gtk_text_change_misc_toggle_visibility);
 }
 
 static void
@@ -1720,7 +1782,7 @@ gtk_text_init (GtkText *self)
     }
 
   set_text_cursor (GTK_WIDGET (self));
-  gtk_text_add_context_actions (self);
+  gtk_widget_add_class_actions (GTK_WIDGET (self));
 }
 
 static void
@@ -1766,7 +1828,7 @@ gtk_text_dispose (GObject *object)
   keymap = gdk_display_get_keymap (gtk_widget_get_display (GTK_WIDGET (object)));
   g_signal_handlers_disconnect_by_func (keymap, keymap_direction_changed, self);
 
-  g_clear_object (&priv->context_actions);
+  g_clear_pointer (&priv->selection_bubble, gtk_widget_unparent);
   g_clear_pointer (&priv->popup_menu, gtk_widget_unparent);
   g_clear_object (&priv->extra_menu);
 
@@ -1783,7 +1845,6 @@ gtk_text_finalize (GObject *object)
 
   g_clear_object (&priv->cached_layout);
   g_clear_object (&priv->im_context);
-  g_clear_pointer (&priv->selection_bubble, gtk_widget_unparent);
   g_clear_pointer (&priv->magnifier_popover, gtk_widget_destroy);
   g_clear_object (&priv->text_handle);
   g_free (priv->im_module);
@@ -2176,6 +2237,9 @@ gtk_text_size_allocate (GtkWidget *widget,
 
   if (priv->popup_menu)
     gtk_native_check_resize (GTK_NATIVE (priv->popup_menu));
+
+  if (priv->selection_bubble)
+    gtk_native_check_resize (GTK_NATIVE (priv->selection_bubble));
 }
 
 static void
@@ -5261,15 +5325,12 @@ gtk_text_set_visibility (GtkText  *self,
 
   if (priv->visible != visible)
     {
-      GAction *action;
-
       priv->visible = visible;
 
       g_object_notify (G_OBJECT (self), "visibility");
       gtk_text_recompute (self);
 
-      action = g_action_map_lookup_action (priv->context_actions, "toggle-visibility");
-      g_simple_action_set_state (G_SIMPLE_ACTION (action), g_variant_new_boolean (visible));
+      gtk_widget_notify_class_action_state (GTK_WIDGET (self), "misc.toggle-visibility");
     }
 }
 
@@ -5614,153 +5675,186 @@ hide_selection_bubble (GtkText *self)
     gtk_widget_hide (priv->selection_bubble);
 }
 
-static void
-cut_clipboard_activated (GSimpleAction *action,
-                         GVariant      *parameter,
-                         gpointer       user_data)
+static gboolean
+gtk_text_query_action (GtkWidget           *widget,
+                       const char          *action_name,
+                       gboolean            *enabled,
+                       const GVariantType **parameter_type,
+                       const GVariantType **state_type,
+                       GVariant           **state_hint,
+                       GVariant           **state)
 {
-  g_signal_emit_by_name (user_data, "cut-clipboard");
-  hide_selection_bubble (GTK_TEXT (user_data));
+  GtkText *self = GTK_TEXT (widget);
+  GtkTextPrivate *priv = gtk_text_get_instance_private (self);
+  GdkClipboard *clipboard;
+  DisplayMode mode;
+  gboolean has_clipboard;
+  gboolean has_selection;
+  gboolean has_content;
+  gboolean visible;
+  gboolean enable = FALSE;
+  const GVariantType *ptype = NULL;
+  const GVariantType *stype = NULL;
+  GVariant *shint = NULL;
+  GVariant *s = NULL;
+
+  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (self));
+  mode = gtk_text_get_display_mode (self);
+  has_clipboard = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), G_TYPE_STRING);
+  has_selection = priv->current_pos != priv->selection_bound;
+  has_content = priv->buffer && (gtk_entry_buffer_get_length (priv->buffer) > 0);
+  visible = mode == DISPLAY_NORMAL;
+
+  if (strcmp (action_name, "cut") == 0)
+    enable = visible && priv->editable && has_selection;
+  else if (strcmp (action_name, "copy") == 0)
+    enable = visible && has_selection;
+  else if (strcmp (action_name, "paste") == 0)
+    enable = priv->editable && has_clipboard;
+  else if (strcmp (action_name, "delete") == 0)
+    enable = priv->editable && has_selection;
+  else if (strcmp (action_name, "select-all") == 0)
+    enable = has_content;
+  else if (strcmp (action_name, "insert-emoji") == 0)
+    enable = (gtk_text_get_input_hints (self) & GTK_INPUT_HINT_NO_EMOJI) == 0;
+  else if (strcmp (action_name, "toggle-visibility") == 0)
+    {
+      enable = TRUE;
+      stype = G_VARIANT_TYPE_BOOLEAN;
+      s = g_variant_new_boolean (visible);
+    }
+  else
+    g_print ("Action %s not found\n", action_name);
+
+  if (enabled)
+    *enabled = enable;
+  if (parameter_type)
+    *parameter_type = ptype;
+  if (state_type)
+    *state_type = stype;
+  if (state_hint)
+    *state_hint = shint;
+  if (state)
+    *state = s;
+
+  return TRUE;
 }
 
 static void
-copy_clipboard_activated (GSimpleAction *action,
-                          GVariant      *parameter,
-                          gpointer       user_data)
+gtk_text_activate_clipboard_cut (GtkWidget *widget,
+                                 const char *action_name,
+                                 GVariant  *parameter)
 {
-  g_signal_emit_by_name (user_data, "copy-clipboard");
-  hide_selection_bubble (GTK_TEXT (user_data));
+  GtkText *self = GTK_TEXT (widget);
+  g_signal_emit_by_name (self, "cut-clipboard");
+  hide_selection_bubble (self);
 }
 
 static void
-paste_clipboard_activated (GSimpleAction *action,
-                           GVariant      *parameter,
-                           gpointer       user_data)
+gtk_text_activate_clipboard_copy (GtkWidget *widget,
+                                  const char *action_name,
+                                  GVariant  *parameter)
 {
-  g_signal_emit_by_name (user_data, "paste-clipboard");
-  hide_selection_bubble (GTK_TEXT (user_data));
+  GtkText *self = GTK_TEXT (widget);
+  g_signal_emit_by_name (self, "copy-clipboard");
+  hide_selection_bubble (self);
 }
 
 static void
-delete_selection_activated (GSimpleAction *action,
-                            GVariant      *parameter,
-                            gpointer       user_data)
+gtk_text_activate_clipboard_paste (GtkWidget *widget,
+                                   const char *action_name,
+                                   GVariant  *parameter)
 {
-  gtk_text_delete_cb (GTK_TEXT (user_data));
-  hide_selection_bubble (GTK_TEXT (user_data));
+  GtkText *self = GTK_TEXT (widget);
+  g_signal_emit_by_name (self, "paste-clipboard");
+  hide_selection_bubble (self);
 }
 
 static void
-select_all_activated (GSimpleAction *action,
-                      GVariant      *parameter,
-                      gpointer       user_data)
+gtk_text_activate_selection_delete (GtkWidget *widget,
+                                    const char *action_name,
+                                    GVariant  *parameter)
 {
-  gtk_text_select_all (GTK_TEXT (user_data));
+  GtkText *self = GTK_TEXT (widget);
+  gtk_text_delete_cb (self);
+  hide_selection_bubble (self);
 }
 
 static void
-insert_emoji_activated (GSimpleAction *action,
-                        GVariant      *parameter,
-                        gpointer       user_data)
+gtk_text_activate_selection_select_all (GtkWidget *widget,
+                                        const char *action_name,
+                                        GVariant  *parameter)
 {
-  gtk_text_insert_emoji (GTK_TEXT (user_data));
-  hide_selection_bubble (GTK_TEXT (user_data));
+  GtkText *self = GTK_TEXT (widget);
+  gtk_text_select_all (self);
 }
 
 static void
-toggle_visibility (GSimpleAction *action,
-                   GVariant      *parameter,
-                   gpointer       user_data)
+gtk_text_activate_misc_insert_emoji (GtkWidget *widget,
+                                     const char *action_name,
+                                     GVariant  *parameter)
 {
-  GtkText *text = GTK_TEXT (user_data);
-  gtk_text_set_visibility (text, !gtk_text_get_visibility (text));
+  GtkText *self = GTK_TEXT (widget);
+  gtk_text_insert_emoji (self);
+  hide_selection_bubble (self);
 }
 
 static void
-gtk_text_add_context_actions (GtkText *self)
+gtk_text_activate_misc_toggle_visibility (GtkWidget *widget,
+                                          const char *action_name,
+                                          GVariant  *parameter)
 {
-  GtkTextPrivate *priv = gtk_text_get_instance_private (self);
-
-  GActionEntry entries[] = {
-    { "cut-clipboard", cut_clipboard_activated, NULL, NULL, NULL },
-    { "copy-clipboard", copy_clipboard_activated, NULL, NULL, NULL },
-    { "paste-clipboard", paste_clipboard_activated, NULL, NULL, NULL },
-    { "delete-selection", delete_selection_activated, NULL, NULL, NULL },
-    { "select-all", select_all_activated, NULL, NULL, NULL },
-    { "insert-emoji", insert_emoji_activated, NULL, NULL, NULL },
-    { "toggle-visibility", toggle_visibility, NULL, "true", 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), self);
-
-  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);
-  action = g_action_map_lookup_action (G_ACTION_MAP (actions), "insert-emoji");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
+  GtkText *self = GTK_TEXT (widget);
+  gtk_text_set_visibility (self, !gtk_text_get_visibility (self));
+}
 
-  gtk_widget_insert_action_group (GTK_WIDGET (self), "context", G_ACTION_GROUP (actions));
+static void
+gtk_text_change_misc_toggle_visibility (GtkWidget  *widget,
+                                        const char *action_name,
+                                        GVariant   *state)
+{
+  GtkText *self = GTK_TEXT (widget);
+  gboolean visible = g_variant_get_boolean (state);
+  gtk_text_set_visibility (self, visible);
 }
 
 static void
 gtk_text_update_clipboard_actions (GtkText *self)
- {
+{
   GtkTextPrivate *priv = gtk_text_get_instance_private (self);
   DisplayMode mode;
   GdkClipboard *clipboard;
   gboolean has_clipboard;
-  GAction *action;
- 
+  gboolean has_selection;
+  gboolean has_content;
+  gboolean visible;
+  GActionGroup *group;
+
   clipboard = gtk_widget_get_clipboard (GTK_WIDGET (self));
-  has_clipboard = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), G_TYPE_STRING);
   mode = gtk_text_get_display_mode (self);
+  has_clipboard = gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), G_TYPE_STRING);
+  has_selection = priv->current_pos != priv->selection_bound;
+  has_content = priv->buffer && (gtk_entry_buffer_get_length (priv->buffer) > 0);
+  visible = mode == DISPLAY_NORMAL;
 
-  action = g_action_map_lookup_action (priv->context_actions, "cut-clipboard");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
-                               mode == DISPLAY_NORMAL &&
-                               priv->editable &&
-                               priv->current_pos != priv->selection_bound);
-
-  action = g_action_map_lookup_action (priv->context_actions, "copy-clipboard");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
-                               mode == DISPLAY_NORMAL &&
-                               priv->current_pos != priv->selection_bound);
-
-  action = g_action_map_lookup_action (priv->context_actions, "paste-clipboard");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
-                               priv->editable && has_clipboard);
+  group = gtk_widget_get_action_group (GTK_WIDGET (self), "clipboard");
+  g_action_group_action_enabled_changed (group, "cut", visible && priv->editable && has_selection);
+  g_action_group_action_enabled_changed (group, "copy", visible && has_selection);
+  g_action_group_action_enabled_changed (group, "paste", priv->editable && has_clipboard);
 
-  action = g_action_map_lookup_action (priv->context_actions, "delete-selection");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
-                               priv->editable &&
-                               priv->current_pos != priv->selection_bound);
+  group = gtk_widget_get_action_group (GTK_WIDGET (self), "selection");
+  g_action_group_action_enabled_changed (group, "delete", priv->editable && has_selection);
 
-  action = g_action_map_lookup_action (priv->context_actions, "select-all");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
-                               priv->buffer && (gtk_entry_buffer_get_length (priv->buffer) > 0));
+  g_action_group_action_enabled_changed (group, "select-all", has_content);
 }
 
 static void
 gtk_text_update_emoji_action (GtkText *self)
 {
-  GtkTextPrivate *priv = gtk_text_get_instance_private (self);
-  GAction *action;
+  GActionGroup *group;
 
-  action = g_action_map_lookup_action (priv->context_actions, "insert-emoji");
-  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
-                               (gtk_text_get_input_hints (self) & GTK_INPUT_HINT_NO_EMOJI) == 0);
+  group = gtk_widget_get_action_group (GTK_WIDGET (self), "misc");
+  g_action_group_action_enabled_changed (group, "insert-emoji", (gtk_text_get_input_hints (self) & 
GTK_INPUT_HINT_NO_EMOJI) == 0);
 }
 
 static GMenuModel *
@@ -5773,19 +5867,19 @@ gtk_text_get_menu_model (GtkText *self)
   menu = g_menu_new ();
 
   section = g_menu_new ();
-  item = g_menu_item_new (_("Cu_t"), "context.cut-clipboard");
+  item = g_menu_item_new (_("Cu_t"), "clipboard.cut");
   g_menu_item_set_attribute (item, "touch-icon", "s", "edit-cut-symbolic");
   g_menu_append_item (section, item);
   g_object_unref (item);
-  item = g_menu_item_new (_("_Copy"), "context.copy-clipboard");
+  item = g_menu_item_new (_("_Copy"), "clipboard.copy");
   g_menu_item_set_attribute (item, "touch-icon", "s", "edit-copy-symbolic");
   g_menu_append_item (section, item);
   g_object_unref (item);
-  item = g_menu_item_new (_("_Paste"), "context.paste-clipboard");
+  item = g_menu_item_new (_("_Paste"), "clipboard.paste");
   g_menu_item_set_attribute (item, "touch-icon", "s", "edit-paste-symbolic");
   g_menu_append_item (section, item);
   g_object_unref (item);
-  item = g_menu_item_new (_("_Delete"), "context.delete-selection");
+  item = g_menu_item_new (_("_Delete"), "selection.delete");
   g_menu_item_set_attribute (item, "touch-icon", "s", "edit-delete-symbolic");
   g_menu_append_item (section, item);
   g_object_unref (item);
@@ -5794,12 +5888,12 @@ gtk_text_get_menu_model (GtkText *self)
 
   section = g_menu_new ();
 
-  item = g_menu_item_new (_("Select _All"), "context.select-all");
+  item = g_menu_item_new (_("Select _All"), "selection.select-all");
   g_menu_item_set_attribute (item, "touch-icon", "s", "edit-select-all-symbolic");
   g_menu_append_item (section, item);
   g_object_unref (item);
 
-  item = g_menu_item_new ( _("Insert _Emoji"), "context.insert-emoji");
+  item = g_menu_item_new ( _("Insert _Emoji"), "misc.insert-emoji");
   g_menu_item_set_attribute (item, "hidden-when", "s", "action-disabled");
   g_menu_item_set_attribute (item, "touch-icon", "s", "face-smile-symbolic");
   g_menu_append_item (section, item);
@@ -5860,12 +5954,13 @@ append_bubble_item (GtkText    *self,
                     GMenuModel *model,
                     int         index)
 {
-  GtkTextPrivate *priv = gtk_text_get_instance_private (self);
+  GtkActionMuxer *muxer;
+  GActionGroup *group;
   GtkWidget *item, *image;
   GVariant *att;
   const char *icon_name;
   const char *action_name;
-  GAction *action;
+  const char *name;
   GMenuModel *link;
 
   link = g_menu_model_get_item_link (model, index, "section");
@@ -5891,10 +5986,12 @@ append_bubble_item (GtkText    *self,
   action_name = g_variant_get_string (att, NULL);
   g_variant_unref (att);
 
-  if (g_str_has_prefix (action_name, "context."))
+  muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (self), FALSE);
+  group = gtk_action_muxer_find (muxer, action_name, &name);
+  if (GTK_IS_WIDGET_ACTION_GROUP (group) &&
+      gtk_widget_action_group_get_widget (GTK_WIDGET_ACTION_GROUP (group)) == GTK_WIDGET (self))
     {
-      action = g_action_map_lookup_action (priv->context_actions, action_name + strlen ("context."));
-      if (action && !g_action_get_enabled (action))
+      if (!g_action_group_get_action_enabled (group, name))
         return;
     }
 
@@ -5989,7 +6086,7 @@ gtk_text_selection_bubble_popup_show (gpointer user_data)
   rect.width += 10;
   rect.height += 10;
 
-  gtk_popover_set_pointing_to (GTK_POPOVER (priv->selection_bubble), &rect);
+  //gtk_popover_set_pointing_to (GTK_POPOVER (priv->selection_bubble), &rect);
   gtk_widget_show (priv->selection_bubble);
 
   priv->selection_bubble_timeout_id = 0;


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