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