[gtk/wip/exalm/buttons] menubutton: Support custom children




commit a42d87d813a978817ec72232a616ac7659d82adf
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Fri Sep 3 16:18:06 2021 +0500

    menubutton: Support custom children
    
    Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/4205

 gtk/gtkmenubutton.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkmenubutton.h |   6 +++
 2 files changed, 138 insertions(+), 1 deletion(-)
---
diff --git a/gtk/gtkmenubutton.c b/gtk/gtkmenubutton.c
index e1d8209ddc..5ba36417ca 100644
--- a/gtk/gtkmenubutton.c
+++ b/gtk/gtkmenubutton.c
@@ -87,6 +87,7 @@
 #include "config.h"
 
 #include "gtkactionable.h"
+#include "gtkbuildable.h"
 #include "gtkbuiltiniconprivate.h"
 #include "gtkintl.h"
 #include "gtkimage.h"
@@ -122,6 +123,7 @@ struct _GtkMenuButton
   GtkWidget *label_widget;
   GtkWidget *image_widget;
   GtkWidget *arrow_widget;
+  GtkWidget *child;
   GtkArrowType arrow_type;
   gboolean always_show_arrow;
 
@@ -147,6 +149,7 @@ enum
   PROP_USE_UNDERLINE,
   PROP_HAS_FRAME,
   PROP_PRIMARY,
+  PROP_CHILD,
   LAST_PROP
 };
 
@@ -158,7 +161,10 @@ enum {
 static GParamSpec *menu_button_props[LAST_PROP];
 static guint signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkMenuButton, gtk_menu_button, GTK_TYPE_WIDGET)
+static void gtk_menu_button_buildable_iface_init (GtkBuildableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkMenuButton, gtk_menu_button, GTK_TYPE_WIDGET,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_menu_button_buildable_iface_init))
 
 static void gtk_menu_button_dispose (GObject *object);
 
