[glade/wip/beniofel/popover: 4/19] Initial GtkPopoverMenu support
- From: Ben Iofel <beniofel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glade/wip/beniofel/popover: 4/19] Initial GtkPopoverMenu support
- Date: Tue, 3 Nov 2015 22:17:14 +0000 (UTC)
commit 8000d66fda171ede71567966deee90257bbb72ae
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Nov 19 07:17:53 2014 +0100
Initial GtkPopoverMenu support
Add GtkPopoverMenu with two virtual properties, one for the number
of menus, and one for the currently edited menu.
plugins/gtk+/Makefile.am | 1 +
plugins/gtk+/glade-gtk-popover-menu.c | 478 ++++++++++++++++++++
plugins/gtk+/gtk+.xml.in | 32 ++
plugins/gtk+/icons/16x16/Makefile.am | 1 +
plugins/gtk+/icons/16x16/widget-gtk-popover.png | Bin 276 -> 311 bytes
.../gtk+/icons/16x16/widget-gtk-popovermenu.png | Bin 0 -> 276 bytes
plugins/gtk+/icons/22x22/Makefile.am | 1 +
plugins/gtk+/icons/22x22/widget-gtk-popover.png | Bin 327 -> 326 bytes
.../gtk+/icons/22x22/widget-gtk-popovermenu.png | Bin 0 -> 327 bytes
9 files changed, 513 insertions(+), 0 deletions(-)
---
diff --git a/plugins/gtk+/Makefile.am b/plugins/gtk+/Makefile.am
index 7e502c1..82b9a3f 100644
--- a/plugins/gtk+/Makefile.am
+++ b/plugins/gtk+/Makefile.am
@@ -92,6 +92,7 @@ libgladegtk_la_SOURCES = \
glade-gtk-overlay.c \
glade-gtk-paned.c \
glade-gtk-popover.c \
+ glade-gtk-popover-menu.c \
glade-gtk-progress-bar.c \
glade-gtk-radio-button.c \
glade-gtk-radio-menu-item.c \
diff --git a/plugins/gtk+/glade-gtk-popover-menu.c b/plugins/gtk+/glade-gtk-popover-menu.c
new file mode 100644
index 0000000..b3bbcc6
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-popover-menu.c
@@ -0,0 +1,478 @@
+/*
+ * glade-gtk-popovermenu.c - GladeWidgetAdaptor for GtkPopoverMenu
+ *
+ * Copyright (C) 2014 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.1 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 program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+#include <gladeui/glade.h>
+
+GObject *
+glade_gtk_popover_menu_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam * construct_properties)
+{
+ GladeWidgetAdaptor *adaptor;
+ GObject *ret_obj;
+
+ ret_obj = GWA_GET_OCLASS (GTK_TYPE_CONTAINER)->constructor
+ (type, n_construct_properties, construct_properties);
+
+ adaptor = GLADE_WIDGET_ADAPTOR (ret_obj);
+
+ glade_widget_adaptor_action_remove (adaptor, "add_parent");
+ glade_widget_adaptor_action_remove (adaptor, "remove_parent");
+
+ return ret_obj;
+}
+
+static void
+glade_gtk_popover_menu_parse_finished (GladeProject * project,
+ GObject * object)
+{
+ GladeWidget *gbox;
+ gint submenus;
+
+ gbox = glade_widget_get_from_gobject (object);
+ glade_widget_property_get (gbox, "submenus", &submenus);
+ glade_widget_property_set (gbox, "submenus", submenus);
+}
+
+void
+glade_gtk_popover_menu_post_create (GladeWidgetAdaptor *adaptor,
+ GObject *container,
+ GladeCreateReason reason)
+{
+ GladeWidget *parent = glade_widget_get_from_gobject (container);
+ GladeProject *project = glade_widget_get_project (parent);
+
+ if (reason == GLADE_CREATE_LOAD)
+ {
+ g_signal_connect (project, "parse-finished",
+ G_CALLBACK (glade_gtk_popover_menu_parse_finished),
+ container);
+ }
+ else if (reason == GLADE_CREATE_USER)
+ {
+ gtk_container_add (GTK_CONTAINER (container), glade_placeholder_new ());
+ }
+}
+
+void
+glade_gtk_popover_menu_add_child (GladeWidgetAdaptor *adaptor,
+ GObject *parent,
+ GObject *child)
+{
+ gtk_container_add (GTK_CONTAINER (parent), GTK_WIDGET (child));
+
+ if (!glade_widget_superuser ())
+ {
+ GladeWidget *gbox;
+ gint submenus;
+
+ gbox = glade_widget_get_from_gobject (parent);
+
+ glade_widget_property_get (gbox, "submenus", &submenus);
+ glade_widget_property_set (gbox, "submenus", submenus);
+ }
+}
+
+void
+glade_gtk_popover_menu_remove_child (GladeWidgetAdaptor *adaptor,
+ GObject *parent,
+ GObject *child)
+{
+ gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (child));
+
+ if (!glade_widget_superuser ())
+ {
+ GladeWidget *gbox;
+ gint submenus;
+
+ gbox = glade_widget_get_from_gobject (parent);
+
+ glade_widget_property_get (gbox, "submenus", &submenus);
+ glade_widget_property_set (gbox, "submenus", submenus);
+ }
+}
+
+void
+glade_gtk_popover_menu_replace_child (GladeWidgetAdaptor * adaptor,
+ GObject * container,
+ GObject * current,
+ GObject * new_widget)
+{
+ gchar *visible;
+ gchar *name;
+ gint position;
+ GladeWidget *gwidget;
+
+ g_object_get (G_OBJECT (container), "visible-submenu", &visible, NULL);
+
+ gtk_container_child_get (GTK_CONTAINER (container),
+ GTK_WIDGET (current),
+ "submenu", &name,
+ "position", &position,
+ NULL);
+
+ gtk_container_add (GTK_CONTAINER (container), GTK_WIDGET (new_widget));
+ gtk_container_remove (GTK_CONTAINER (container), GTK_WIDGET (current));
+
+ gtk_container_child_set (GTK_CONTAINER (container),
+ GTK_WIDGET (new_widget),
+ "submenu", name,
+ "position", position,
+ NULL);
+
+ g_object_set (G_OBJECT (container), "visible-submenu", visible, NULL);
+
+ gwidget = glade_widget_get_from_gobject (new_widget);
+ if (gwidget)
+ {
+ glade_widget_pack_property_set (gwidget, "submenu", name);
+ glade_widget_pack_property_set (gwidget, "position", position);
+ }
+
+ g_free (visible);
+ g_free (name);
+}
+
+typedef struct {
+ gint size;
+ gboolean include_placeholders;
+} ChildData;
+
+static void
+count_child (GtkWidget *child, gpointer data)
+{
+ ChildData *cdata = data;
+
+ if (cdata->include_placeholders || !GLADE_IS_PLACEHOLDER (child))
+ cdata->size++;
+}
+
+static gint
+count_children (GtkContainer *container,
+ gboolean include_placeholders)
+{
+ ChildData data;
+
+ data.size = 0;
+ data.include_placeholders = include_placeholders;
+ gtk_container_foreach (container, count_child, &data);
+ return data.size;
+}
+
+static gchar *
+get_unused_name (GtkPopoverMenu *popover)
+{
+ gint i;
+ gchar *name = NULL;
+ GList *children, *l;
+ gboolean exists;
+
+ children = gtk_container_get_children (GTK_CONTAINER (popover));
+
+ i = g_list_length (children);
+ while (1)
+ {
+ name = g_strdup_printf ("submenu%d", i);
+ exists = FALSE;
+ for (l = children; l && !exists; l = l->next)
+ {
+ gchar *submenu;
+ gtk_container_child_get (GTK_CONTAINER (popover), GTK_WIDGET (l->data),
+ "submenu", &submenu, NULL);
+ if (!strcmp (submenu, name))
+ exists = TRUE;
+ g_free (submenu);
+ }
+ if (!exists)
+ break;
+
+ g_free (name);
+ i++;
+ }
+
+ g_list_free (children);
+
+ return name;
+}
+
+static void
+glade_gtk_popover_menu_set_submenus (GObject * object,
+ const GValue * value)
+{
+ GladeWidget *gbox;
+ GtkWidget *child;
+ gint new_size, i;
+ gint old_size;
+ gchar *name;
+ gint page;
+
+ new_size = g_value_get_int (value);
+ old_size = count_children (GTK_CONTAINER (object), TRUE);
+
+ if (old_size == new_size)
+ return;
+ else if (old_size < new_size)
+ {
+ for (i = old_size; i < new_size; i++)
+ {
+ name = get_unused_name (GTK_POPOVER_MENU (object));
+ child = glade_placeholder_new ();
+ gtk_container_add_with_properties (GTK_CONTAINER (object), child,
+ "submenu", name, NULL);
+ g_free (name);
+ }
+ }
+ else
+ {
+ GList *children, *l;
+
+ children = gtk_container_get_children (GTK_CONTAINER (object));
+ for (l = g_list_last (children); l; l = l->prev)
+ {
+ if (old_size <= new_size)
+ break;
+
+ child = l->data;
+ if (GLADE_IS_PLACEHOLDER (child))
+ {
+ gtk_container_remove (GTK_CONTAINER (object), child);
+ old_size--;
+ }
+ }
+ }
+
+ gbox = glade_widget_get_from_gobject (object);
+ glade_widget_property_get (gbox, "current", &page);
+ glade_widget_property_set (gbox, "current", page);
+}
+
+static void
+glade_gtk_popover_menu_set_current (GObject *object,
+ const GValue *value)
+{
+ gint new_page;
+ GList *children;
+ GtkWidget *child;
+ gchar *submenu;
+
+ new_page = g_value_get_int (value);
+ children = gtk_container_get_children (GTK_CONTAINER (object));
+ child = g_list_nth_data (children, new_page);
+ if (child)
+ {
+ gtk_container_child_get (GTK_CONTAINER (object), child,
+ "submenu", &submenu,
+ NULL);
+ gtk_popover_menu_open_submenu (GTK_POPOVER_MENU (object), submenu);
+ g_free (submenu);
+ }
+
+ g_list_free (children);
+}
+
+void
+glade_gtk_popover_menu_set_property (GladeWidgetAdaptor * adaptor,
+ GObject * object,
+ const gchar * id,
+ const GValue * value)
+{
+ if (!strcmp (id, "submenus"))
+ glade_gtk_popover_menu_set_submenus (object, value);
+ else if (!strcmp (id, "current"))
+ glade_gtk_popover_menu_set_current (object, value);
+ else
+ GWA_GET_CLASS (GTK_TYPE_CONTAINER)->set_property (adaptor, object, id, value);
+}
+
+static gint
+get_visible_child (GtkPopoverMenu *popover)
+{
+ gchar *visible;
+ GList *children, *l;
+ gint ret, i;
+
+ ret = -1;
+
+ g_object_get (G_OBJECT (popover), "visible-submenu", &visible, NULL);
+ children = gtk_container_get_children (GTK_CONTAINER (popover));
+ for (l = children, i = 0; l; l = l->next, i++)
+ {
+ GtkWidget *child = l->data;
+ gchar *name;
+ gboolean found;
+
+ gtk_container_child_get (GTK_CONTAINER (popover), child, "submenu", &name, NULL);
+ found = !strcmp (visible, name);
+ g_free (name);
+ if (found)
+ {
+ ret = i;
+ break;
+ }
+ }
+ g_list_free (children);
+ g_free (visible);
+
+ return ret;
+}
+
+void
+glade_gtk_popover_menu_get_property (GladeWidgetAdaptor * adaptor,
+ GObject * object,
+ const gchar * id,
+ GValue * value)
+{
+ if (!strcmp (id, "submenus"))
+ {
+ g_value_reset (value);
+ g_value_set_int (value, count_children (GTK_CONTAINER (object), TRUE));
+ }
+ else if (!strcmp (id, "current"))
+ {
+ g_value_reset (value);
+ g_value_set_int (value, get_visible_child (GTK_POPOVER_MENU (object)));
+ }
+ else
+ GWA_GET_CLASS (GTK_TYPE_CONTAINER)->get_property (adaptor, object, id, value);
+}
+
+static gboolean
+glade_gtk_popover_menu_verify_submenus (GObject * object,
+ const GValue *value)
+{
+ gint new_size, old_size;
+
+ new_size = g_value_get_int (value);
+ old_size = count_children (GTK_CONTAINER (object), FALSE);
+
+ return old_size <= new_size;
+}
+
+static gboolean
+glade_gtk_popover_menu_verify_current (GObject *object,
+ const GValue *value)
+{
+ gint current;
+ gint submenus;
+
+ current = g_value_get_int (value);
+ submenus = count_children (GTK_CONTAINER (object), TRUE);
+
+ return 0 <= current && current < submenus;
+}
+
+gboolean
+glade_gtk_popover_menu_verify_property (GladeWidgetAdaptor * adaptor,
+ GObject * object,
+ const gchar * id,
+ const GValue * value)
+{
+ if (!strcmp (id, "submenus"))
+ return glade_gtk_popover_menu_verify_submenus (object, value);
+ else if (!strcmp (id, "current"))
+ return glade_gtk_popover_menu_verify_current (object, value);
+ else if (GWA_GET_CLASS (GTK_TYPE_CONTAINER)->verify_property)
+ return GWA_GET_CLASS (GTK_TYPE_CONTAINER)->verify_property (adaptor, object, id, value);
+
+ return TRUE;
+}
+
+static void
+update_position (GtkWidget *widget, gpointer data)
+{
+ GtkContainer *parent = data;
+ GladeWidget *gwidget;
+ gint position;
+
+ gwidget = glade_widget_get_from_gobject (widget);
+ if (gwidget)
+ {
+ gtk_container_child_get (parent, widget, "position", &position, NULL);
+ glade_widget_pack_property_set (gwidget, "position", position);
+ }
+}
+
+static void
+glade_gtk_popover_menu_set_child_position (GObject * container,
+ GObject * child,
+ GValue * value)
+{
+ static gboolean recursion = FALSE;
+ gint new_position, old_position;
+ gchar *visible_child;
+ GladeWidget *gbox;
+
+ g_object_get (container, "visible-submenu", &visible_child, NULL);
+
+ if (recursion)
+ return;
+
+ gtk_container_child_get (GTK_CONTAINER (container), GTK_WIDGET (child), "position", &old_position, NULL);
+ new_position = g_value_get_int (value);
+
+ if (old_position != new_position)
+ {
+ recursion = TRUE;
+ gtk_container_child_set (GTK_CONTAINER (container), GTK_WIDGET (child),
+ "position", new_position,
+ NULL);
+ gtk_container_forall (GTK_CONTAINER (container), update_position, container);
+ recursion = FALSE;
+ }
+
+ g_object_set (container, "visible-submenu", visible_child, NULL);
+ g_free (visible_child);
+
+ gbox = glade_widget_get_from_gobject (container);
+ glade_widget_pack_property_set (gbox, "visible-submenu", get_visible_child (GTK_POPOVER_MENU (container)));
+}
+
+void
+glade_gtk_popover_menu_set_child_property (GladeWidgetAdaptor * adaptor,
+ GObject * container,
+ GObject * child,
+ const gchar * id,
+ GValue * value)
+{
+ if (!strcmp (id, "position"))
+ glade_gtk_popover_menu_set_child_position (container, child, value);
+ else if (!strcmp (id, "submenu"))
+ gtk_container_child_set_property (GTK_CONTAINER (container),
+ GTK_WIDGET (child), id, value);
+ else
+ GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_set_property (adaptor, container, child, id, value);
+}
+
+void
+glade_gtk_popover_menu_get_child_property (GladeWidgetAdaptor * adaptor,
+ GObject * container,
+ GObject * child,
+ const gchar * id,
+ GValue * value)
+{
+ gtk_container_child_get_property (GTK_CONTAINER (container),
+ GTK_WIDGET (child), id, value);
+}
+
diff --git a/plugins/gtk+/gtk+.xml.in b/plugins/gtk+/gtk+.xml.in
index 5ae0b80..577810d 100644
--- a/plugins/gtk+/gtk+.xml.in
+++ b/plugins/gtk+/gtk+.xml.in
@@ -3368,6 +3368,37 @@
</properties>
</glade-widget-class>
+ <glade-widget-class name="GtkPopoverMenu" generic-name="popovermenu" _title="Popover Menu">
+ <constructor-function>glade_gtk_popover_menu_constructor</constructor-function>
+ <post-create-function>glade_gtk_popover_menu_post_create</post-create-function>
+ <add-child-function>glade_gtk_popover_menu_add_child</add-child-function>
+ <remove-child-function>glade_gtk_popover_menu_remove_child</remove-child-function>
+ <replace-child-function>glade_gtk_popover_menu_replace_child</replace-child-function>
+ <get-property-function>glade_gtk_popover_menu_get_property</get-property-function>
+ <set-property-function>glade_gtk_popover_menu_set_property</set-property-function>
+ <verify-function>glade_gtk_popover_menu_verify_property</verify-function>
+ <child-set-property-function>glade_gtk_popover_menu_set_child_property</child-set-property-function>
+ <child-get-property-function>glade_gtk_popover_menu_get_child_property</child-get-property-function>
+
+ <properties>
+ <property id="visible-submenu" disabled="True"/>
+ <property id="submenus" _name="Number of submenus" save="False" default="1"> <!--
custom-layout="True" -->
+ <parameter-spec>
+ <type>GParamInt</type>
+ <min>1</min>
+ </parameter-spec>
+ <_tooltip>The number of submenus in the popover menu</_tooltip>
+ </property>
+ <property id="current" _name="Edit menu" save="False" default="0"> <!-- custom-layout="True" -->
+ <parameter-spec>
+ <type>GParamInt</type>
+ <min>0</min>
+ </parameter-spec>
+ <_tooltip>Set the currently active submenu to edit, this property will not be saved</_tooltip>
+ </property>
+ </properties>
+ </glade-widget-class>
+
<glade-widget-class name="GtkLinkButton" generic-name="linkbutton" _title="Link Button">
<properties>
<!-- The pspec of this prop says that the default is http://www.gtk.org but gtk_link_button_init()
does
@@ -5362,6 +5393,7 @@
<glade-widget-class-ref name="GtkHeaderBar" />
<glade-widget-class-ref name="GtkStack" />
<glade-widget-class-ref name="GtkPopover"/>
+ <glade-widget-class-ref name="GtkPopoverMenu"/>
</glade-widget-group>
<glade-widget-group name="gtk-control-display" _title="Control and Display">
diff --git a/plugins/gtk+/icons/16x16/Makefile.am b/plugins/gtk+/icons/16x16/Makefile.am
index 2601a11..c196a22 100644
--- a/plugins/gtk+/icons/16x16/Makefile.am
+++ b/plugins/gtk+/icons/16x16/Makefile.am
@@ -80,6 +80,7 @@ icons_DATA = \
widget-gtk-pagesetupdialog.png \
widget-gtk-placessidebar.png \
widget-gtk-popover.png \
+ widget-gtk-popovermenu.png \
widget-gtk-printdialog.png \
widget-gtk-progressbar.png \
widget-gtk-searchbar.png \
diff --git a/plugins/gtk+/icons/16x16/widget-gtk-popover.png b/plugins/gtk+/icons/16x16/widget-gtk-popover.png
index 5f82f3c..154a77c 100644
Binary files a/plugins/gtk+/icons/16x16/widget-gtk-popover.png and
b/plugins/gtk+/icons/16x16/widget-gtk-popover.png differ
diff --git a/plugins/gtk+/icons/16x16/widget-gtk-popovermenu.png
b/plugins/gtk+/icons/16x16/widget-gtk-popovermenu.png
new file mode 100644
index 0000000..5f82f3c
Binary files /dev/null and b/plugins/gtk+/icons/16x16/widget-gtk-popovermenu.png differ
diff --git a/plugins/gtk+/icons/22x22/Makefile.am b/plugins/gtk+/icons/22x22/Makefile.am
index a08b04c..6ec90df 100644
--- a/plugins/gtk+/icons/22x22/Makefile.am
+++ b/plugins/gtk+/icons/22x22/Makefile.am
@@ -80,6 +80,7 @@ icons_DATA = \
widget-gtk-pagesetupdialog.png \
widget-gtk-placessidebar.png \
widget-gtk-popover.png \
+ widget-gtk-popovermenu.png \
widget-gtk-printdialog.png \
widget-gtk-progressbar.png \
widget-gtk-searchbar.png \
diff --git a/plugins/gtk+/icons/22x22/widget-gtk-popover.png b/plugins/gtk+/icons/22x22/widget-gtk-popover.png
index ac5e04c..bc2d5d0 100644
Binary files a/plugins/gtk+/icons/22x22/widget-gtk-popover.png and
b/plugins/gtk+/icons/22x22/widget-gtk-popover.png differ
diff --git a/plugins/gtk+/icons/22x22/widget-gtk-popovermenu.png
b/plugins/gtk+/icons/22x22/widget-gtk-popovermenu.png
new file mode 100644
index 0000000..ac5e04c
Binary files /dev/null and b/plugins/gtk+/icons/22x22/widget-gtk-popovermenu.png differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]