X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtksizegroup.c;h=e31dfa84eb1755b30b53f228eeff280941a16989;hb=HEAD;hp=48b9d7989ad48197abdc4a0278dfd82a6ae387c3;hpb=fcbbd763cd1ab7ea1893569d0408e76eb9db0f43;p=~andy%2Fgtk diff --git a/gtk/gtksizegroup.c b/gtk/gtksizegroup.c index 48b9d7989..e31dfa84e 100644 --- a/gtk/gtksizegroup.c +++ b/gtk/gtksizegroup.c @@ -13,28 +13,109 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" #include + +#include "gtkbuildable.h" #include "gtkcontainer.h" #include "gtkintl.h" +#include "gtktypebuiltins.h" #include "gtkprivate.h" -#include "gtksizegroup.h" -#include "gtkbuildable.h" -#include "gtkextendedlayout.h" -#include "gtkalias.h" +#include "gtksizegroup-private.h" +#include "gtksizerequestcacheprivate.h" +#include "gtkwidgetprivate.h" +#include "gtkcontainerprivate.h" -#define GTK_SIZE_GROUP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_SIZE_GROUP, GtkSizeGroupPrivate)) -typedef struct _GtkSizeGroupPrivate GtkSizeGroupPrivate; +/** + * SECTION:gtksizegroup + * @Short_description: Grouping widgets so they request the same size + * @Title: GtkSizeGroup + * + * #GtkSizeGroup provides a mechanism for grouping a number of widgets + * together so they all request the same amount of space. This is + * typically useful when you want a column of widgets to have the same + * size, but you can't use a #GtkGrid widget. + * + * In detail, the size requested for each widget in a #GtkSizeGroup is + * the maximum of the sizes that would have been requested for each + * widget in the size group if they were not in the size group. The mode + * of the size group (see gtk_size_group_set_mode()) determines whether + * this applies to the horizontal size, the vertical size, or both sizes. + * + * Note that size groups only affect the amount of space requested, not + * the size that the widgets finally receive. If you want the widgets in + * a #GtkSizeGroup to actually be the same size, you need to pack them in + * such a way that they get the size they request and not more. For + * example, if you are packing your widgets into a table, you would not + * include the %GTK_FILL flag. + * + * #GtkSizeGroup objects are referenced by each widget in the size group, + * so once you have added all widgets to a #GtkSizeGroup, you can drop + * the initial reference to the size group with g_object_unref(). If the + * widgets in the size group are subsequently destroyed, then they will + * be removed from the size group and drop their references on the size + * group; when all widgets have been removed, the size group will be + * freed. + * + * Widgets can be part of multiple size groups; GTK+ will compute the + * horizontal size of a widget from the horizontal requisition of all + * widgets that can be reached from the widget by a chain of size groups + * of type %GTK_SIZE_GROUP_HORIZONTAL or %GTK_SIZE_GROUP_BOTH, and the + * vertical size from the vertical requisition of all widgets that can be + * reached from the widget by a chain of size groups of type + * %GTK_SIZE_GROUP_VERTICAL or %GTK_SIZE_GROUP_BOTH. + * + * Note that only non-contextual sizes of every widget are ever consulted + * by size groups (since size groups have no knowledge of what size a widget + * will be allocated in one dimension, it cannot derive how much height + * a widget will receive for a given width). When grouping widgets that + * trade height for width in mode %GTK_SIZE_GROUP_VERTICAL or %GTK_SIZE_GROUP_BOTH: + * the height for the minimum width will be the requested height for all + * widgets in the group. The same is of course true when horizontally grouping + * width for height widgets. + * + * Widgets that trade height-for-width should set a reasonably large minimum width + * by way of #GtkLabel:width-chars for instance. Widgets with static sizes as well + * as widgets that grow (such as ellipsizing text) need no such considerations. + * + * + * GtkSizeGroup as GtkBuildable + * + * Size groups can be specified in a UI definition by placing an + * <object> element with class="GtkSizeGroup" + * somewhere in the UI definition. The widgets that belong to the + * size group are specified by a <widgets> element that may + * contain multiple <widget> elements, one for each member + * of the size group. The name attribute gives the id of the widget. + * + * + * A UI definition fragment with GtkSizeGroup + * + * GTK_SIZE_GROUP_HORIZONTAL + * + * + * + * + * + * ]]> + * + * + * + */ + struct _GtkSizeGroupPrivate { - GtkRequisition natural_size; + GSList *widgets; + + guint8 mode; + + guint ignore_hidden : 1; }; enum { @@ -52,15 +133,6 @@ static void gtk_size_group_get_property (GObject *object, GValue *value, GParamSpec *pspec); -static void add_group_to_closure (GtkSizeGroup *group, - GtkSizeGroupMode mode, - GSList **groups, - GSList **widgets); -static void add_widget_to_closure (GtkWidget *widget, - GtkSizeGroupMode mode, - GSList **groups, - GSList **widgets); - /* GtkBuildable */ static void gtk_size_group_buildable_init (GtkBuildableIface *iface); static gboolean gtk_size_group_buildable_custom_tag_start (GtkBuildable *buildable, @@ -75,226 +147,167 @@ static void gtk_size_group_buildable_custom_finished (GtkBuildable *buildable, const gchar *tagname, gpointer user_data); -static GQuark size_groups_quark; -static const gchar size_groups_tag[] = "gtk-size-groups"; - -static GQuark visited_quark; -static const gchar visited_tag[] = "gtk-size-group-visited"; - -static GSList * -get_size_groups (GtkWidget *widget) -{ - return g_object_get_qdata (G_OBJECT (widget), size_groups_quark); -} +G_STATIC_ASSERT (GTK_SIZE_GROUP_HORIZONTAL == (1 << GTK_ORIENTATION_HORIZONTAL)); +G_STATIC_ASSERT (GTK_SIZE_GROUP_VERTICAL == (1 << GTK_ORIENTATION_VERTICAL)); +G_STATIC_ASSERT (GTK_SIZE_GROUP_BOTH == (GTK_SIZE_GROUP_HORIZONTAL | GTK_SIZE_GROUP_VERTICAL)); static void -set_size_groups (GtkWidget *widget, - GSList *groups) +add_widget_to_closure (GHashTable *widgets, + GHashTable *groups, + GtkWidget *widget, + GtkOrientation orientation) { - g_object_set_qdata (G_OBJECT (widget), size_groups_quark, groups); -} + GSList *tmp_groups, *tmp_widgets; + gboolean hidden; -static void -mark_visited (gpointer object) -{ - g_object_set_qdata (object, visited_quark, "visited"); -} + if (g_hash_table_lookup (widgets, widget)) + return; -static void -mark_unvisited (gpointer object) -{ - g_object_set_qdata (object, visited_quark, NULL); -} + g_hash_table_add (widgets, widget); + hidden = !gtk_widget_is_visible (widget); -static gboolean -is_visited (gpointer object) -{ - return g_object_get_qdata (object, visited_quark) != NULL; -} + for (tmp_groups = _gtk_widget_get_sizegroups (widget); tmp_groups; tmp_groups = tmp_groups->next) + { + GtkSizeGroup *tmp_group = tmp_groups->data; + GtkSizeGroupPrivate *tmp_priv = tmp_group->priv; -static void -add_group_to_closure (GtkSizeGroup *group, - GtkSizeGroupMode mode, - GSList **groups, - GSList **widgets) -{ - GSList *tmp_widgets; - - *groups = g_slist_prepend (*groups, group); - mark_visited (group); + if (g_hash_table_lookup (groups, tmp_group)) + continue; - tmp_widgets = group->widgets; - while (tmp_widgets) - { - GtkWidget *tmp_widget = tmp_widgets->data; - - if (!is_visited (tmp_widget)) - add_widget_to_closure (tmp_widget, mode, groups, widgets); - - tmp_widgets = tmp_widgets->next; + if (tmp_priv->ignore_hidden && hidden) + continue; + + if (!(tmp_priv->mode & (1 << orientation))) + continue; + + g_hash_table_add (groups, tmp_group); + + for (tmp_widgets = tmp_priv->widgets; tmp_widgets; tmp_widgets = tmp_widgets->next) + add_widget_to_closure (widgets, groups, tmp_widgets->data, orientation); } } -static void -add_widget_to_closure (GtkWidget *widget, - GtkSizeGroupMode mode, - GSList **groups, - GSList **widgets) +GHashTable * +_gtk_size_group_get_widget_peers (GtkWidget *for_widget, + GtkOrientation orientation) { - GSList *tmp_groups; + GHashTable *widgets, *groups; - *widgets = g_slist_prepend (*widgets, widget); - mark_visited (widget); + widgets = g_hash_table_new (g_direct_hash, g_direct_equal); + groups = g_hash_table_new (g_direct_hash, g_direct_equal); - tmp_groups = get_size_groups (widget); - while (tmp_groups) - { - GtkSizeGroup *tmp_group = tmp_groups->data; - - if ((tmp_group->mode == GTK_SIZE_GROUP_BOTH || tmp_group->mode == mode) && - !is_visited (tmp_group)) - add_group_to_closure (tmp_group, mode, groups, widgets); + add_widget_to_closure (widgets, groups, for_widget, orientation); - tmp_groups = tmp_groups->next; - } -} + g_hash_table_unref (groups); -static void -real_queue_resize (GtkWidget *widget) -{ - GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED); - GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED); - - if (widget->parent) - _gtk_container_queue_resize (GTK_CONTAINER (widget->parent)); - else if (GTK_WIDGET_TOPLEVEL (widget) && GTK_IS_CONTAINER (widget)) - _gtk_container_queue_resize (GTK_CONTAINER (widget)); + return widgets; } - + static void -reset_group_sizes (GSList *groups) +real_queue_resize (GtkWidget *widget, + GtkQueueResizeFlags flags) { - GSList *tmp_list = groups; - while (tmp_list) - { - GtkSizeGroup *tmp_group = tmp_list->data; + GtkWidget *container; - tmp_group->have_width = FALSE; - tmp_group->have_height = FALSE; - - tmp_list = tmp_list->next; + _gtk_widget_set_alloc_needed (widget, TRUE); + _gtk_size_request_cache_clear (_gtk_widget_peek_request_cache (widget)); + + container = gtk_widget_get_parent (widget); + if (!container && + gtk_widget_is_toplevel (widget) && GTK_IS_CONTAINER (widget)) + container = widget; + + if (container) + { + if (flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY) + _gtk_container_resize_invalidate (GTK_CONTAINER (container)); + else + _gtk_container_queue_resize (GTK_CONTAINER (container)); } } static void -queue_resize_on_widget (GtkWidget *widget, - gboolean check_siblings) +queue_resize_on_widget (GtkWidget *widget, + gboolean check_siblings, + GtkQueueResizeFlags flags) { GtkWidget *parent = widget; - GSList *tmp_list; while (parent) { GSList *widget_groups; - GSList *groups; - GSList *widgets; + GHashTable *widgets; + GHashTableIter iter; + gpointer current; if (widget == parent && !check_siblings) { - real_queue_resize (widget); - parent = parent->parent; + real_queue_resize (widget, flags); + parent = gtk_widget_get_parent (parent); continue; } - widget_groups = get_size_groups (parent); + widget_groups = _gtk_widget_get_sizegroups (parent); if (!widget_groups) { if (widget == parent) - real_queue_resize (widget); + real_queue_resize (widget, flags); - parent = parent->parent; + parent = gtk_widget_get_parent (parent); continue; } - groups = NULL; - widgets = NULL; - - add_widget_to_closure (parent, GTK_SIZE_GROUP_HORIZONTAL, &groups, &widgets); - g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL); - g_slist_foreach (groups, (GFunc)mark_unvisited, NULL); - - reset_group_sizes (groups); - - tmp_list = widgets; - while (tmp_list) + widgets = _gtk_size_group_get_widget_peers (parent, GTK_ORIENTATION_HORIZONTAL); + + g_hash_table_iter_init (&iter, widgets); + while (g_hash_table_iter_next (&iter, ¤t, NULL)) { - if (tmp_list->data == parent) + if (current == parent) { if (widget == parent) - real_queue_resize (parent); + real_queue_resize (parent, flags); } - else if (tmp_list->data == widget) + else if (current == widget) { g_warning ("A container and its child are part of this SizeGroup"); } else - queue_resize_on_widget (tmp_list->data, FALSE); - - tmp_list = tmp_list->next; + queue_resize_on_widget (current, FALSE, flags); } - g_slist_free (widgets); - g_slist_free (groups); - - groups = NULL; - widgets = NULL; - - add_widget_to_closure (parent, GTK_SIZE_GROUP_VERTICAL, &groups, &widgets); - g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL); - g_slist_foreach (groups, (GFunc)mark_unvisited, NULL); - - reset_group_sizes (groups); - - tmp_list = widgets; - while (tmp_list) + g_hash_table_destroy (widgets); + + widgets = _gtk_size_group_get_widget_peers (parent, GTK_ORIENTATION_VERTICAL); + + g_hash_table_iter_init (&iter, widgets); + while (g_hash_table_iter_next (&iter, ¤t, NULL)) { - if (tmp_list->data == parent) + if (current == parent) { if (widget == parent) - real_queue_resize (parent); + real_queue_resize (parent, flags); } - else if (tmp_list->data == widget) + else if (current == widget) { g_warning ("A container and its child are part of this SizeGroup"); } else - queue_resize_on_widget (tmp_list->data, FALSE); - - tmp_list = tmp_list->next; + queue_resize_on_widget (current, FALSE, flags); } - g_slist_free (widgets); - g_slist_free (groups); - - parent = parent->parent; + g_hash_table_destroy (widgets); + + parent = gtk_widget_get_parent (parent); } } static void -queue_resize_on_group (GtkSizeGroup *size_group) +queue_resize_on_group (GtkSizeGroup *size_group) { - if (size_group->widgets) - queue_resize_on_widget (size_group->widgets->data, TRUE); -} + GtkSizeGroupPrivate *priv = size_group->priv; -static void -initialize_size_group_quarks (void) -{ - if (!size_groups_quark) - { - size_groups_quark = g_quark_from_static_string (size_groups_tag); - visited_quark = g_quark_from_static_string (visited_tag); - } + if (priv->widgets) + queue_resize_on_widget (priv->widgets->data, TRUE, 0); } static void @@ -330,19 +343,23 @@ gtk_size_group_class_init (GtkSizeGroupClass *klass) "when determining the size of the group"), FALSE, GTK_PARAM_READWRITE)); - - initialize_size_group_quarks (); + g_type_class_add_private (klass, sizeof (GtkSizeGroupPrivate)); } static void gtk_size_group_init (GtkSizeGroup *size_group) { - size_group->widgets = NULL; - size_group->mode = GTK_SIZE_GROUP_HORIZONTAL; - size_group->have_width = 0; - size_group->have_height = 0; - size_group->ignore_hidden = 0; + GtkSizeGroupPrivate *priv; + + size_group->priv = G_TYPE_INSTANCE_GET_PRIVATE (size_group, + GTK_TYPE_SIZE_GROUP, + GtkSizeGroupPrivate); + priv = size_group->priv; + + priv->widgets = NULL; + priv->mode = GTK_SIZE_GROUP_HORIZONTAL; + priv->ignore_hidden = FALSE; } static void @@ -385,14 +402,15 @@ gtk_size_group_get_property (GObject *object, GParamSpec *pspec) { GtkSizeGroup *size_group = GTK_SIZE_GROUP (object); + GtkSizeGroupPrivate *priv = size_group->priv; switch (prop_id) { case PROP_MODE: - g_value_set_enum (value, size_group->mode); + g_value_set_enum (value, priv->mode); break; case PROP_IGNORE_HIDDEN: - g_value_set_boolean (value, size_group->ignore_hidden); + g_value_set_boolean (value, priv->ignore_hidden); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -412,8 +430,9 @@ GtkSizeGroup * gtk_size_group_new (GtkSizeGroupMode mode) { GtkSizeGroup *size_group = g_object_new (GTK_TYPE_SIZE_GROUP, NULL); + GtkSizeGroupPrivate *priv = size_group->priv; - size_group->mode = mode; + priv->mode = mode; return size_group; } @@ -425,23 +444,27 @@ gtk_size_group_new (GtkSizeGroupMode mode) * * Sets the #GtkSizeGroupMode of the size group. The mode of the size * group determines whether the widgets in the size group should - * all have the same horizontal requisition (%GTK_SIZE_GROUP_MODE_HORIZONTAL) - * all have the same vertical requisition (%GTK_SIZE_GROUP_MODE_VERTICAL), + * all have the same horizontal requisition (%GTK_SIZE_GROUP_HORIZONTAL) + * all have the same vertical requisition (%GTK_SIZE_GROUP_VERTICAL), * or should all have the same requisition in both directions - * (%GTK_SIZE_GROUP_MODE_BOTH). + * (%GTK_SIZE_GROUP_BOTH). **/ void gtk_size_group_set_mode (GtkSizeGroup *size_group, GtkSizeGroupMode mode) { + GtkSizeGroupPrivate *priv; + g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); - if (size_group->mode != mode) + priv = size_group->priv; + + if (priv->mode != mode) { - if (size_group->mode != GTK_SIZE_GROUP_NONE) + if (priv->mode != GTK_SIZE_GROUP_NONE) queue_resize_on_group (size_group); - size_group->mode = mode; - if (size_group->mode != GTK_SIZE_GROUP_NONE) + priv->mode = mode; + if (priv->mode != GTK_SIZE_GROUP_NONE) queue_resize_on_group (size_group); g_object_notify (G_OBJECT (size_group), "mode"); @@ -461,7 +484,7 @@ gtk_size_group_get_mode (GtkSizeGroup *size_group) { g_return_val_if_fail (GTK_IS_SIZE_GROUP (size_group), GTK_SIZE_GROUP_BOTH); - return size_group->mode; + return size_group->priv->mode; } /** @@ -479,13 +502,17 @@ void gtk_size_group_set_ignore_hidden (GtkSizeGroup *size_group, gboolean ignore_hidden) { + GtkSizeGroupPrivate *priv; + g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); - + + priv = size_group->priv; + ignore_hidden = ignore_hidden != FALSE; - if (size_group->ignore_hidden != ignore_hidden) + if (priv->ignore_hidden != ignore_hidden) { - size_group->ignore_hidden = ignore_hidden; + priv->ignore_hidden = ignore_hidden; g_object_notify (G_OBJECT (size_group), "ignore-hidden"); } @@ -506,7 +533,7 @@ gtk_size_group_get_ignore_hidden (GtkSizeGroup *size_group) { g_return_val_if_fail (GTK_IS_SIZE_GROUP (size_group), FALSE); - return size_group->ignore_hidden; + return size_group->priv->ignore_hidden; } static void @@ -534,19 +561,21 @@ void gtk_size_group_add_widget (GtkSizeGroup *size_group, GtkWidget *widget) { + GtkSizeGroupPrivate *priv; GSList *groups; g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); g_return_if_fail (GTK_IS_WIDGET (widget)); - - groups = get_size_groups (widget); + + priv = size_group->priv; + + groups = _gtk_widget_get_sizegroups (widget); if (!g_slist_find (groups, size_group)) { - groups = g_slist_prepend (groups, size_group); - set_size_groups (widget, groups); + _gtk_widget_add_sizegroup (widget, size_group); - size_group->widgets = g_slist_prepend (size_group->widgets, widget); + priv->widgets = g_slist_prepend (priv->widgets, widget); g_signal_connect (widget, "destroy", G_CALLBACK (gtk_size_group_widget_destroyed), @@ -560,7 +589,7 @@ gtk_size_group_add_widget (GtkSizeGroup *size_group, /** * gtk_size_group_remove_widget: - * @size_group: a #GtkSizeGrup + * @size_group: a #GtkSizeGroup * @widget: the #GtkWidget to remove * * Removes a widget from a #GtkSizeGroup. @@ -569,21 +598,22 @@ void gtk_size_group_remove_widget (GtkSizeGroup *size_group, GtkWidget *widget) { - GSList *groups; + GtkSizeGroupPrivate *priv; g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (g_slist_find (size_group->widgets, widget)); + + priv = size_group->priv; + + g_return_if_fail (g_slist_find (priv->widgets, widget)); g_signal_handlers_disconnect_by_func (widget, gtk_size_group_widget_destroyed, size_group); - groups = get_size_groups (widget); - groups = g_slist_remove (groups, size_group); - set_size_groups (widget, groups); + _gtk_widget_remove_sizegroup (widget, size_group); - size_group->widgets = g_slist_remove (size_group->widgets, widget); + priv->widgets = g_slist_remove (priv->widgets, widget); queue_resize_on_group (size_group); gtk_widget_queue_resize (widget); @@ -592,7 +622,7 @@ gtk_size_group_remove_widget (GtkSizeGroup *size_group, /** * gtk_size_group_get_widgets: - * @size_group: a #GtkSizeGrup + * @size_group: a #GtkSizeGroup * * Returns the list of widgets associated with @size_group. * @@ -604,320 +634,7 @@ gtk_size_group_remove_widget (GtkSizeGroup *size_group, GSList * gtk_size_group_get_widgets (GtkSizeGroup *size_group) { - return size_group->widgets; -} - -static void -get_base_dimensions (GtkWidget *widget, - GtkSizeGroupMode mode, - gint *minimum_size, - gint *natural_size) -{ - GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE); - - if (mode == GTK_SIZE_GROUP_HORIZONTAL) - { - if (minimum_size) - { - if (aux_info && aux_info->width > 0) - *minimum_size = aux_info->width; - else - *minimum_size = widget->requisition.width; - } - - if (natural_size) - { - if (aux_info) - *natural_size = aux_info->natural_size.width; - else - *natural_size = widget->requisition.width; - } - } - else - { - if (minimum_size) - { - if (aux_info && aux_info->height > 0) - *minimum_size = aux_info->height; - else - *minimum_size = widget->requisition.height; - } - - if (natural_size) - { - if (aux_info) - *natural_size = aux_info->natural_size.height; - else - *natural_size = widget->requisition.height; - } - } -} - -static void -do_size_request (GtkWidget *widget) -{ - if (GTK_WIDGET_REQUEST_NEEDED (widget)) - { - GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, TRUE); - - gtk_widget_ensure_style (widget); - GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED); - - gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (widget), - &widget->requisition, - &aux_info->natural_size); - - g_assert (widget->requisition.width <= aux_info->natural_size.width); - g_assert (widget->requisition.height <= aux_info->natural_size.height); - } -} - -static void -compute_base_dimensions (GtkWidget *widget, - GtkSizeGroupMode mode, - gint *minimum_size, - gint *natural_size) -{ - do_size_request (widget); - get_base_dimensions (widget, mode, minimum_size, natural_size); -} - -static gint -compute_dimension (GtkWidget *widget, - GtkSizeGroupMode mode, - gint *minimum_size, - gint *natural_size) -{ - GSList *widgets = NULL; - GSList *groups = NULL; - GSList *tmp_list; - gint result = 0; - - add_widget_to_closure (widget, mode, &groups, &widgets); - - g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL); - g_slist_foreach (groups, (GFunc)mark_unvisited, NULL); - - g_slist_foreach (widgets, (GFunc)g_object_ref, NULL); - - if (!groups) - { - compute_base_dimensions (widget, mode, minimum_size, natural_size); - } - else - { - GtkSizeGroup *group = groups->data; - GtkSizeGroupPrivate *priv = GTK_SIZE_GROUP_GET_PRIVATE (group); - - gint result_minimum_size = 0; - gint result_natural_size = 0; - - if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width) - { - result_minimum_size = group->requisition.width; - result_natural_size = priv->natural_size.width; - } - else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height) - { - result_minimum_size = group->requisition.height; - result_natural_size = priv->natural_size.height; - } - else - { - tmp_list = widgets; - while (tmp_list) - { - GtkWidget *tmp_widget = tmp_list->data; - - gint tmp_widget_minimum_size; - gint tmp_widget_natural_size; - - compute_base_dimensions (tmp_widget, mode, - &tmp_widget_minimum_size, - &tmp_widget_natural_size); - - if (GTK_WIDGET_MAPPED (tmp_widget) || !group->ignore_hidden) - { - if (result_minimum_size < tmp_widget_minimum_size) - result_minimum_size = tmp_widget_minimum_size; - if (result_natural_size < tmp_widget_natural_size) - result_natural_size = tmp_widget_natural_size; - } - - tmp_list = tmp_list->next; - } - - tmp_list = groups; - while (tmp_list) - { - GtkSizeGroup *tmp_group = tmp_list->data; - GtkSizeGroupPrivate *tmp_priv = GTK_SIZE_GROUP_GET_PRIVATE (tmp_group); - - if (mode == GTK_SIZE_GROUP_HORIZONTAL) - { - tmp_group->have_width = TRUE; - tmp_group->requisition.width = result_minimum_size; - tmp_priv->natural_size.width = result_natural_size; - } - else - { - tmp_group->have_height = TRUE; - tmp_group->requisition.height = result_minimum_size; - tmp_priv->natural_size.height = result_natural_size; - } - - tmp_list = tmp_list->next; - } - } - - if (minimum_size) - *minimum_size = result_minimum_size; - if (natural_size) - *natural_size = result_natural_size; - } - - g_slist_foreach (widgets, (GFunc)g_object_unref, NULL); - - g_slist_free (widgets); - g_slist_free (groups); -} - -static void -get_dimensions (GtkWidget *widget, - GtkSizeGroupMode mode, - gint *minimum_size, - gint *natural_size) -{ - GSList *widgets = NULL; - GSList *groups = NULL; - - add_widget_to_closure (widget, mode, &groups, &widgets); - - g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL); - g_slist_foreach (groups, (GFunc)mark_unvisited, NULL); - - if (!groups) - { - get_base_dimensions (widget, mode, minimum_size, natural_size); - } - else - { - GtkSizeGroup *group = groups->data; - GtkSizeGroupPrivate *priv = GTK_SIZE_GROUP_GET_PRIVATE (group); - - if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width) - { - if (minimum_size) - *minimum_size = group->requisition.width; - if (natural_size) - *natural_size = priv->natural_size.width; - } - else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height) - { - if (minimum_size) - *minimum_size = group->requisition.height; - if (natural_size) - *natural_size = priv->natural_size.height; - } - } - - g_slist_free (widgets); - g_slist_free (groups); -} - -static void -get_fast_child_requisition (GtkWidget *widget, - GtkRequisition *requisition) -{ - GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE); - - *requisition = widget->requisition; - - if (aux_info) - { - if (aux_info->width > 0) - requisition->width = aux_info->width; - if (aux_info->height > 0) - requisition->height = aux_info->height; - } -} - -static void -get_fast_natural_size (GtkWidget *widget, - GtkRequisition *requisition) -{ - GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE); - - if (aux_info) - *requisition = aux_info->natural_size; - else - *requisition = widget->requisition; -} - -/** - * _gtk_size_group_get_child_requisition: - * @widget: a #GtkWidget - * @requisition: location to store computed requisition. - * - * Retrieve the "child requisition" of the widget, taking account grouping - * of the widget's requisition with other widgets. - **/ -void -_gtk_size_group_get_child_requisition (GtkWidget *widget, - GtkRequisition *requisition) -{ - initialize_size_group_quarks (); - - if (requisition) - { - if (get_size_groups (widget)) - { - get_dimensions (widget, GTK_SIZE_GROUP_HORIZONTAL, &requisition->width, NULL); - get_dimensions (widget, GTK_SIZE_GROUP_VERTICAL, &requisition->height, NULL); - - /* Only do the full computation if we actually have size groups */ - } - else - get_fast_child_requisition (widget, requisition); - } -} - -/** - * _gtk_size_group_compute_desired_size: - * @widget: a #GtkWidget - * @minimum_size: location to store computed minimum size - * @natural_size: location to store computed natural size - * - * Compute the desired size of a widget taking into account grouping of - * the widget's requisition with other widgets. - **/ -void -_gtk_size_group_compute_desired_size (GtkWidget *widget, - GtkRequisition *minimum_size, - GtkRequisition *natural_size) -{ - initialize_size_group_quarks (); - - if (get_size_groups (widget)) - { - /* Only do the full computation if we actually have size groups */ - - compute_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL, - minimum_size ? &minimum_size->width : NULL, - natural_size ? &natural_size->width : NULL); - compute_dimension (widget, GTK_SIZE_GROUP_VERTICAL, - minimum_size ? &minimum_size->height : NULL, - natural_size ? &natural_size->height : NULL); - } - else - { - do_size_request (widget); - - if (minimum_size) - get_fast_child_requisition (widget, minimum_size); - if (natural_size) - get_fast_natural_size (widget, natural_size); - } + return size_group->priv->widgets; } /** @@ -927,11 +644,10 @@ _gtk_size_group_compute_desired_size (GtkWidget *widget, * Queue a resize on a widget, and on all other widgets grouped with this widget. **/ void -_gtk_size_group_queue_resize (GtkWidget *widget) +_gtk_size_group_queue_resize (GtkWidget *widget, + GtkQueueResizeFlags flags) { - initialize_size_group_quarks (); - - queue_resize_on_widget (widget, TRUE); + queue_resize_on_widget (widget, TRUE, flags); } typedef struct { @@ -1028,7 +744,3 @@ gtk_size_group_buildable_custom_finished (GtkBuildable *buildable, g_slist_free (data->items); g_slice_free (GSListSubParserData, data); } - - -#define __GTK_SIZE_GROUP_C__ -#include "gtkaliasdef.c"