summaryrefslogtreecommitdiff
path: root/gtk/gtkextendedlayout.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkextendedlayout.c')
-rw-r--r--gtk/gtkextendedlayout.c381
1 files changed, 346 insertions, 35 deletions
diff --git a/gtk/gtkextendedlayout.c b/gtk/gtkextendedlayout.c
index a8293e32de..0da095342b 100644
--- a/gtk/gtkextendedlayout.c
+++ b/gtk/gtkextendedlayout.c
@@ -24,9 +24,14 @@
#include <config.h>
#include "gtkextendedlayout.h"
#include "gtksizegroup.h"
+#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
+
+#define DEBUG_EXTENDED_LAYOUT 0
+
+
GType
gtk_extended_layout_get_type (void)
{
@@ -45,32 +50,40 @@ gtk_extended_layout_get_type (void)
return extended_layout_type;
}
-/**
- * gtk_extended_layout_get_desired_size:
- * @layout: a #GtkExtendedLayout instance
- * @minimum_size: location for storing the minimum size, or %NULL
- * @natural_size: location for storing the preferred size, or %NULL
- *
- * Retreives a widget's minimum and natural size and caches the values.
- *
- * <note><para>This api will consider any restrictions imposed by
- * #GtkSizeGroup<!-- -->s or previous calls to gtk_widget_set_size_request().
- * </para></note>
- *
- * Since: 3.0
- */
-void
-gtk_extended_layout_get_desired_size (GtkExtendedLayout *layout,
- GtkRequisition *minimum_size,
- GtkRequisition *natural_size)
+
+
+
+/* looks for a cached size request for this for_size. If not
+ * found, returns the oldest entry so it can be overwritten */
+static gboolean
+_gtk_extended_layout_get_cached_desired_size (gfloat for_size,
+ GtkDesiredSize *cached_sizes,
+ GtkDesiredSize **result)
{
- g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
- g_return_if_fail (NULL != minimum_size || NULL != natural_size);
+ guint i;
- _gtk_size_group_compute_desired_size (GTK_WIDGET (layout), minimum_size, natural_size);
-}
+ *result = &cached_sizes[0];
+ for (i = 0; i < GTK_N_CACHED_SIZES; i++)
+ {
+ GtkDesiredSize *cs;
+ cs = &cached_sizes[i];
+
+ if (cs->age > 0 &&
+ cs->for_size == for_size)
+ {
+ *result = cs;
+ return TRUE;
+ }
+ else if (cs->age < (*result)->age)
+ {
+ *result = cs;
+ }
+ }
+
+ return FALSE;
+}
/**
* gtk_extended_layout_is_height_for_width:
@@ -99,6 +112,147 @@ gtk_extended_layout_is_height_for_width (GtkExtendedLayout *layout)
return TRUE;
}
+/**
+ * gtk_extended_layout_get_desired_width:
+ * @layout: a #GtkExtendedLayout instance
+ * @minimum_width: location to store the minimum size, or %NULL
+ * @natural_width: location to store the natural size, or %NULL
+ *
+ * Retreives a widget's minimum and natural size in a single dimension.
+ *
+ * Since: 3.0
+ */
+void
+gtk_extended_layout_get_desired_width (GtkExtendedLayout *layout,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ GtkWidgetAuxInfo *aux_info;
+ gboolean found_in_cache = FALSE;
+ GtkDesiredSize *cached_size;
+
+ g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+ g_return_if_fail (minimum_width != NULL || natural_width != NULL);
+
+ aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
+
+ cached_size = &aux_info->desired_widths[0];
+
+ if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
+ found_in_cache = _gtk_extended_layout_get_cached_desired_size (-1, aux_info->desired_widths,
+ &cached_size);
+
+ if (!found_in_cache)
+ {
+ GtkRequisition requisition;
+ gint minimum_width = 0, natural_width = 0;
+
+ /* Unconditionally envoke size-request and use those return values as
+ * the base end of our values */
+ _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
+
+ /* Envoke this after, default GtkWidgetClass will simply copy over widget->requisition
+ */
+ GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_width (layout,
+ &minimum_width,
+ &natural_width);
+
+
+ cached_size->minimum_size = MAX (minimum_width, requisition.width);
+ cached_size->natural_size = MAX (natural_width, requisition.width);
+ cached_size->for_size = -1;
+ cached_size->age = aux_info->cached_width_age;
+
+ aux_info->cached_width_age ++;
+
+ GTK_PRIVATE_UNSET_FLAG (layout, GTK_WIDTH_REQUEST_NEEDED);
+ }
+
+ if (minimum_width)
+ *minimum_width = cached_size->minimum_size;
+
+ if (natural_width)
+ *natural_width = cached_size->natural_size;
+
+#if DEBUG_EXTENDED_LAYOUT
+ g_message ("%s returning minimum width: %d and natural width: %d",
+ G_OBJECT_TYPE_NAME (layout),
+ cached_size->minimum_size,
+ cached_size->natural_size);
+#endif
+}
+
+
+/**
+ * gtk_extended_layout_get_desired_height:
+ * @layout: a #GtkExtendedLayout instance
+ * @minimum_width: location to store the minimum size, or %NULL
+ * @natural_width: location to store the natural size, or %NULL
+ *
+ * Retreives a widget's minimum and natural size in a single dimension.
+ *
+ * Since: 3.0
+ */
+void
+gtk_extended_layout_get_desired_height (GtkExtendedLayout *layout,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ GtkWidgetAuxInfo *aux_info;
+ gboolean found_in_cache = FALSE;
+ GtkDesiredSize *cached_size;
+
+ g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+ g_return_if_fail (minimum_height != NULL || natural_height != NULL);
+
+ aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
+
+ cached_size = &aux_info->desired_heights[0];
+
+ if (GTK_WIDGET_HEIGHT_REQUEST_NEEDED (layout) == FALSE)
+ found_in_cache = _gtk_extended_layout_get_cached_desired_size (-1, aux_info->desired_heights,
+ &cached_size);
+
+ if (!found_in_cache)
+ {
+ GtkRequisition requisition;
+ gint minimum_height = 0, natural_height = 0;
+
+ /* Unconditionally envoke size-request and use those return values as
+ * the base end of our values */
+ _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
+
+ /* Envoke this after, default GtkWidgetClass will simply copy over widget->requisition
+ */
+ GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_height (layout,
+ &minimum_height,
+ &natural_height);
+
+ cached_size->minimum_size = MAX (minimum_height, requisition.height);
+ cached_size->natural_size = MAX (natural_height, requisition.height);
+ cached_size->for_size = -1;
+ cached_size->age = aux_info->cached_height_age;
+
+ aux_info->cached_height_age ++;
+
+ GTK_PRIVATE_UNSET_FLAG (layout, GTK_HEIGHT_REQUEST_NEEDED);
+ }
+
+ if (minimum_height)
+ *minimum_height = cached_size->minimum_size;
+
+ if (natural_height)
+ *natural_height = cached_size->natural_size;
+
+
+#if DEBUG_EXTENDED_LAYOUT
+ g_message ("%s returning minimum height: %d and natural height: %d",
+ G_OBJECT_TYPE_NAME (layout),
+ cached_size->minimum_size,
+ cached_size->natural_size);
+#endif
+}
+
/**
@@ -106,7 +260,7 @@ gtk_extended_layout_is_height_for_width (GtkExtendedLayout *layout)
* @layout: a #GtkExtendedLayout instance
* @height: the size which is available for allocation
* @minimum_size: location for storing the minimum size, or %NULL
- * @natural_size: location for storing the preferred size, or %NULL
+ * @natural_size: location for storing the natural size, or %NULL
*
* Retreives a widget's desired width if it would be given
* the specified @height.
@@ -119,20 +273,61 @@ gtk_extended_layout_get_width_for_height (GtkExtendedLayout *layout,
gint *minimum_width,
gint *natural_width)
{
- GtkExtendedLayoutIface *iface;
+ GtkWidgetAuxInfo *aux_info;
+ gboolean found_in_cache = FALSE;
+ GtkDesiredSize *cached_size;
g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+ g_return_if_fail (minimum_width != NULL || natural_width != NULL);
- /* XXX Maybe here we do _gtk_size_group_compute_width_for_height()
- * and return hard coded minimum widths/heights for for widgets with
- * explicit size requests as well as fetch the common minimum/natural
- * widths/heights for size grouped widgets.
- */
+ aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
- iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
- iface->get_width_for_height (layout, height, minimum_width, natural_width);
+ cached_size = &aux_info->desired_widths[0];
+
+ if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
+ found_in_cache = _gtk_extended_layout_get_cached_desired_size (height, aux_info->desired_widths,
+ &cached_size);
+
+ if (!found_in_cache)
+ {
+ GtkRequisition requisition;
+ gint minimum_width = 0, natural_width = 0;
+
+ /* Unconditionally envoke size-request and use those return values as
+ * the base end of our values */
+ _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
+
+ GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_width_for_height (layout,
+ height,
+ &minimum_width,
+ &natural_width);
+
+ cached_size->minimum_size = MAX (minimum_width, requisition.width);
+ cached_size->natural_size = MAX (natural_width, requisition.width);
+ cached_size->for_size = height;
+ cached_size->age = aux_info->cached_width_age;
+
+ aux_info->cached_width_age++;
+
+ GTK_PRIVATE_UNSET_FLAG (layout, GTK_WIDTH_REQUEST_NEEDED);
+ }
+
+
+ if (minimum_width)
+ *minimum_width = cached_size->minimum_size;
+
+ if (natural_width)
+ *natural_width = cached_size->natural_size;
g_assert (!minimum_width || !natural_width || *minimum_width <= *natural_width);
+
+#if DEBUG_EXTENDED_LAYOUT
+ g_message ("%s width for height: %d is minimum %d and natural: %d",
+ G_OBJECT_TYPE_NAME (layout), height,
+ cached_size->minimum_size,
+ cached_size->natural_size);
+#endif
+
}
/**
@@ -140,7 +335,7 @@ gtk_extended_layout_get_width_for_height (GtkExtendedLayout *layout,
* @layout: a #GtkExtendedLayout instance
* @width: the size which is available for allocation
* @minimum_size: location for storing the minimum size, or %NULL
- * @natural_size: location for storing the preferred size, or %NULL
+ * @natural_size: location for storing the natural size, or %NULL
*
* Retreives a widget's desired height if it would be given
* the specified @width.
@@ -153,15 +348,131 @@ gtk_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
gint *minimum_height,
gint *natural_height)
{
- GtkExtendedLayoutIface *iface;
+ GtkWidgetAuxInfo *aux_info;
+ gboolean found_in_cache = FALSE;
+ GtkDesiredSize *cached_size;
g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+ g_return_if_fail (minimum_height != NULL || natural_height != NULL);
- iface = GTK_EXTENDED_LAYOUT_GET_IFACE (layout);
- iface->get_height_for_width (layout, width, minimum_height, natural_height);
+ aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
+
+ cached_size = &aux_info->desired_heights[0];
+
+ if (GTK_WIDGET_HEIGHT_REQUEST_NEEDED (layout) == FALSE)
+ found_in_cache = _gtk_extended_layout_get_cached_desired_size (width, aux_info->desired_heights,
+ &cached_size);
+
+ if (!found_in_cache)
+ {
+ GtkRequisition requisition;
+ gint minimum_height = 0, natural_height = 0;
+
+ /* Unconditionally envoke size-request and use those return values as
+ * the base end of our values */
+ _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
+
+ GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_height_for_width (layout,
+ width,
+ &minimum_height,
+ &natural_height);
+
+ cached_size->minimum_size = MAX (minimum_height, requisition.height);
+ cached_size->natural_size = MAX (natural_height, requisition.height);
+ cached_size->for_size = width;
+ cached_size->age = aux_info->cached_height_age;
+
+ aux_info->cached_height_age++;
+
+ GTK_PRIVATE_UNSET_FLAG (layout, GTK_HEIGHT_REQUEST_NEEDED);
+ }
+
+
+ if (minimum_height)
+ *minimum_height = cached_size->minimum_size;
+
+ if (natural_height)
+ *natural_height = cached_size->natural_size;
g_assert (!minimum_height || !natural_height || *minimum_height <= *natural_height);
+
+#if DEBUG_EXTENDED_LAYOUT
+ g_message ("%s height for width: %d is minimum %d and natural: %d",
+ G_OBJECT_TYPE_NAME (layout), width,
+ cached_size->minimum_size,
+ cached_size->natural_size);
+#endif
}
+
+
+
+/**
+ * gtk_extended_layout_get_desired_size:
+ * @layout: a #GtkExtendedLayout instance
+ * @width: the size which is available for allocation
+ * @minimum_size: location for storing the minimum size, or %NULL
+ * @natural_size: location for storing the natural size, or %NULL
+ *
+ * Retreives the minimum and natural size of a widget taking
+ * into account the widget's preference for height-for-width management.
+ *
+ * This is used to retreive a suitable size by container widgets whom dont
+ * impose any restrictions on the child placement, examples of these are
+ * #GtkWindow and #GtkScrolledWindow.
+ *
+ * Since: 3.0
+ */
+void
+gtk_extended_layout_get_desired_size (GtkExtendedLayout *layout,
+ GtkRequisition *minimum_size,
+ GtkRequisition *natural_size)
+{
+ gint min_width, nat_width;
+ gint min_height, nat_height;
+
+ g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+
+ if (gtk_extended_layout_is_height_for_width (layout))
+ {
+ gtk_extended_layout_get_desired_width (layout, &min_width, &nat_width);
+ gtk_extended_layout_get_height_for_width (layout, nat_width, &min_height, &nat_height);
+
+ /* The minimum size here is the minimum height for the natrual width */
+ if (minimum_size)
+ {
+ minimum_size->width = nat_width;
+ minimum_size->height = min_height;
+ }
+
+ }
+ else
+ {
+ gtk_extended_layout_get_desired_height (layout, &min_height, &nat_height);
+ gtk_extended_layout_get_height_for_width (layout, nat_height, &min_width, &nat_width);
+
+ /* The minimum size here is the minimum width for the natrual height */
+ if (minimum_size)
+ {
+ minimum_size->width = min_width;
+ minimum_size->height = nat_height;
+ }
+ }
+
+ if (natural_size)
+ {
+ natural_size->width = nat_width;
+ natural_size->height = nat_height;
+ }
+
+
+#if DEBUG_EXTENDED_LAYOUT
+ g_message ("get_desired_size called on a %s; minimum width: %d natural width: %d minimum height %d natural height %d",
+ G_OBJECT_TYPE_NAME (layout), min_width, nat_width, min_height, nat_height);
+#endif
+}
+
+
+
#define __GTK_EXTENDED_LAYOUT_C__
#include "gtkaliasdef.c"