[gtk/new-style-menu: 22/48] Introduce a popover bar



commit f91cc6c473e9f45d2e631973c718997d19051466
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Jun 7 23:27:24 2019 +0000

    Introduce a popover bar
    
    This is meant to grow into a menubar replacement
    with popovers. For now, it is just a box of menubuttons,
    and not very much like a menubar at all.

 gtk/gtk.h           |   1 +
 gtk/gtkpopoverbar.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkpopoverbar.h |  47 ++++++++++++
 gtk/meson.build     |   1 +
 4 files changed, 265 insertions(+)
---
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 2f6e7e59be..9bb5145c3d 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -173,6 +173,7 @@
 #include <gtk/gtkpasswordentry.h>
 #include <gtk/gtkpicture.h>
 #include <gtk/gtkpopover.h>
+#include <gtk/gtkpopoverbar.h>
 #include <gtk/gtkpopovermenu.h>
 #include <gtk/gtkprintcontext.h>
 #include <gtk/gtkprintoperation.h>
diff --git a/gtk/gtkpopoverbar.c b/gtk/gtkpopoverbar.c
new file mode 100644
index 0000000000..327379df39
--- /dev/null
+++ b/gtk/gtkpopoverbar.c
@@ -0,0 +1,216 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen redhat com>
+ *
+ * This library 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) any later version.
+ *
+ * This library 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 this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkpopoverbar.h"
+#include "gtkpopovermenu.h"
+
+#include "gtkbox.h"
+#include "gtklabel.h"
+#include "gtkmenubutton.h"
+#include "gtkintl.h"
+#include "gtkprivate.h"
+#include "gtkmarshalers.h"
+#include "gtkstylecontext.h"
+#include "gtkgestureclick.h"
+#include "gtkeventcontrollerkey.h"
+#include "gtkactionmuxerprivate.h"
+#include "gtkmenutracker.h"
+#include "gtkwidgetprivate.h"
+
+struct _GtkPopoverBar
+{
+  GtkWidget parent;
+
+  GtkMenuTracker *tracker;
+  GtkWidget *box;
+};
+
+typedef struct _GtkPopoverBarClass GtkPopoverBarClass;
+struct _GtkPopoverBarClass
+{
+  GtkWidgetClass parent_class;
+};
+
+G_DEFINE_TYPE (GtkPopoverBar, gtk_popover_bar, GTK_TYPE_WIDGET)
+
+static void
+gtk_popover_bar_init (GtkPopoverBar *bar)
+{
+  bar->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_set_parent (bar->box, GTK_WIDGET (bar));
+}
+
+static void
+gtk_popover_bar_dispose (GObject *object)
+{
+  GtkPopoverBar *bar = GTK_POPOVER_BAR (object);
+
+  g_clear_pointer (&bar->tracker, gtk_menu_tracker_free);
+  g_clear_pointer (&bar->box, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (gtk_popover_bar_parent_class)->dispose (object);
+}
+
+static void
+gtk_popover_bar_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_popover_bar_parent_class)->finalize (object);
+}
+
+static void
+gtk_popover_bar_measure (GtkWidget      *widget,
+                         GtkOrientation  orientation,
+                         int             for_size,
+                         int            *minimum,
+                         int            *natural,
+                         int            *minimum_baseline,
+                         int            *natural_baseline)
+{
+  GtkPopoverBar *bar = GTK_POPOVER_BAR (widget);
+
+  gtk_widget_measure (bar->box, orientation, for_size,
+                      minimum, natural,
+                      minimum_baseline, natural_baseline);
+}
+
+static void
+gtk_popover_bar_size_allocate (GtkWidget *widget,
+                               int        width,
+                               int        height,
+                               int        baseline)
+{
+  GtkPopoverBar *bar = GTK_POPOVER_BAR (widget);
+
+  gtk_widget_size_allocate (bar->box,
+                            &(GtkAllocation) { 0, 0, width, height },
+                            baseline);
+}
+
+static void
+gtk_popover_bar_class_init (GtkPopoverBarClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = gtk_popover_bar_dispose;
+  object_class->finalize = gtk_popover_bar_finalize;
+
+  widget_class->measure = gtk_popover_bar_measure;
+  widget_class->size_allocate = gtk_popover_bar_size_allocate;
+
+  gtk_widget_class_set_css_name (widget_class, I_("menubar"));
+}
+
+static void
+tracker_remove (gint     position,
+                gpointer user_data)
+{
+  GtkPopoverBar *bar = user_data;
+  GtkWidget *child;
+  int i;
+
+  for (child = gtk_widget_get_first_child (bar->box), i = 0;
+       child;
+       child = gtk_widget_get_next_sibling (child), i++)
+    {
+      if (i == position)
+        {
+          gtk_widget_destroy (child);
+          break;
+        }
+    }
+}
+
+static void
+tracker_insert (GtkMenuTrackerItem *item,
+                gint                position,
+                gpointer            user_data)
+{
+  GtkPopoverBar *bar = user_data;
+
+  if (gtk_menu_tracker_item_get_has_link (item, G_MENU_LINK_SUBMENU))
+    {
+      GtkWidget *widget;
+      GMenuModel *model;
+      GtkWidget *sibling;
+      GtkWidget *child;
+      GtkWidget *popover;
+      int i;
+
+#if 0
+      widget = gtk_label_new (NULL);
+#else
+      widget = gtk_menu_button_new ();
+      gtk_menu_button_set_relief (GTK_MENU_BUTTON (widget), GTK_RELIEF_NONE);
+#endif
+      g_object_bind_property (item, "label", widget, "label", G_BINDING_SYNC_CREATE);
+
+      model = _gtk_menu_tracker_item_get_link (item, G_MENU_LINK_SUBMENU);
+#if 0
+      popover = gtk_popover_menu_new_from_model (GTK_WIDGET (bar), model);
+#else
+      gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (widget), model);
+      gtk_menu_button_set_direction (GTK_MENU_BUTTON (widget), GTK_ARROW_NONE);
+      popover = gtk_menu_button_get_popover (GTK_MENU_BUTTON (widget));
+#endif
+      gtk_popover_set_has_arrow (GTK_POPOVER (popover), FALSE);
+
+      sibling = NULL;
+      for (child = gtk_widget_get_first_child (bar->box), i = 1;
+           child;
+           child = gtk_widget_get_next_sibling (child), i++)
+        {
+          if (i == position)
+            {
+              sibling = child;
+              break;
+            }
+        }
+      gtk_box_insert_child_after (GTK_BOX (bar->box), widget, sibling);
+    }
+  else
+    g_warning ("Don't know how to handle this item");
+}
+
+GtkWidget *
+gtk_popover_bar_new_from_model (GMenuModel *model)
+{
+  GtkWidget *bar;
+  GtkActionMuxer *muxer;
+
+  bar = g_object_new (GTK_TYPE_POPOVER_BAR, NULL);
+
+  muxer = _gtk_widget_get_action_muxer (bar, TRUE);
+
+  GTK_POPOVER_BAR (bar)->tracker =
+      gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (muxer),
+                            model,
+                            FALSE,
+                            TRUE,
+                            FALSE,
+                            NULL,
+                            tracker_insert,
+                            tracker_remove,
+                            bar);
+
+  return bar;
+}
diff --git a/gtk/gtkpopoverbar.h b/gtk/gtkpopoverbar.h
new file mode 100644
index 0000000000..5b74e0bd96
--- /dev/null
+++ b/gtk/gtkpopoverbar.h
@@ -0,0 +1,47 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library 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) any later version.
+ *
+ * This library 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 this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_POPOVER_BAR_H__
+#define __GTK_POPOVER_BAR_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkpopover.h>
+
+
+G_BEGIN_DECLS
+
+
+#define        GTK_TYPE_POPOVER_BAR               (gtk_popover_bar_get_type ())
+#define GTK_POPOVER_BAR(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER_BAR, 
GtkPopoverBar))
+#define GTK_IS_POPOVER_BAR(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER_BAR))
+
+typedef struct _GtkPopoverBar GtkPopoverBar;
+
+GDK_AVAILABLE_IN_ALL
+GType      gtk_popover_bar_get_type        (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkWidget* gtk_popover_bar_new_from_model  (GMenuModel *model);
+
+G_END_DECLS
+
+
+#endif /* __GTK_POPOVER_BAR_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index 8d7285ed7b..2c844edbef 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -296,6 +296,7 @@ gtk_public_sources = files([
   'gtkpasswordentry.c',
   'gtkpicture.c',
   'gtkpopover.c',
+  'gtkpopoverbar.c',
   'gtkpopovermenu.c',
   'gtkprintcontext.c',
   'gtkprintoperation.c',


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