diff options
author | Matthias Clasen <mclasen@redhat.com> | 2014-11-10 22:28:21 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2014-11-10 22:28:21 -0500 |
commit | e533231f471afa029667983324ac9854217ba1b1 (patch) | |
tree | 1a52dd712ca7106f73779e21fd4c0b6b8fc55574 | |
parent | 79f0f1ce316633c9af686b65cf49c1a072e1b648 (diff) | |
download | glade-e533231f471afa029667983324ac9854217ba1b1.tar.gz |
Many GtkStack fixes
Implement all of the required adaptor functions, add a virtual
'page' property and use it instead of visible-child-name to switch
between the pages to edit.
-rw-r--r-- | plugins/gtk+/glade-gtk-stack.c | 421 | ||||
-rw-r--r-- | plugins/gtk+/glade-stack-editor.ui | 61 | ||||
-rw-r--r-- | plugins/gtk+/gtk+.xml.in | 21 |
3 files changed, 480 insertions, 23 deletions
diff --git a/plugins/gtk+/glade-gtk-stack.c b/plugins/gtk+/glade-gtk-stack.c index 99ba5df6..c71ae08e 100644 --- a/plugins/gtk+/glade-gtk-stack.c +++ b/plugins/gtk+/glade-gtk-stack.c @@ -33,6 +33,7 @@ glade_gtk_stack_selection_changed (GladeProject * project, GList *list; GtkWidget *page, *sel_widget; GtkStack *stack = GTK_STACK (glade_widget_get_object (gwidget)); + gint position; if ((list = glade_project_selection_get (project)) != NULL && g_list_length (list) == 1) @@ -52,6 +53,8 @@ glade_gtk_stack_selection_changed (GladeProject * project, gtk_widget_is_ancestor (sel_widget, page)) { gtk_stack_set_visible_child (stack, page); + gtk_container_child_get (GTK_CONTAINER (stack), page, "position", &position, NULL); + glade_widget_property_set (gwidget, "page", position); break; } } @@ -89,9 +92,7 @@ glade_gtk_stack_post_create (GladeWidgetAdaptor *adaptor, GladeWidget *gwidget = glade_widget_get_from_gobject (container); if (reason == GLADE_CREATE_USER) - gtk_stack_add_named (GTK_STACK (container), - glade_placeholder_new (), - "page0"); + gtk_stack_add_named (GTK_STACK (container), glade_placeholder_new (), "page0"); g_signal_connect (G_OBJECT (gwidget), "notify::project", G_CALLBACK (glade_gtk_stack_project_changed), NULL); @@ -100,6 +101,42 @@ glade_gtk_stack_post_create (GladeWidgetAdaptor *adaptor, } +static gchar * +get_unused_name (GtkStack *stack) +{ + gchar *name; + gint i; + + i = 0; + while (TRUE) + { + name = g_strdup_printf ("page%d", i); + if (gtk_stack_get_child_by_name (stack, name) == NULL) + return name; + g_free (name); + i++; + } + + return NULL; +} + +static void +update_position_with_command (GtkWidget *widget, gpointer data) +{ + GtkContainer *parent = data; + GladeWidget *gwidget; + GladeProperty *property; + gint position; + + gwidget = glade_widget_get_from_gobject (widget); + if (!gwidget) + return; + + property = glade_widget_get_pack_property (gwidget, "position"); + gtk_container_child_get (parent, widget, "position", &position, NULL); + glade_command_set_property (property, position); +} + void glade_gtk_stack_child_action_activate (GladeWidgetAdaptor * adaptor, GObject * container, @@ -109,9 +146,17 @@ glade_gtk_stack_child_action_activate (GladeWidgetAdaptor * adaptor, if (!strcmp (action_path, "insert_page_after") || !strcmp (action_path, "insert_page_before")) { + GladeWidget *parent; + GladeProperty *property; gint position; gchar *name; GtkWidget *new_widget; + gint pages; + + parent = glade_widget_get_from_gobject (container); + glade_widget_property_get (parent, "pages", &pages); + + glade_command_push_group (_("Insert placeholder to %s"), glade_widget_get_name (parent)); gtk_container_child_get (GTK_CONTAINER (container), GTK_WIDGET (object), "position", &position, NULL); @@ -119,17 +164,49 @@ glade_gtk_stack_child_action_activate (GladeWidgetAdaptor * adaptor, if (!strcmp (action_path, "insert_page_after")) position++; - name = g_strdup_printf ("page%d", position); + name = get_unused_name (GTK_STACK (container)); new_widget = glade_placeholder_new (); - gtk_stack_add_named (GTK_STACK (container), new_widget, name); + gtk_container_child_set (GTK_CONTAINER (container), new_widget, + "position", position, NULL); gtk_stack_set_visible_child (GTK_STACK (container), new_widget); + property = glade_widget_get_property (parent, "pages"); + glade_command_set_property (property, pages + 1); + + gtk_container_forall (GTK_CONTAINER (container), update_position_with_command, container); + + property = glade_widget_get_property (parent, "page"); + glade_command_set_property (property, position); + + glade_command_pop_group (); + g_free (name); } else if (strcmp (action_path, "remove_page") == 0) { - gtk_container_remove (GTK_CONTAINER (container), GTK_WIDGET (object)); + GladeWidget *parent; + GladeProperty *property; + gint pages; + gint position; + + parent = glade_widget_get_from_gobject (container); + glade_widget_property_get (parent, "pages", &pages); + + glade_command_push_group (_("Remove placeholder from %s"), glade_widget_get_name (parent)); + g_assert (GLADE_IS_PLACEHOLDER (object)); + gtk_container_remove (GTK_CONTAINER (container), GTK_WIDGET (object)); + + property = glade_widget_get_property (parent, "pages"); + glade_command_set_property (property, pages - 1); + + gtk_container_forall (GTK_CONTAINER (container), update_position_with_command, container); + + glade_widget_property_get (parent, "page", &position); + property = glade_widget_get_property (parent, "page"); + glade_command_set_property (property, position); + + glade_command_pop_group (); } else GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_action_activate (adaptor, @@ -148,3 +225,335 @@ glade_gtk_stack_create_editable (GladeWidgetAdaptor * adaptor, return GWA_GET_CLASS (GTK_TYPE_CONTAINER)->create_editable (adaptor, type); } +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 +gtk_stack_get_n_pages (GtkStack *stack, + gboolean include_placeholders) +{ + ChildData data; + + data.size = 0; + data.include_placeholders = include_placeholders; + gtk_container_forall (GTK_CONTAINER (stack), count_child, &data); + return data.size; +} + +static GtkWidget * +gtk_stack_get_nth_child (GtkStack *stack, + gint n) +{ + GList *children; + GtkWidget *child; + + children = gtk_container_get_children (GTK_CONTAINER (stack)); + child = g_list_nth_data (children, n); + g_list_free (children); + + return child; +} + +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_stack_set_n_pages (GObject * object, + const GValue * value) +{ + GladeWidget *gbox; + GtkStack *stack; + GtkWidget *child; + gint new_size, i; + gint old_size; + gchar *name; + gint page; + + stack = GTK_STACK (object); + + new_size = g_value_get_int (value); + old_size = gtk_stack_get_n_pages (stack, TRUE); + + if (old_size == new_size) + return; + + for (i = old_size; i < new_size; i++) + { + name = get_unused_name (stack); + child = glade_placeholder_new (); + gtk_stack_add_named (stack, child, name); + g_free (name); + } + + for (i = old_size; i > 0; i--) + { + if (old_size <= new_size) + break; + child = gtk_stack_get_nth_child (stack, i - 1); + if (GLADE_IS_PLACEHOLDER (child)) + { + gtk_container_remove (GTK_CONTAINER (stack), child); + old_size--; + } + } + + gtk_container_forall (GTK_CONTAINER (stack), update_position, stack); + + gbox = glade_widget_get_from_gobject (stack); + glade_widget_property_get (gbox, "page", &page); + glade_widget_property_set (gbox, "page", page); +} + +static void +glade_gtk_stack_set_page (GObject *object, + const GValue *value) +{ + gint new_page; + GList *children; + GtkWidget *child; + + 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_stack_set_visible_child (GTK_STACK (object), child); + + g_list_free (children); +} + +static gint +gtk_stack_get_page (GtkStack *stack) +{ + GtkWidget *child; + gint page; + + child = gtk_stack_get_visible_child (stack); + gtk_container_child_get (GTK_CONTAINER (stack), child, "position", &page, NULL); + return page; +} + +void +glade_gtk_stack_set_property (GladeWidgetAdaptor * adaptor, + GObject * object, + const gchar * id, + const GValue * value) +{ + if (!strcmp (id, "pages")) + glade_gtk_stack_set_n_pages (object, value); + else if (!strcmp (id, "page")) + glade_gtk_stack_set_page (object, value); + else + GWA_GET_CLASS (GTK_TYPE_CONTAINER)->set_property (adaptor, object, id, value); +} + +void +glade_gtk_stack_get_property (GladeWidgetAdaptor * adaptor, + GObject * object, + const gchar * id, + GValue * value) +{ + if (!strcmp (id, "pages")) + { + g_value_reset (value); + g_value_set_int (value, gtk_stack_get_n_pages (GTK_STACK (object), TRUE)); + } + else if (!strcmp (id, "page")) + { + g_value_reset (value); + g_value_set_int (value, gtk_stack_get_page (GTK_STACK (object))); + } + else + GWA_GET_CLASS (GTK_TYPE_CONTAINER)->get_property (adaptor, object, id, value); +} + +static void +glade_gtk_stack_set_child_position (GObject * container, + GObject * child, + const GValue * value) +{ + static gboolean recursion = FALSE; + gint new_position, old_position; + GladeWidget *gbox; + gint page; + + 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) + return; + + 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; + + gbox = glade_widget_get_from_gobject (container); + glade_widget_property_get (gbox, "page", &page); + glade_widget_property_set (gbox, "page", page); +} + +void +glade_gtk_stack_set_child_property (GladeWidgetAdaptor * adaptor, + GObject * container, + GObject * child, + const gchar * id, + GValue * value) +{ + if (!strcmp (id, "position")) + glade_gtk_stack_set_child_position (container, child, value); + else + GWA_GET_CLASS (GTK_TYPE_CONTAINER)->child_set_property (adaptor, container, child, id, value); +} + +static gboolean +glade_gtk_stack_verify_n_pages (GObject * object, + const GValue *value) +{ + gint new_size, old_size; + + new_size = g_value_get_int (value); + old_size = gtk_stack_get_n_pages (GTK_STACK (object), FALSE); + + return old_size <= new_size; +} + +static gboolean +glade_gtk_stack_verify_page (GObject *object, + const GValue *value) +{ + gint page; + gint pages; + + page = g_value_get_int (value); + pages = gtk_stack_get_n_pages (GTK_STACK (object), TRUE); + + return 0 <= page && page < pages; +} + +gboolean +glade_gtk_stack_verify_property (GladeWidgetAdaptor * adaptor, + GObject * object, + const gchar * id, + const GValue * value) +{ + if (!strcmp (id, "pages")) + return glade_gtk_stack_verify_n_pages (object, value); + else if (!strcmp (id, "page")) + return glade_gtk_stack_verify_page (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; +} + +void +glade_gtk_stack_add_child (GladeWidgetAdaptor * adaptor, + GObject * object, + GObject * child) +{ + GladeWidget *gbox, *gchild; + gint pages, page; + + if (!glade_widget_superuser () && !GLADE_IS_PLACEHOLDER (child)) + { + GList *l, *children; + + children = gtk_container_get_children (GTK_CONTAINER (object)); + + for (l = g_list_last (children); l; l = l->prev) + { + GtkWidget *widget = l->data; + if (GLADE_IS_PLACEHOLDER (widget)) + { + gtk_container_remove (GTK_CONTAINER (object), widget); + break; + } + } + g_list_free (children); + } + + gtk_container_add (GTK_CONTAINER (object), GTK_WIDGET (child)); + + gbox = glade_widget_get_from_gobject (object); + glade_widget_property_get (gbox, "pages", &pages); + glade_widget_property_set (gbox, "pages", pages); + glade_widget_property_get (gbox, "page", &page); + glade_widget_property_set (gbox, "page", page); + + gchild = glade_widget_get_from_gobject (child); + if (gchild != NULL) + glade_widget_set_pack_action_visible (gchild, "remove_page", FALSE); +} + +void +glade_gtk_stack_remove_child (GladeWidgetAdaptor * adaptor, + GObject * object, + GObject * child) +{ + GladeWidget *gbox; + gint pages, page; + + gtk_container_remove (GTK_CONTAINER (object), GTK_WIDGET (child)); + + gbox = glade_widget_get_from_gobject (object); + glade_widget_property_get (gbox, "pages", &pages); + glade_widget_property_set (gbox, "pages", pages); + glade_widget_property_get (gbox, "page", &page); + glade_widget_property_set (gbox, "page", page); +} + +void +glade_gtk_stack_replace_child (GladeWidgetAdaptor * adaptor, + GObject * container, + GObject * current, + GObject * new_widget) +{ + GladeWidget *gchild; + GladeWidget *gbox; + gint pages, page; + + GWA_GET_CLASS (GTK_TYPE_CONTAINER)->replace_child (adaptor, + container, + current, + new_widget); + + gbox = glade_widget_get_from_gobject (container); + glade_widget_property_get (gbox, "pages", &pages); + glade_widget_property_set (gbox, "pages", pages); + glade_widget_property_get (gbox, "page", &page); + glade_widget_property_set (gbox, "page", page); + + gchild = glade_widget_get_from_gobject (new_widget); + if (gchild != NULL) + glade_widget_set_pack_action_visible (gchild, "remove_page", FALSE); + +} diff --git a/plugins/gtk+/glade-stack-editor.ui b/plugins/gtk+/glade-stack-editor.ui index 59c6ab95..da553bf5 100644 --- a/plugins/gtk+/glade-stack-editor.ui +++ b/plugins/gtk+/glade-stack-editor.ui @@ -65,32 +65,57 @@ Author: Matthias Clasen <mclasen@redhat.com> </packing> </child> <child> - <object class="GladePropertyLabel" id="visible_child_label"> + <object class="GladePropertyLabel" id="pages_label"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="hexpand">False</property> <property name="margin_left">12</property> - <property name="property_name">visible-child-name</property> + <property name="hexpand">False</property> + <property name="property_name">pages</property> </object> <packing> <property name="left_attach">0</property> <property name="top_attach">2</property> <property name="width">2</property> - <property name="height">1</property> </packing> </child> <child> - <object class="GladePropertyShell" id="visible_child_editor"> + <object class="GladePropertyShell" id="pages_editor"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="hexpand">True</property> - <property name="property_name">visible-child-name</property> + <property name="hexpand">False</property> + <property name="property_name">pages</property> </object> <packing> <property name="left_attach">2</property> <property name="top_attach">2</property> <property name="width">4</property> - <property name="height">1</property> + </packing> + </child> + <child> + <object class="GladePropertyLabel" id="page_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">12</property> + <property name="hexpand">False</property> + <property name="property_name">page</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + <property name="width">2</property> + </packing> + </child> + <child> + <object class="GladePropertyShell" id="page_editor"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">False</property> + <property name="property_name">page</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">3</property> + <property name="width">4</property> </packing> </child> <child> @@ -104,7 +129,7 @@ Author: Matthias Clasen <mclasen@redhat.com> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">3</property> + <property name="top_attach">4</property> <property name="width">2</property> <property name="height">1</property> </packing> @@ -118,7 +143,7 @@ Author: Matthias Clasen <mclasen@redhat.com> </object> <packing> <property name="left_attach">2</property> - <property name="top_attach">3</property> + <property name="top_attach">4</property> <property name="width">1</property> <property name="height">1</property> </packing> @@ -132,7 +157,7 @@ Author: Matthias Clasen <mclasen@redhat.com> </object> <packing> <property name="left_attach">3</property> - <property name="top_attach">3</property> + <property name="top_attach">4</property> <property name="width">1</property> <property name="height">1</property> </packing> @@ -147,7 +172,7 @@ Author: Matthias Clasen <mclasen@redhat.com> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">4</property> + <property name="top_attach">5</property> <property name="width">2</property> <property name="height">1</property> </packing> @@ -161,7 +186,7 @@ Author: Matthias Clasen <mclasen@redhat.com> </object> <packing> <property name="left_attach">2</property> - <property name="top_attach">4</property> + <property name="top_attach">5</property> <property name="width">4</property> <property name="height">1</property> </packing> @@ -176,7 +201,7 @@ Author: Matthias Clasen <mclasen@redhat.com> </object> <packing> <property name="left_attach">0</property> - <property name="top_attach">5</property> + <property name="top_attach">6</property> <property name="width">2</property> <property name="height">1</property> </packing> @@ -190,7 +215,7 @@ Author: Matthias Clasen <mclasen@redhat.com> </object> <packing> <property name="left_attach">2</property> - <property name="top_attach">5</property> + <property name="top_attach">6</property> <property name="width">4</property> <property name="height">1</property> </packing> @@ -205,8 +230,10 @@ Author: Matthias Clasen <mclasen@redhat.com> </child> <child-editors> <editor id="embed"/> - <editor id="visible_child_label"/> - <editor id="visible_child_editor"/> + <editor id="pages_label"/> + <editor id="pages_editor"/> + <editor id="page_label"/> + <editor id="page_editor"/> <editor id="hhomogeneous_editor"/> <editor id="vhomogeneous_editor"/> <editor id="transition_type_label"/> diff --git a/plugins/gtk+/gtk+.xml.in b/plugins/gtk+/gtk+.xml.in index 3e5bd723..252ae0d6 100644 --- a/plugins/gtk+/gtk+.xml.in +++ b/plugins/gtk+/gtk+.xml.in @@ -2458,13 +2458,34 @@ <glade-widget-class name="GtkStack" generic-name="stack" _title="Stack" since="3.10"> <create-editable-function>glade_gtk_stack_create_editable</create-editable-function> <post-create-function>glade_gtk_stack_post_create</post-create-function> + <add-child-function>glade_gtk_stack_add_child</add-child-function> + <remove-child-function>glade_gtk_stack_remove_child</remove-child-function> + <replace-child-function>glade_gtk_stack_replace_child</replace-child-function> <child-action-activate-function>glade_gtk_stack_child_action_activate</child-action-activate-function> + <get-property-function>glade_gtk_stack_get_property</get-property-function> + <set-property-function>glade_gtk_stack_set_property</set-property-function> + <child-set-property-function>glade_gtk_stack_set_child_property</child-set-property-function> + <verify-function>glade_gtk_stack_verify_property</verify-function> <packing-actions> <action id="insert_page_before" _name="Insert Page Before" stock="list-add"/> <action id="insert_page_after" _name="Insert Page After" stock="list-add"/> <action id="remove_page" _name="Remove Page" stock="list-remove"/> </packing-actions> <properties> + <property id="pages" _name="Number of pages" save="False" default="1" custom-layout="True"> + <parameter-spec> + <type>GParamInt</type> + <min>1</min> + </parameter-spec> + <_tooltip>The number of pages in the stack</_tooltip> + </property> + <property id="page" _name="Edit page" save="False" default="0" custom-layout="True"> + <parameter-spec> + <type>GParamInt</type> + <min>0</min> + </parameter-spec> + <_tooltip>Set the currently active page to edit, this property will not be saved</_tooltip> + </property> <property id="visible-child" save="False" disabled="True"/> <property id="visible-child-name" _name="Visible child" save="False" custom-layout="True"/> <property id="homogeneous" save="False" disabled="True"/> |