summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2010-04-10 22:39:11 -0400
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2010-04-10 22:39:11 -0400
commit6b89f05a99f62281953a806de3ef332d7e777ac9 (patch)
tree9c5ca498feb2595c65533bc86264470344aced93
parent639e396147a02010a0d3eb7ec1cbef542321c2b2 (diff)
downloadgdk-pixbuf-6b89f05a99f62281953a806de3ef332d7e777ac9.tar.gz
Implemented gtk_extended_layout_is_height_for_width() and added another guess algorithm
This patch adds another commented algorythm to find the collective minimum and natural height for a said width of a horizontally oriented box (or the opposite). The algorithm works quite well and can be optimized a bit more - currently its commented because GtkLabel cannot effectively do width-for-height calculations (doh). Further, this patch returns an is_height_for_width() preference depending on the boxes orientation (vertical boxes are width-for-height).
-rw-r--r--gtk/gtkbox.c95
1 files changed, 77 insertions, 18 deletions
diff --git a/gtk/gtkbox.c b/gtk/gtkbox.c
index 144124a6a..27c4de118 100644
--- a/gtk/gtkbox.c
+++ b/gtk/gtkbox.c
@@ -113,6 +113,7 @@ static void gtk_box_extended_layout_init (GtkExtendedLayoutIface *iface);
static void gtk_box_get_desired_size (GtkExtendedLayout *layout,
GtkRequisition *minimum_size,
GtkRequisition *natural_size);
+static gboolean gtk_box_is_height_for_width (GtkExtendedLayout *layout);
static void gtk_box_get_width_for_height (GtkExtendedLayout *layout,
gint height,
gint *minimum_width,
@@ -122,7 +123,7 @@ static void gtk_box_get_height_for_width (GtkExtendedLayout *layout,
gint *minimum_height,
gint *natural_height);
-GtkExtendedLayoutIface *parent_extended_layout_iface;
+static GtkExtendedLayoutIface *parent_extended_layout_iface;
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkBox, gtk_box, GTK_TYPE_CONTAINER,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,
@@ -747,11 +748,20 @@ gtk_box_extended_layout_init (GtkExtendedLayoutIface *iface)
{
parent_extended_layout_iface = g_type_interface_peek_parent (iface);
+ iface->is_height_for_width = gtk_box_is_height_for_width;
iface->get_desired_size = gtk_box_get_desired_size;
iface->get_height_for_width = gtk_box_get_height_for_width;
iface->get_width_for_height = gtk_box_get_width_for_height;
}
+static gboolean
+gtk_box_is_height_for_width (GtkExtendedLayout *layout)
+{
+ GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (layout);
+
+ return (private->orientation == GTK_ORIENTATION_HORIZONTAL);
+}
+
static void
gtk_box_get_desired_size (GtkExtendedLayout *layout,
GtkRequisition *minimum_size,
@@ -949,23 +959,62 @@ size_fits_for_dimension (GtkBox *box,
static void
-gtk_box_compute_size_for_awkward_orientation (GtkBox *box,
- gint avail_size,
- gint *minimum_size,
- gint *natural_size)
+gtk_box_bisect_for_size_in_opposing_orientation (GtkBox *box,
+ gboolean check_natural,
+ gint avail_size,
+ gint floor,
+ gint ceiling,
+ gint *size)
+{
+ if (ceiling - floor <= 1)
+ *size = ceiling;
+ else
+ {
+ gint check_size = floor + (ceiling - floor) / 2;
+
+ if (size_fits_for_dimension (box, avail_size, check_size, check_natural))
+
+ /* If check_size is large enough for box to fit into avail_size, we go on
+ * to check between the given floor and check_size as the new ceiling
+ */
+
+ gtk_box_bisect_for_size_in_opposing_orientation (box, check_natural, avail_size,
+ floor, check_size, size);
+ else
+ gtk_box_bisect_for_size_in_opposing_orientation (box, check_natural, avail_size,
+ check_size, ceiling, size);
+
+ }
+}
+
+static void
+gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
+ gint avail_size,
+ gint *minimum_size,
+ gint *natural_size)
{
gint minimum, natural;
-
- /* Find the smallest possible fit in the orientation of 'box' where 'avail_size' is the available
- * size in the opposing orientation
+ gint min_ceiling, nat_ceiling;
+ gint step = 200;
+
+ /* First a large gap to search inside of
*/
- for (minimum = 1; !size_fits_for_dimension (box, avail_size, minimum, FALSE); minimum++);
+ for (min_ceiling = (step + 1); !size_fits_for_dimension (box, avail_size, min_ceiling, FALSE); min_ceiling += step);
- /* Starting from the minimum available size, do the same to find the smallest allocation where
- * all children receive their natural size
+ /* This will find the minimum sizes by halfing the guesses until they are found
*/
- for (natural = minimum; !size_fits_for_dimension (box, avail_size, natural, TRUE); natural++);
-
+ gtk_box_bisect_for_size_in_opposing_orientation (box, FALSE, avail_size,
+ min_ceiling - step,
+ min_ceiling,
+ &minimum);
+
+ /* Basing the natural size on the found minimum, do the same operation for the natural size */
+ for (nat_ceiling = minimum + step; !size_fits_for_dimension (box, avail_size, nat_ceiling, TRUE); nat_ceiling += step);
+ gtk_box_bisect_for_size_in_opposing_orientation (box, TRUE, avail_size,
+ nat_ceiling - step,
+ nat_ceiling,
+ &natural);
+
if (minimum_size)
*minimum_size = minimum;
@@ -1050,9 +1099,14 @@ gtk_box_get_width_for_height (GtkExtendedLayout *layout,
GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (layout);
if (private->orientation == GTK_ORIENTATION_VERTICAL)
-/* gtk_box_compute_size_for_awkward_orientation (box, height, minimum_width, natural_width); */
- /* Have the base class return the values previously computed by get_desired_size() */
+ {
+#if 0
+ gtk_box_compute_size_for_opposing_orientation (box, height, minimum_width, natural_width);
+#else
+ /* Have the base class return the values previously computed by get_desired_size() */
parent_extended_layout_iface->get_width_for_height (layout, height, minimum_width, natural_width);
+#endif
+ }
else
gtk_box_compute_size_for_orientation (box, height, minimum_width, natural_width);
}
@@ -1067,9 +1121,14 @@ gtk_box_get_height_for_width (GtkExtendedLayout *layout,
GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (layout);
if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
-/* gtk_box_compute_size_for_awkward_orientation (box, width, minimum_height, natural_height); */
- /* Have the base class return the values previously computed by get_desired_size() */
- parent_extended_layout_iface->get_height_for_width (layout, width, minimum_height, natural_height);
+ {
+#if 0
+ gtk_box_compute_size_for_opposing_orientation (box, width, minimum_height, natural_height);
+#else
+ /* Have the base class return the values previously computed by get_desired_size() */
+ parent_extended_layout_iface->get_height_for_width (layout, width, minimum_height, natural_height);
+#endif
+ }
else
gtk_box_compute_size_for_orientation (box, width, minimum_height, natural_height);
}