Seems I didn't get all details of Behdad's algorithm. Fixed. Like it much better now: http://taschenorakel.de/media/movies/natural-size-behdad-style.ogg TODO: - get size-group-natural-size interaction halfway right. - get agreement on code/API (commit?) - factor out Behdad's/Havoc's natural size algorithm for reuse Am Dienstag, den 08.01.2008, 19:17 +0100 schrieb Mathias Hasselmann: > Attached the current state of natural size, with an API similiar to > Havoc's wishes and implementing the natural size allocation they both > suggested. > > Havoc suggest to have two methods: get_desired_width() and > get_desired_height(), but I implemented get_desired_size(), since I do > not see how to implement this for GtkLabel, without recalculating the > entire layout four times on each desired size request. -- Mathias Hasselmann <mathias hasselmann gmx de> Openismus GmbH: http://www.openismus.com/ Personal Site: http://taschenorakel.de/
diff -u b/gtk/gtkhbox.c b/gtk/gtkhbox.c
--- b/gtk/gtkhbox.c
+++ b/gtk/gtkhbox.c
@@ -169,7 +169,7 @@
}
static gint
-gtk_vbox_compare_gap (gconstpointer p1,
+gtk_hbox_compare_gap (gconstpointer p1,
gconstpointer p2,
gpointer data)
{
@@ -178,16 +178,14 @@
const GtkBoxSpreading *c2 = p2;
const gint d1 = MAX (sizes[c1->index].natural_size -
- sizes[c1->index].minimum_size,
- 0);
+ sizes[c1->index].minimum_size, 0);
const gint d2 = MAX (sizes[c2->index].natural_size -
- sizes[c2->index].minimum_size,
- 0);
+ sizes[c2->index].minimum_size, 0);
- gint delta = (d1 - d2);
+ gint delta = (d2 - d1); /* sort descending by gap... */
- if (0 == delta)
- delta = (c1->index - c2->index);
+ if (0 == delta) /* ...and position on draw. */
+ delta = (c2->index - c1->index);
return delta;
}
@@ -209,6 +207,8 @@
nexpand_children = 0;
children = box->children;
+ /* Count number of visible children. */
+
while (children)
{
child = children->data;
@@ -236,7 +236,7 @@
gint width;
gint extra;
- gint x, i;
+ gint i, x;
width = (allocation->width - border_width * 2 -
(nvis_children - 1) * box->spacing);
@@ -247,7 +247,7 @@
}
else
{
- /* Retreive desired size for visible children */
+ /* Retreive desired size for visible children. */
for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
{
@@ -275,23 +275,51 @@
}
}
- /* Sort children by difference between natural and minimum size */
+ /* Distribute the container's extra space c_gap. We want to assign
+ * this space such that the sum of extra space assigned to children
+ * (c^i_gap) is equal to c_cap. The case that there's not enough
+ * space for all children to take their natural size needs some
+ * attention. The goals we want to achieve are:
+ *
+ * a) Maximize number of children taking their natural size.
+ * b) The allocated size of children should be a continuous
+ * function of c_gap. That is, increasing the container size by
+ * one pixel should never make drastic changes in the distribution.
+ * c) If child i takes its natural size and child j doesn't,
+ * child j should have received at least as much gap as child i.
+ *
+ * The following code distributes the additional space by following
+ * this rules.
+ */
+
+ /* Sort descending by gap and position. */
g_qsort_with_data (spreading,
nvis_children, sizeof (GtkBoxSpreading),
- gtk_vbox_compare_gap, sizes);
+ gtk_hbox_compare_gap, sizes);
- for (i = 0; width > 0 && i < nvis_children; ++i)
+ /* Distribute available space.
+ * This master piece of a loop was conceived by Behdad Esfahbod.
+ */
+ for (i = nvis_children - 1; i >= 0; --i)
{
- extra = sizes[spreading[i].index].natural_size
- - sizes[spreading[i].index].minimum_size;
-
- extra = MIN (width, extra);
- width -= extra;
+ /* Divide remaining space by number of remaining children.
+ * Sort order and reducing remaining space by assigned space
+ * ensures that space is distributed equally.
+ */
+ gint glue = (width + i) / (i + 1);
+ gint gap = sizes[spreading[i].index].natural_size
+ - sizes[spreading[i].index].minimum_size;
+ extra = MIN (glue, gap);
sizes[spreading[i].index].minimum_size += extra;
+
+ width -= extra;
}
+ /* Calculate space which hasn't distributed yet,
+ * and is available for expanding children.
+ */
if (nexpand_children > 0)
extra = width / nexpand_children;
else
@@ -308,7 +336,7 @@
else
x = allocation->x + allocation->width - border_width;;
- /* Allocate child positions */
+ /* Allocate child positions. */
i = 0;
children = box->children;
@@ -319,6 +347,8 @@
if (child->pack == packing && GTK_WIDGET_VISIBLE (child->widget))
{
+ /* Assign the child's size. */
+
if (box->homogeneous)
{
if (nvis_children == 1)
@@ -345,6 +375,8 @@
}
}
+ /* Assign the child's position. */
+
if (child->fill)
{
child_allocation.width = MAX (1, (gint) child_width - (gint) child->padding * 2);
Attachment:
signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil