diff options
author | Alexander Mikhaylenko <alexm@gnome.org> | 2021-09-03 16:18:06 +0500 |
---|---|---|
committer | Alexander Mikhaylenko <alexm@gnome.org> | 2021-09-03 16:18:06 +0500 |
commit | a42d87d813a978817ec72232a616ac7659d82adf (patch) | |
tree | db379328c9a1234bd240c5bcf408b6b6a603668c | |
parent | 32899a1edd3e4b724ddb90c3f9d383010de68f33 (diff) | |
download | gtk+-wip/exalm/buttons.tar.gz |
menubutton: Support custom childrenwip/exalm/buttons
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/4205
-rw-r--r-- | gtk/gtkmenubutton.c | 133 | ||||
-rw-r--r-- | gtk/gtkmenubutton.h | 6 |
2 files changed, 138 insertions, 1 deletions
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__ */ |