@@ -199,6 +205,9 @@ gtk_menu_button_set_property (GObject      *object,
       case PROP_PRIMARY:
         gtk_menu_button_set_primary (self, g_value_get_boolean (value));
         break;
+      case PROP_CHILD:
+        gtk_menu_button_set_child (self, g_value_get_object (value));
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -241,6 +250,9 @@ gtk_menu_button_get_property (GObject    *object,
       case PROP_PRIMARY:
         g_value_set_boolean (value, gtk_menu_button_get_primary (GTK_MENU_BUTTON (object)));
         break;
+      case PROP_CHILD:
+        g_value_set_object (value, gtk_menu_button_get_child (self));
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -507,6 +519,20 @@ gtk_menu_button_class_init (GtkMenuButtonClass *klass)
                           FALSE,
                           GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * GtkMenuButton:child: (attributes org.gtk.Property.get=gtk_menu_button_get_child 
org.gtk.Property.set=gtk_menu_button_set_child)
+   *
+   * The child widget.
+   *
+   * Since: 4.6
+   */
+  menu_button_props[PROP_CHILD] =
+    g_param_spec_object ("child",
+                         P_("Child"),
+                         P_("The child widget"),
+                         GTK_TYPE_WIDGET,
+                         GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
   g_object_class_install_properties (gobject_class, LAST_PROP, menu_button_props);
 
   /**
@@ -635,6 +661,28 @@ gtk_menu_button_init (GtkMenuButton *self)
   gtk_widget_add_css_class (GTK_WIDGET (self), "popup");
 }
 
+static GtkBuildableIface *parent_buildable_iface;
+
+static void
+gtk_menu_button_buildable_add_child (GtkBuildable *buildable,
+                                     GtkBuilder   *builder,
+                                     GObject      *child,
+                                     const char   *type)
+{
+  if (GTK_IS_WIDGET (child))
+    gtk_menu_button_set_child (GTK_MENU_BUTTON (buildable), GTK_WIDGET (child));
+  else
+    parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+gtk_menu_button_buildable_iface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+  iface->add_child = gtk_menu_button_buildable_add_child;
+}
+
 /**
  * gtk_menu_button_new:
  *
@@ -946,6 +994,9 @@ gtk_menu_button_set_icon_name (GtkMenuButton *menu_button,
   if (gtk_menu_button_get_label (menu_button))
     g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_LABEL]);
 
+  if (gtk_menu_button_get_child (menu_button))
+    g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_CHILD]);
+
   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
   gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
 
@@ -963,6 +1014,7 @@ gtk_menu_button_set_icon_name (GtkMenuButton *menu_button,
   gtk_button_set_child (GTK_BUTTON (menu_button->button), box);
 
   menu_button->label_widget = NULL;
+  menu_button->child = NULL;
 
   update_arrow (menu_button);
 
@@ -1056,6 +1108,8 @@ gtk_menu_button_set_label (GtkMenuButton *menu_button,
 
   if (gtk_menu_button_get_icon_name (menu_button))
     g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_ICON_NAME]);
+  if (gtk_menu_button_get_child (menu_button))
+    g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_CHILD]);
 
   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
   label_widget = gtk_label_new (label);
@@ -1072,6 +1126,7 @@ gtk_menu_button_set_label (GtkMenuButton *menu_button,
   menu_button->label_widget = label_widget;
 
   menu_button->image_widget = NULL;
+  menu_button->child = NULL;
 
   update_arrow (menu_button);
 
@@ -1354,3 +1409,79 @@ gtk_menu_button_get_primary (GtkMenuButton *menu_button)
 
   return menu_button->primary;
 }
+
+/**
+ * gtk_menu_button_set_child: (attributes org.gtk.Method.set_property=child)
+ * @menu_button: a `GtkMenuButton`
+ * @child: (nullable): the child widget
+ *
+ * Sets the child widget of @menu_button.
+ *
+ * Since: 4.6
+ */
+void
+gtk_menu_button_set_child (GtkMenuButton *menu_button,
+                           GtkWidget     *child)
+{
+  GtkWidget *box, *arrow;
+
+  g_return_if_fail (GTK_IS_MENU_BUTTON (menu_button));
+  g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
+
+  g_object_freeze_notify (G_OBJECT (menu_button));
+
+  if (gtk_menu_button_get_label (menu_button))
+    g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_LABEL]);
+  if (gtk_menu_button_get_icon_name (menu_button))
+    g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_ICON_NAME]);
+
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_set_halign (box, GTK_ALIGN_CENTER);
+
+  arrow = gtk_builtin_icon_new ("arrow");
+  menu_button->arrow_widget = arrow;
+
+  gtk_box_append (GTK_BOX (box), child);
+  gtk_box_append (GTK_BOX (box), arrow);
+  gtk_button_set_child (GTK_BUTTON (menu_button->button), box);
+
+  menu_button->child = child;
+
+  menu_button->image_widget = NULL;
+  menu_button->label_widget = NULL;
+
+  update_arrow (menu_button);
+
+  g_object_notify_by_pspec (G_OBJECT (menu_button), menu_button_props[PROP_CHILD]);
+
+  g_object_thaw_notify (G_OBJECT (menu_button));
+
+/*
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  priv->child = child;
+
+  if (priv->child)
+    gtk_widget_set_parent (priv->child, GTK_WIDGET (button));
+
+  gtk_button_set_child_type (button, WIDGET_CHILD);
+  g_object_notify_by_pspec (G_OBJECT (button), props[PROP_CHILD]);*/
+}
+
+/**
+ * gtk_menu_button_get_child: (attributes org.gtk.Method.get_property=child)
+ * @menu_button: a `GtkMenuButton`
+ *
+ * Gets the child widget of @menu_button.
+ *
+ * Returns: (nullable) (transfer none): the child widget of @menu_button
+ *
+ * Since: 4.6
+ */
+GtkWidget *
+gtk_menu_button_get_child (GtkMenuButton *menu_button)
+{
+  g_return_val_if_fail (GTK_IS_MENU_BUTTON (menu_button), NULL);
+
+  return menu_button->child;
+}
diff --git a/gtk/gtkmenubutton.h b/gtk/gtkmenubutton.h
index 390771f049..723adb34da 100644
--- a/gtk/gtkmenubutton.h
+++ b/gtk/gtkmenubutton.h
@@ -121,6 +121,12 @@ void          gtk_menu_button_set_primary (GtkMenuButton *menu_button,
 GDK_AVAILABLE_IN_4_4
 gboolean      gtk_menu_button_get_primary (GtkMenuButton *menu_button);
 
+GDK_AVAILABLE_IN_4_6
+void          gtk_menu_button_set_child   (GtkMenuButton *menu_button,
+                                           GtkWidget     *child);
+GDK_AVAILABLE_IN_4_6
+GtkWidget *   gtk_menu_button_get_child   (GtkMenuButton *menu_button);
+
 G_END_DECLS
 
 #endif /* __GTK_MENU_BUTTON_H__ */


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