diff options
author | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2011-03-05 17:49:49 +0900 |
---|---|---|
committer | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2011-03-25 18:42:07 +0900 |
commit | 887142f1f5d364765bc84a46ddb187be08261710 (patch) | |
tree | 25591d2b4c6df43b2d1b443c5a94340f1bd69567 | |
parent | 59440927d001e4d6400548a9e7f02dd43be6a4d0 (diff) | |
download | gtk+-887142f1f5d364765bc84a46ddb187be08261710.tar.gz |
Added GTK_SIZE_REQUEST_CONSTANT_SIZE to GtkSizeRequestMode
The constant size request mode defines a request mode where
height-for-width geometry is unneeded, thus optimizing GTK+
by reducing the overall amount of requests that need to be
performed and cached while resizing an interface.
-rw-r--r-- | gtk/gtkbin.c | 14 | ||||
-rw-r--r-- | gtk/gtkbox.c | 12 | ||||
-rw-r--r-- | gtk/gtkcellview.c | 11 | ||||
-rw-r--r-- | gtk/gtkcontainer.c | 54 | ||||
-rw-r--r-- | gtk/gtkenums.h | 4 | ||||
-rw-r--r-- | gtk/gtkgrid.c | 21 | ||||
-rw-r--r-- | gtk/gtklabel.c | 8 | ||||
-rw-r--r-- | gtk/gtksizerequest.c | 40 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 4 | ||||
-rw-r--r-- | gtk/gtkwidget.h | 15 |
10 files changed, 120 insertions, 63 deletions
diff --git a/gtk/gtkbin.c b/gtk/gtkbin.c index af3efea253..331ae53766 100644 --- a/gtk/gtkbin.c +++ b/gtk/gtkbin.c @@ -59,7 +59,6 @@ static void gtk_bin_forall (GtkContainer *container, static GType gtk_bin_child_type (GtkContainer *container); -static GtkSizeRequestMode gtk_bin_get_request_mode (GtkWidget *widget); static void gtk_bin_get_preferred_width_for_height (GtkWidget *widget, gint height, gint *minimum_width, @@ -77,7 +76,6 @@ gtk_bin_class_init (GtkBinClass *class) GtkWidgetClass *widget_class = (GtkWidgetClass*) class; GtkContainerClass *container_class = (GtkContainerClass*) class; - widget_class->get_request_mode = gtk_bin_get_request_mode; widget_class->get_preferred_width_for_height = gtk_bin_get_preferred_width_for_height; widget_class->get_preferred_height_for_width = gtk_bin_get_preferred_height_for_width; @@ -184,18 +182,6 @@ gtk_bin_forall (GtkContainer *container, * deduce a common code path for the get_width_for_height()/get_height_for_width() * cases by using the delta of the base size requsts. */ -static GtkSizeRequestMode -gtk_bin_get_request_mode (GtkWidget *widget) -{ - GtkBin *bin = GTK_BIN (widget); - GtkBinPrivate *priv = bin->priv; - - if (priv->child) - return gtk_widget_get_request_mode (priv->child); - - return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; -} - static void get_child_padding_delta (GtkBin *bin, gint *delta_h, diff --git a/gtk/gtkbox.c b/gtk/gtkbox.c index f508173430..bc9693d437 100644 --- a/gtk/gtkbox.c +++ b/gtk/gtkbox.c @@ -185,7 +185,6 @@ static void gtk_box_get_child_property (GtkContainer *container, static GType gtk_box_child_type (GtkContainer *container); -static GtkSizeRequestMode gtk_box_get_request_mode (GtkWidget *widget); static void gtk_box_get_preferred_width (GtkWidget *widget, gint *minimum_size, gint *natural_size); @@ -216,7 +215,6 @@ gtk_box_class_init (GtkBoxClass *class) object_class->get_property = gtk_box_get_property; widget_class->size_allocate = gtk_box_size_allocate; - widget_class->get_request_mode = gtk_box_get_request_mode; widget_class->get_preferred_width = gtk_box_get_preferred_width; widget_class->get_preferred_height = gtk_box_get_preferred_height; widget_class->get_preferred_height_for_width = gtk_box_get_preferred_height_for_width; @@ -870,16 +868,6 @@ gtk_box_pack (GtkBox *box, gtk_widget_thaw_child_notify (child); } - -static GtkSizeRequestMode -gtk_box_get_request_mode (GtkWidget *widget) -{ - GtkBoxPrivate *private = GTK_BOX (widget)->priv; - - return (private->orientation == GTK_ORIENTATION_VERTICAL) ? - GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH : GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT; -} - static void gtk_box_get_size (GtkWidget *widget, GtkOrientation orientation, diff --git a/gtk/gtkcellview.c b/gtk/gtkcellview.c index d6a87af0e5..051bae5050 100644 --- a/gtk/gtkcellview.c +++ b/gtk/gtkcellview.c @@ -93,6 +93,7 @@ static void gtk_cell_view_buildable_custom_tag_end (GtkBuildable const gchar *tagname, gpointer *data); +static GtkSizeRequestMode gtk_cell_view_get_request_mode (GtkWidget *widget); static void gtk_cell_view_get_preferred_width (GtkWidget *widget, gint *minimum_size, gint *natural_size); @@ -175,6 +176,7 @@ gtk_cell_view_class_init (GtkCellViewClass *klass) widget_class->draw = gtk_cell_view_draw; widget_class->size_allocate = gtk_cell_view_size_allocate; + widget_class->get_request_mode = gtk_cell_view_get_request_mode; widget_class->get_preferred_width = gtk_cell_view_get_preferred_width; widget_class->get_preferred_height = gtk_cell_view_get_preferred_height; widget_class->get_preferred_width_for_height = gtk_cell_view_get_preferred_width_for_height; @@ -637,6 +639,15 @@ gtk_cell_view_request_model (GtkCellView *cellview, } } +static GtkSizeRequestMode +gtk_cell_view_get_request_mode (GtkWidget *widget) +{ + GtkCellView *cellview = GTK_CELL_VIEW (widget); + GtkCellViewPrivate *priv = cellview->priv; + + return gtk_cell_area_get_request_mode (priv->area); +} + static void gtk_cell_view_get_preferred_width (GtkWidget *widget, gint *minimum_size, diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index f6fff0697b..2a1438a2ee 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -239,6 +239,7 @@ struct _GtkContainerPrivate guint need_resize : 1; guint reallocate_redraws : 1; guint resize_mode : 2; + guint request_mode : 2; }; enum { @@ -307,6 +308,7 @@ static void gtk_container_adjust_size_allocation (GtkWidget *widget, gint *natural_size, gint *allocated_pos, gint *allocated_size); +static GtkSizeRequestMode gtk_container_get_request_mode (GtkWidget *widget); static gchar* gtk_container_child_default_composite_name (GtkContainer *container, GtkWidget *child); @@ -437,6 +439,7 @@ gtk_container_class_init (GtkContainerClass *class) widget_class->adjust_size_request = gtk_container_adjust_size_request; widget_class->adjust_size_allocation = gtk_container_adjust_size_allocation; + widget_class->get_request_mode = gtk_container_get_request_mode; class->add = gtk_container_add_unimplemented; class->remove = gtk_container_remove_unimplemented; @@ -1851,6 +1854,57 @@ gtk_container_adjust_size_allocation (GtkWidget *widget, allocated_size); } +typedef struct { + gint hfw; + gint wfh; +} RequestModeCount; + +static void +count_request_modes (GtkWidget *widget, + RequestModeCount *count) +{ + GtkSizeRequestMode mode = gtk_widget_get_request_mode (widget); + + switch (mode) + { + case GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH: + count->hfw++; + break; + case GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT: + count->wfh++; + break; + case GTK_SIZE_REQUEST_CONSTANT_SIZE: + default: + break; + } +} + +static GtkSizeRequestMode +gtk_container_get_request_mode (GtkWidget *widget) +{ + GtkContainer *container = GTK_CONTAINER (widget); + GtkContainerPrivate *priv = container->priv; + + /* Recalculate the request mode of the children by majority + * vote whenever the internal content changes */ + if (_gtk_widget_get_width_request_needed (widget) || + _gtk_widget_get_height_request_needed (widget)) + { + RequestModeCount count = { 0, 0 }; + + gtk_container_forall (container, (GtkCallback)count_request_modes, &count); + + if (!count.hfw && !count.wfh) + priv->request_mode = GTK_SIZE_REQUEST_CONSTANT_SIZE; + else + priv->request_mode = count.wfh > count.hfw ? + GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT : + GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; + } + + return priv->request_mode; +} + /** * gtk_container_class_handle_border_width: * @klass: the class struct of a #GtkContainer subclass diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index 78ea40c98d..2233b00b7f 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -790,6 +790,7 @@ typedef enum * GtkSizeRequestMode: * @GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH: Prefer height-for-width geometry management * @GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT: Prefer width-for-height geometry management + * @GTK_SIZE_REQUEST_CONSTANT_SIZE: Dont trade height-for-width or width-for-height * * Specifies a preference for height-for-width or * width-for-height geometry management. @@ -797,7 +798,8 @@ typedef enum typedef enum { GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH = 0, - GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT + GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT, + GTK_SIZE_REQUEST_CONSTANT_SIZE } GtkSizeRequestMode; /** diff --git a/gtk/gtkgrid.c b/gtk/gtkgrid.c index bd305f6d46..4719857944 100644 --- a/gtk/gtkgrid.c +++ b/gtk/gtkgrid.c @@ -458,17 +458,6 @@ gtk_grid_child_type (GtkContainer *container) return GTK_TYPE_WIDGET; } -static GtkSizeRequestMode -gtk_grid_get_request_mode (GtkWidget *widget) -{ - GtkGridPrivate *priv = GTK_GRID (widget)->priv; - - if (priv->orientation == GTK_ORIENTATION_VERTICAL) - return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; - else - return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT; -} - /* Calculates the min and max numbers for both orientations. */ static void @@ -1104,8 +1093,7 @@ gtk_grid_get_preferred_width (GtkWidget *widget, { GtkGrid *grid = GTK_GRID (widget); - if (gtk_grid_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT) - + if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT) gtk_grid_get_size_for_size (grid, GTK_ORIENTATION_HORIZONTAL, 0, minimum, natural); else gtk_grid_get_size (grid, GTK_ORIENTATION_HORIZONTAL, minimum, natural); @@ -1118,7 +1106,7 @@ gtk_grid_get_preferred_height (GtkWidget *widget, { GtkGrid *grid = GTK_GRID (widget); - if (gtk_grid_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) + if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) gtk_grid_get_size_for_size (grid, GTK_ORIENTATION_VERTICAL, 0, minimum, natural); else gtk_grid_get_size (grid, GTK_ORIENTATION_VERTICAL, minimum, natural); @@ -1132,7 +1120,7 @@ gtk_grid_get_preferred_width_for_height (GtkWidget *widget, { GtkGrid *grid = GTK_GRID (widget); - if (gtk_grid_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT) + if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT) gtk_grid_get_size_for_size (grid, GTK_ORIENTATION_HORIZONTAL, height, minimum, natural); else gtk_grid_get_size (grid, GTK_ORIENTATION_HORIZONTAL, minimum, natural); @@ -1146,7 +1134,7 @@ gtk_grid_get_preferred_height_for_width (GtkWidget *widget, { GtkGrid *grid = GTK_GRID (widget); - if (gtk_grid_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) + if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) gtk_grid_get_size_for_size (grid, GTK_ORIENTATION_VERTICAL, width, minimum, natural); else gtk_grid_get_size (grid, GTK_ORIENTATION_VERTICAL, minimum, natural); @@ -1258,7 +1246,6 @@ gtk_grid_class_init (GtkGridClass *class) widget_class->size_allocate = gtk_grid_size_allocate; widget_class->get_preferred_width = gtk_grid_get_preferred_width; widget_class->get_preferred_height = gtk_grid_get_preferred_height; - widget_class->get_request_mode = gtk_grid_get_request_mode; widget_class->get_preferred_width_for_height = gtk_grid_get_preferred_width_for_height; widget_class->get_preferred_height_for_width = gtk_grid_get_preferred_height_for_width; diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 9f7c7ada06..922e2f5246 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -3381,10 +3381,12 @@ gtk_label_get_request_mode (GtkWidget *widget) GtkLabel *label = GTK_LABEL (widget); gdouble angle = gtk_label_get_angle (label); - if (angle == 90 || angle == 270) - return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT; + if (label->priv->wrap) + return (angle == 90 || angle == 270) ? + GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT : + GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; - return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; + return GTK_SIZE_REQUEST_CONSTANT_SIZE; } static void diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c index ef96ed0402..81edba6a42 100644 --- a/gtk/gtksizerequest.c +++ b/gtk/gtksizerequest.c @@ -156,6 +156,11 @@ pop_recursion_check (GtkWidget *widget, #endif } +/* This is the main function that checks for a cached size and + * possibly queries the widget class to compute the size if it's + * not cached. If the for_size here is -1, then get_preferred_width() + * or get_preferred_height() will be used. + */ static void compute_size_for_orientation (GtkWidget *widget, GtkSizeGroupMode orientation, @@ -168,9 +173,6 @@ compute_size_for_orientation (GtkWidget *widget, gboolean found_in_cache = FALSE; int adjusted_min, adjusted_natural; - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (minimum_size != NULL || natural_size != NULL); - cache = _gtk_widget_peek_request_cache (widget); if (orientation == GTK_SIZE_GROUP_HORIZONTAL) @@ -399,6 +401,9 @@ gtk_widget_get_preferred_width (GtkWidget *widget, gint *minimum_width, gint *natural_width) { + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (minimum_width != NULL || natural_width != NULL); + compute_size_for_orientation (widget, GTK_SIZE_GROUP_HORIZONTAL, -1, minimum_width, natural_width); } @@ -427,6 +432,9 @@ gtk_widget_get_preferred_height (GtkWidget *widget, gint *minimum_height, gint *natural_height) { + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (minimum_height != NULL || natural_height != NULL); + compute_size_for_orientation (widget, GTK_SIZE_GROUP_VERTICAL, -1, minimum_height, natural_height); } @@ -457,8 +465,16 @@ gtk_widget_get_preferred_width_for_height (GtkWidget *widget, gint *minimum_width, gint *natural_width) { - compute_size_for_orientation (widget, GTK_SIZE_GROUP_HORIZONTAL, - height, minimum_width, natural_width); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (minimum_width != NULL || natural_width != NULL); + g_return_if_fail (height >= 0); + + if (GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE) + compute_size_for_orientation (widget, GTK_SIZE_GROUP_HORIZONTAL, + -1, minimum_width, natural_width); + else + compute_size_for_orientation (widget, GTK_SIZE_GROUP_HORIZONTAL, + height, minimum_width, natural_width); } /** @@ -485,8 +501,16 @@ gtk_widget_get_preferred_height_for_width (GtkWidget *widget, gint *minimum_height, gint *natural_height) { - compute_size_for_orientation (widget, GTK_SIZE_GROUP_VERTICAL, - width, minimum_height, natural_height); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (minimum_height != NULL || natural_height != NULL); + g_return_if_fail (width >= 0); + + if (GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE) + compute_size_for_orientation (widget, GTK_SIZE_GROUP_VERTICAL, + -1, minimum_height, natural_height); + else + compute_size_for_orientation (widget, GTK_SIZE_GROUP_VERTICAL, + width, minimum_height, natural_height); } /** @@ -538,7 +562,7 @@ gtk_widget_get_preferred_size (GtkWidget *widget, NULL, &natural_size->height); } } - else /* GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT */ + else /* GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT or CONSTANT_SIZE */ { gtk_widget_get_preferred_height (widget, &min_height, &nat_height); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 427b3b7840..5c28ef190d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -13007,8 +13007,8 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable, static GtkSizeRequestMode gtk_widget_real_get_request_mode (GtkWidget *widget) { - /* By default widgets are height-for-width. */ - return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH; + /* By default widgets dont trade size at all. */ + return GTK_SIZE_REQUEST_CONSTANT_SIZE; } static void diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index 49fde65497..9c1dec9e71 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -139,12 +139,15 @@ struct _GtkWidget * %GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT mode. * %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH means the widget prefers to have * #GtkWidgetClass.get_preferred_width() called and then - * #GtkWidgetClass.get_preferred_height_for_width() and is the default - * return for unimplemented cases. - * However it's important to note (as described below) that any widget - * which trades height-for-width must respond properly to both - * #GtkSizeRequestModes since it might be queried in either orientation - * by its parent container. + * #GtkWidgetClass.get_preferred_height_for_width(). + * %GTK_SIZE_REQUEST_CONSTANT_SIZE disables any height-for-width or + * width-for-height geometry management for a said widget and is the + * default return. + * It's important to note (as described below) that any widget + * which trades height-for-width or width-for-height must respond properly + * to both of the virtual methods #GtkWidgetClass.get_preferred_height_for_width() + * and #GtkWidgetClass.get_preferred_width_for_height() since it might be + * queried in either #GtkSizeRequestMode by its parent container. * @get_preferred_height: This is called by containers to obtain the minimum * and natural height of a widget. A widget that does not actually trade * any height for width or width for height only has to implement these |