[gtk/global-coords: 20/24] More menu restructuring



commit 3f6272f56eb7b7d32aad1979c67a744a14aa02ed
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri May 31 02:36:34 2019 +0000

    More menu restructuring
    
    Make GtkMenuBar use a box as well,
    and let GtkMenuShell get the items
    from GtkMenuBar and GtkMenu via
    a vfunc. Use that to fix the keynav
    implementation in GtkMenuShell.

 gtk/gtkmenu.c      |  24 +++++++
 gtk/gtkmenubar.c   | 186 +++++++++++++++++++----------------------------------
 gtk/gtkmenushell.c |  56 +++++++++++-----
 3 files changed, 131 insertions(+), 135 deletions(-)
---
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 6592a909c2..98f1541184 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -195,6 +195,8 @@ static void     gtk_menu_move_current      (GtkMenuShell     *menu_shell,
 
 static void gtk_menu_deactivate     (GtkMenuShell      *menu_shell);
 static void gtk_menu_position       (GtkMenu           *menu);
+static void gtk_menu_add            (GtkContainer      *menu,
+                                     GtkWidget         *widget);
 static void gtk_menu_remove         (GtkContainer      *menu,
                                      GtkWidget         *widget);
 
@@ -239,6 +241,14 @@ menu_queue_resize (GtkMenu *menu)
   gtk_widget_queue_resize (GTK_WIDGET (menu));
 }
 
