summaryrefslogtreecommitdiff
path: root/gtk/gtkbox.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2011-05-25 23:38:59 +0200
committerBenjamin Otte <otte@redhat.com>2011-06-02 02:03:51 +0200
commitcd838480eb01ad8a9185cb1d407088b7eb34d926 (patch)
tree2b6d75f8c6e363f05411252ebf44958ad2ab9960 /gtk/gtkbox.c
parentbc9c43c1cbb1fdb7faf292ee0e57c5efd06e890e (diff)
downloadgtk+-cd838480eb01ad8a9185cb1d407088b7eb34d926.tar.gz
box: Add support for siblings in widget paths of box children
Diffstat (limited to 'gtk/gtkbox.c')
-rw-r--r--gtk/gtkbox.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/gtk/gtkbox.c b/gtk/gtkbox.c
index b1d1df952b..0c52a906e3 100644
--- a/gtk/gtkbox.c
+++ b/gtk/gtkbox.c
@@ -115,6 +115,7 @@ struct _GtkBoxPrivate
GtkOrientation orientation;
gint16 spacing;
+ GtkWidgetPath *sibling_path;
guint default_expand : 1;
guint homogeneous : 1;
@@ -182,6 +183,9 @@ static void gtk_box_get_child_property (GtkContainer *container,
GValue *value,
GParamSpec *pspec);
static GType gtk_box_child_type (GtkContainer *container);
+static GtkWidgetPath * gtk_box_get_path_for_child
+ (GtkContainer *container,
+ GtkWidget *child);
static void gtk_box_get_preferred_width (GtkWidget *widget,
@@ -226,6 +230,7 @@ gtk_box_class_init (GtkBoxClass *class)
container_class->child_type = gtk_box_child_type;
container_class->set_child_property = gtk_box_set_child_property;
container_class->get_child_property = gtk_box_get_child_property;
+ container_class->get_path_for_child = gtk_box_get_path_for_child;
gtk_container_class_handle_border_width (container_class);
g_object_class_override_property (object_class,
@@ -831,6 +836,113 @@ gtk_box_get_child_property (GtkContainer *container,
}
}
+typedef struct _CountingData CountingData;
+struct _CountingData {
+ GtkWidget *widget;
+ gboolean found;
+ guint count;
+};
+
+static void
+count_widget_position (GtkWidget *widget,
+ gpointer data)
+{
+ CountingData *count = data;
+
+#if 0
+ /* We cannot reliably detect changes in widget visibility */
+ if (!gtk_widget_get_visible (widget))
+ return;
+#endif
+
+ if (count->found)
+ return;
+
+ if (count->widget == widget)
+ {
+ count->found = TRUE;
+ return;
+ }
+
+ count->count++;
+}
+
+static guint
+gtk_box_get_visible_position (GtkBox *box,
+ GtkWidget *child)
+{
+ CountingData count = { child, FALSE, 0 };
+
+ /* forall iterates in visible order */
+ gtk_container_forall (GTK_CONTAINER (box),
+ count_widget_position,
+ &count);
+
+ g_assert (count.found);
+ return count.count;
+}
+
+static void
+add_widget_to_path (GtkWidget *widget,
+ gpointer path)
+{
+#if 0
+ /* We cannot reliably detect changes in widget visibility */
+ if (!gtk_widget_get_visible (widget))
+ return;
+#endif
+
+ gtk_widget_path_append_for_widget (path, widget);
+}
+
+static GtkWidgetPath *
+gtk_box_get_path_for_child (GtkContainer *container,
+ GtkWidget *child)
+{
+ GtkWidgetPath *path;
+ GtkBox *box;
+ GtkBoxPrivate *private;
+
+ box = GTK_BOX (container);
+ private = box->priv;
+
+ if (private->sibling_path == NULL)
+ {
+ private->sibling_path = gtk_widget_path_new ();
+ /* forall iterates in visible order */
+ gtk_container_forall (container,
+ add_widget_to_path,
+ private->sibling_path);
+ }
+
+ path = gtk_widget_path_copy (gtk_widget_get_path (GTK_WIDGET (container)));
+ if (gtk_widget_get_visible (child))
+ gtk_widget_path_append_with_siblings (path,
+ private->sibling_path,
+ gtk_box_get_visible_position (box,
+ child));
+ else
+ gtk_widget_path_append_for_widget (path, child);
+
+ return path;
+}
+
+static void
+gtk_box_invalidate_order (GtkBox *box)
+{
+ GtkBoxPrivate *private = box->priv;
+
+ if (private->sibling_path != NULL)
+ {
+ gtk_widget_path_unref (private->sibling_path);
+ private->sibling_path = NULL;
+ }
+
+ gtk_container_foreach (GTK_CONTAINER (box),
+ (GtkCallback) gtk_widget_reset_style,
+ NULL);
+}
+
static void
gtk_box_pack (GtkBox *box,
GtkWidget *child,
@@ -857,6 +969,7 @@ gtk_box_pack (GtkBox *box,
gtk_widget_freeze_child_notify (child);
+ gtk_box_invalidate_order (box);
gtk_widget_set_parent (child, GTK_WIDGET (box));
gtk_widget_child_notify (child, "expand");
@@ -1495,7 +1608,10 @@ gtk_box_reorder_child (GtkBox *box,
gtk_widget_child_notify (child, "position");
if (gtk_widget_get_visible (child)
&& gtk_widget_get_visible (GTK_WIDGET (box)))
- gtk_widget_queue_resize (child);
+ {
+ gtk_box_invalidate_order (box);
+ gtk_widget_queue_resize (child);
+ }
}
/**
@@ -1614,10 +1730,11 @@ gtk_box_set_child_packing (GtkBox *box,
gtk_widget_child_notify (child, "padding");
if (pack_type != GTK_PACK_END)
pack_type = GTK_PACK_START;
- if (child_info->pack_type != pack_type)
+ if (child_info->pack != pack_type)
{
child_info->pack = GTK_PACK_END;
gtk_widget_child_notify (child, "pack-type");
+ gtk_box_invalidate_order (box);
}
if (gtk_widget_get_visible (child)
@@ -1680,7 +1797,10 @@ gtk_box_remove (GtkContainer *container,
* since that's what is needed by toplevels.
*/
if (was_visible)
- gtk_widget_queue_resize (GTK_WIDGET (container));
+ {
+ gtk_box_invalidate_order (box);
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
break;
}