summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2014-11-10 22:28:21 -0500
committerMatthias Clasen <mclasen@redhat.com>2014-11-10 22:28:21 -0500
commite533231f471afa029667983324ac9854217ba1b1 (patch)
tree1a52dd712ca7106f73779e21fd4c0b6b8fc55574
parent79f0f1ce316633c9af686b65cf49c1a072e1b648 (diff)
downloadglade-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.c421
-rw-r--r--plugins/gtk+/glade-stack-editor.ui61
-rw-r--r--plugins/gtk+/gtk+.xml.in21
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"/>