box: Add support for siblings in widget paths of box children

This commit is contained in:
Benjamin Otte 2011-05-25 23:38:59 +02:00
parent bc9c43c1cb
commit cd838480eb

View File

@ -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_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_box_invalidate_order (box);
gtk_widget_queue_resize (GTK_WIDGET (container));
}
break;
}