+static GList *
+gtk_menu_get_items (GtkMenuShell *menu_shell)
+{
+  GtkMenuPrivate *priv = GTK_MENU (menu_shell)->priv;
+
+  return gtk_container_get_children (GTK_CONTAINER (priv->box));
+}
+
 static void
 gtk_menu_class_init (GtkMenuClass *class)
 {
@@ -261,6 +271,7 @@ gtk_menu_class_init (GtkMenuClass *class)
   widget_class->grab_notify = gtk_menu_grab_notify;
   widget_class->measure = gtk_menu_measure;
 
+  container_class->add = gtk_menu_add;
   container_class->remove = gtk_menu_remove;
 
   menu_shell_class->submenu_placement = GTK_LEFT_RIGHT;
@@ -268,6 +279,7 @@ gtk_menu_class_init (GtkMenuClass *class)
   menu_shell_class->insert = gtk_menu_real_insert;
   menu_shell_class->get_popup_delay = gtk_menu_get_popup_delay;
   menu_shell_class->move_current = gtk_menu_move_current;
+  menu_shell_class->get_items = gtk_menu_get_items;
 
   /**
    * GtkMenu::popped-up:
@@ -978,6 +990,18 @@ gtk_menu_detach (GtkMenu *menu)
   g_object_unref (menu);
 }
 
+static void
+gtk_menu_add (GtkContainer *container,
+              GtkWidget    *widget)
+{
+  GtkMenu *menu = GTK_MENU (container);
+  GtkMenuPrivate *priv = menu->priv;
+
+  gtk_container_add (GTK_CONTAINER (priv->box), widget);
+
+  menu_queue_resize (menu);
+}
+
 static void
 gtk_menu_remove (GtkContainer *container,
                  GtkWidget    *widget)
diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c
index 5ae9f35a7c..165412318f 100644
--- a/gtk/gtkmenubar.c
+++ b/gtk/gtkmenubar.c
@@ -51,10 +51,12 @@
 #include "gtksizerequest.h"
 #include "gtkwindow.h"
 #include "gtkcontainerprivate.h"
+#include "gtkcheckmenuitem.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
 #include "gtktypebuiltins.h"
 #include "gtkwidgetprivate.h"
+#include "gtkbox.h"
 
 #define MENU_BAR_POPUP_DELAY 0
 
@@ -65,6 +67,9 @@ typedef struct _GtkMenuBarClass    GtkMenuBarClass;
 struct _GtkMenuBar
 {
   GtkMenuShell menu_shell;
+
+  int toggle_size;
+  GtkWidget *box;
 };
 
 struct _GtkMenuBarClass
@@ -72,6 +77,11 @@ struct _GtkMenuBarClass
   GtkMenuShellClass parent_class;
 };
 
+static void gtk_menu_bar_add    (GtkContainer *container,
+                                 GtkWidget    *widget);
+static void gtk_menu_bar_remove (GtkContainer *container,
+                                 GtkWidget    *widget);
+
 static void gtk_menu_bar_measure (GtkWidget     *widget,
                                   GtkOrientation  orientation,
                                   int             for_size,
@@ -88,13 +98,25 @@ static void gtk_menu_bar_unroot            (GtkWidget *widget);
 static gint gtk_menu_bar_get_popup_delay   (GtkMenuShell    *menu_shell);
 static void gtk_menu_bar_move_current      (GtkMenuShell     *menu_shell,
                                             GtkMenuDirectionType direction);
+static void gtk_menu_bar_insert            (GtkMenuShell *menu_shell,
+                                            GtkWidget    *child,
+                                            gint          position);
 
 G_DEFINE_TYPE (GtkMenuBar, gtk_menu_bar, GTK_TYPE_MENU_SHELL)
 
+static GList *
+gtk_menu_bar_get_items (GtkMenuShell *menu_shell)
+{
+  GtkMenuBar *menu_bar = GTK_MENU_BAR (menu_shell);
+
+  return gtk_container_get_children (GTK_CONTAINER (menu_bar->box));
+}
+
 static void
 gtk_menu_bar_class_init (GtkMenuBarClass *class)
 {
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
   GtkMenuShellClass *menu_shell_class = GTK_MENU_SHELL_CLASS (class);
 
   GtkBindingSet *binding_set;
@@ -104,9 +126,14 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class)
   widget_class->root = gtk_menu_bar_root;
   widget_class->unroot = gtk_menu_bar_unroot;
 
+  container_class->add = gtk_menu_bar_add;
+  container_class->remove = gtk_menu_bar_remove;
+
+  menu_shell_class->insert = gtk_menu_bar_insert;
   menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
   menu_shell_class->get_popup_delay = gtk_menu_bar_get_popup_delay;
   menu_shell_class->move_current = gtk_menu_bar_move_current;
+  menu_shell_class->get_items = gtk_menu_bar_get_items;
 
   binding_set = gtk_binding_set_by_class (class);
   gtk_binding_entry_add_signal (binding_set,
@@ -157,6 +184,8 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class)
 static void
 gtk_menu_bar_init (GtkMenuBar *menu_bar)
 {
+  menu_bar->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_set_parent (menu_bar->box, GTK_WIDGET (menu_bar));
 }
 
 /**
@@ -181,58 +210,13 @@ gtk_menu_bar_measure (GtkWidget      *widget,
                       int            *minimum_baseline,
                       int            *natural_baseline)
 {
-  GtkMenuShell *menu_shell;
-  GtkWidget *child;
-  GList *children;
-  gboolean use_toggle_size, use_maximize;
-  gint child_minimum, child_natural;
-
-  *minimum = 0;
-  *natural = 0;
-
-  menu_shell = GTK_MENU_SHELL (widget);
-
-  children = menu_shell->priv->children;
-
-  use_toggle_size = (orientation == GTK_ORIENTATION_HORIZONTAL);
-  use_maximize = (orientation == GTK_ORIENTATION_VERTICAL);
+  GtkMenuBar *menu_bar = GTK_MENU_BAR (widget);
 
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-
-      if (gtk_widget_get_visible (child))
-        {
-          gtk_widget_measure (child,
-                              orientation,
-                              for_size,
-                              &child_minimum, &child_natural,
-                              NULL, NULL);
-
-          if (use_toggle_size)
-            {
-              gint toggle_size;
-
-              gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child),
-                                                 &toggle_size);
-
-              child_minimum += toggle_size;
-              child_natural += toggle_size;
-            }
-
-          if (use_maximize)
-            {
-              *minimum = MAX (*minimum, child_minimum);
-              *natural = MAX (*natural, child_natural);
-            }
-          else
-            {
-              *minimum += child_minimum;
-              *natural += child_natural;
-            }
-        }
-    }
+  gtk_widget_measure (menu_bar->box,
+                      orientation,
+                      for_size,
+                      minimum, natural,
+                      minimum_baseline, natural_baseline);
 }
 
 static void
@@ -241,75 +225,11 @@ gtk_menu_bar_size_allocate (GtkWidget *widget,
                             int        height,
                             int        baseline)
 {
-  GtkMenuShell *menu_shell;
-  GtkWidget *child;
-  GList *children;
-  GtkAllocation remaining_space;
-  GArray *requested_sizes;
-  gint toggle_size;
-  guint i;
-  int size;
-  gboolean ltr = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR);
-
-  menu_shell = GTK_MENU_SHELL (widget);
-
-  if (!menu_shell->priv->children)
-    return;
-
-  remaining_space = (GtkAllocation) {0, 0, width, height};
-  requested_sizes = g_array_new (FALSE, FALSE, sizeof (GtkRequestedSize));
-  size = remaining_space.width;
-
-  for (children = menu_shell->priv->children; children; children = children->next)
-    {
-      GtkRequestedSize request;
-      child = children->data;
-
-      if (!gtk_widget_get_visible (child))
-        continue;
-
-      request.data = child;
-      gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL,
-                          remaining_space.height,
-                          &request.minimum_size, &request.natural_size,
-                          NULL, NULL);
-      gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child),
-                                         &toggle_size);
-      request.minimum_size += toggle_size;
-      request.natural_size += toggle_size;
-
-      gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), toggle_size);
-
-      g_array_append_val (requested_sizes, request);
-
-      size -= request.minimum_size;
-    }
+  GtkMenuBar *menu_bar = GTK_MENU_BAR (widget);
 
-  size = gtk_distribute_natural_allocation (size,
-                                            requested_sizes->len,
-                                            (GtkRequestedSize *) requested_sizes->data);
-
-  for (i = 0; i < requested_sizes->len; i++)
-    {
-      GtkAllocation child_allocation = remaining_space;
-      GtkRequestedSize *request = &g_array_index (requested_sizes, GtkRequestedSize, i);
-
-      child_allocation.width = request->minimum_size;
-      remaining_space.width -= request->minimum_size;
-
-      if (i + 1 == requested_sizes->len && GTK_IS_MENU_ITEM (request->data) &&
-          GTK_MENU_ITEM (request->data)->priv->right_justify)
-        ltr = !ltr;
-
-      if (ltr)
-        remaining_space.x += request->minimum_size;
-      else
-        child_allocation.x += remaining_space.width;
-
-      gtk_widget_size_allocate (request->data, &child_allocation, -1);
-    }
-
-  g_array_free (requested_sizes, TRUE);
+  gtk_widget_size_allocate (menu_bar->box,
+                            &(GtkAllocation) { 0, 0, width, height },
+                            baseline);
 }
 
 static GList *
@@ -503,3 +423,31 @@ gtk_menu_bar_new_from_model (GMenuModel *model)
 
   return menubar;
 }
+
+static void
+gtk_menu_bar_add (GtkContainer *container,
+                  GtkWidget    *widget)
+{
+  GtkMenuBar *menu_bar = GTK_MENU_BAR (container);
+
+  gtk_container_add (GTK_CONTAINER (menu_bar->box), widget);
+}
+
+static void
+gtk_menu_bar_remove (GtkContainer *container,
+                     GtkWidget    *widget)
+{
+  GtkMenuBar *menu_bar = GTK_MENU_BAR (container);
+
+  gtk_container_remove (GTK_CONTAINER (menu_bar->box), widget);
+}
+
+static void
+gtk_menu_bar_insert (GtkMenuShell *menu_shell,
+                     GtkWidget    *child,
+                     gint          position)
+{
+  GtkMenuBar *menu_bar = GTK_MENU_BAR (menu_shell);
+
+  gtk_container_add (GTK_CONTAINER (menu_bar->box), child);
+}
diff --git a/gtk/gtkmenushell.c b/gtk/gtkmenushell.c
index d141c13f42..7ae0a0a1d5 100644
--- a/gtk/gtkmenushell.c
+++ b/gtk/gtkmenushell.c
@@ -656,13 +656,16 @@ click_pressed (GtkGestureClick *gesture,
   GtkMenuShellPrivate *priv = menu_shell->priv;
   GtkWidget *menu_item;
   GdkEvent *event;
+  GtkWidget *item_shell;
 
   event = gtk_get_current_event ();
   menu_item = gtk_get_event_target_with_type (event, GTK_TYPE_MENU_ITEM);
+  if (menu_item)
+    item_shell = gtk_widget_get_ancestor (GTK_WIDGET (menu_item), GTK_TYPE_MENU_SHELL);
 
   if (menu_item &&
       _gtk_menu_item_is_selectable (menu_item) &&
-      gtk_widget_get_parent (menu_item) == GTK_WIDGET (menu_shell))
+      item_shell == GTK_WIDGET (menu_shell))
     {
       if (menu_item != menu_shell->priv->active_menu_item)
         {
@@ -699,7 +702,7 @@ click_pressed (GtkGestureClick *gesture,
       if (menu_item)
         {
           if (_gtk_menu_item_is_selectable (menu_item) &&
-              gtk_widget_get_parent (menu_item) == GTK_WIDGET (menu_shell) &&
+              item_shell == GTK_WIDGET (menu_shell) &&
               menu_item != priv->active_menu_item)
             {
               priv->active = TRUE;
@@ -1194,6 +1197,12 @@ gtk_menu_shell_activate_item (GtkMenuShell *menu_shell,
   g_object_unref (menu_item);
 }
 
+static GList *
+gtk_menu_shell_get_items (GtkMenuShell *menu_shell)
+{
+  return GTK_MENU_SHELL_GET_CLASS (menu_shell)->get_items (menu_shell);
+}
+
 /* Distance should be +/- 1 */
 static gboolean
 gtk_menu_shell_real_move_selected (GtkMenuShell  *menu_shell,
@@ -1203,7 +1212,8 @@ gtk_menu_shell_real_move_selected (GtkMenuShell  *menu_shell,
 
   if (priv->active_menu_item)
     {
-      GList *node = g_list_find (priv->children, priv->active_menu_item);
+      GList *children = gtk_menu_shell_get_items (menu_shell);
+      GList *node = g_list_find (children, priv->active_menu_item);
       GList *start_node = node;
 
       if (distance > 0)
@@ -1215,7 +1225,7 @@ gtk_menu_shell_real_move_selected (GtkMenuShell  *menu_shell,
               if (node)
                 node = node->next;
               else
-                node = priv->children;
+                node = children;
             }
         }
       else
@@ -1227,12 +1237,14 @@ gtk_menu_shell_real_move_selected (GtkMenuShell  *menu_shell,
               if (node)
                 node = node->prev;
               else
-                node = g_list_last (priv->children);
+                node = g_list_last (children);
             }
         }
       
       if (node)
         gtk_menu_shell_select_item (menu_shell, node->data);
+
+      g_list_free (children);
     }
 
   return TRUE;
@@ -1264,14 +1276,13 @@ void
 gtk_menu_shell_select_first (GtkMenuShell *menu_shell,
                              gboolean      search_sensitive)
 {
-  GtkMenuShellPrivate *priv;
+  GList *children;
   GList *tmp_list;
 
   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
 
-  priv = menu_shell->priv;
-
-  tmp_list = priv->children;
+  children = gtk_menu_shell_get_items (menu_shell);
+  tmp_list = children;
   while (tmp_list)
     {
       GtkWidget *child = tmp_list->data;
@@ -1280,21 +1291,24 @@ gtk_menu_shell_select_first (GtkMenuShell *menu_shell,
           _gtk_menu_item_is_selectable (child))
         {
           gtk_menu_shell_select_item (menu_shell, child);
-          return;
+          break;
         }
 
       tmp_list = tmp_list->next;
     }
+
+  g_list_free (children);
 }
 
 void
 _gtk_menu_shell_select_last (GtkMenuShell *menu_shell,
                              gboolean      search_sensitive)
 {
-  GtkMenuShellPrivate *priv = menu_shell->priv;
   GList *tmp_list;
+  GList *children;
 
-  tmp_list = g_list_last (priv->children);
+  children = gtk_menu_shell_get_items (menu_shell);
+  tmp_list = g_list_last (children);
   while (tmp_list)
     {
       GtkWidget *child = tmp_list->data;
@@ -1303,11 +1317,13 @@ _gtk_menu_shell_select_last (GtkMenuShell *menu_shell,
           _gtk_menu_item_is_selectable (child))
         {
           gtk_menu_shell_select_item (menu_shell, child);
-          return;
+          break;
         }
 
       tmp_list = tmp_list->prev;
     }
+
+  g_list_free (children);
 }
 
 static gboolean
@@ -1805,14 +1821,19 @@ gtk_menu_shell_tracker_remove_func (gint     position,
                                     gpointer user_data)
 {
   GtkMenuShell *menu_shell = user_data;
+  GList *children;
   GtkWidget *child;
 
-  child = g_list_nth_data (menu_shell->priv->children, position);
+  children = gtk_menu_shell_get_items (menu_shell);
+
+  child = g_list_nth_data (children, position);
   /* We use destroy here because in the case of an item with a submenu,
    * the attached-to from the submenu holds a ref on the item and a
    * simple gtk_container_remove() isn't good enough to break that.
    */
   gtk_widget_destroy (child);
+
+  g_list_free (children);
 }
 
 static void
@@ -1956,6 +1977,7 @@ gtk_menu_shell_bind_model (GtkMenuShell *menu_shell,
                            gboolean      with_separators)
 {
   GtkActionMuxer *muxer;
+  GList *children, *l;
 
   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
   g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model));
@@ -1964,8 +1986,10 @@ gtk_menu_shell_bind_model (GtkMenuShell *menu_shell,
 
   g_clear_pointer (&menu_shell->priv->tracker, gtk_menu_tracker_free);
 
-  while (menu_shell->priv->children)
-    gtk_container_remove (GTK_CONTAINER (menu_shell), menu_shell->priv->children->data);
+  children = gtk_menu_shell_get_items (menu_shell);
+  for (l = children; l; l = l->next)
+    gtk_widget_destroy (GTK_WIDGET (l->data));
+  g_list_free (children);
 
   if (model)
     menu_shell->priv->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (muxer), model,


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