]> Pileus Git - ~andy/gtk/blob - gtk/gtksizegroup.c
d66586c8867061dfdf1fd9251e8db6192c28be01
[~andy/gtk] / gtk / gtksizegroup.c
1 /* GTK - The GIMP Toolkit
2  * gtksizegroup.c: 
3  * Copyright (C) 2001 Red Hat Software
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22 #include "gtkcontainer.h"
23 #include "gtkintl.h"
24 #include "gtkprivate.h"
25 #include "gtksizegroup.h"
26 #include "gtkalias.h"
27
28 enum {
29   PROP_0,
30   PROP_MODE,
31   PROP_IGNORE_HIDDEN
32 };
33
34 static void gtk_size_group_set_property (GObject      *object,
35                                          guint         prop_id,
36                                          const GValue *value,
37                                          GParamSpec   *pspec);
38 static void gtk_size_group_get_property (GObject      *object,
39                                          guint         prop_id,
40                                          GValue       *value,
41                                          GParamSpec   *pspec);
42
43 static void add_group_to_closure  (GtkSizeGroup      *group,
44                                    GtkSizeGroupMode   mode,
45                                    GSList           **groups,
46                                    GSList           **widgets);
47 static void add_widget_to_closure (GtkWidget         *widget,
48                                    GtkSizeGroupMode   mode,
49                                    GSList           **groups,
50                                    GSList           **widgets);
51
52 static GQuark size_groups_quark;
53 static const gchar size_groups_tag[] = "gtk-size-groups";
54
55 static GQuark visited_quark;
56 static const gchar visited_tag[] = "gtk-size-group-visited";
57
58 static GSList *
59 get_size_groups (GtkWidget *widget)
60 {
61   return g_object_get_qdata (G_OBJECT (widget), size_groups_quark);
62 }
63
64 static void
65 set_size_groups (GtkWidget *widget,
66                  GSList    *groups)
67 {
68   g_object_set_qdata (G_OBJECT (widget), size_groups_quark, groups);
69 }
70
71 static void
72 mark_visited (gpointer object)
73 {
74   g_object_set_qdata (object, visited_quark, "visited");
75 }
76
77 static void
78 mark_unvisited (gpointer object)
79 {
80   g_object_set_qdata (object, visited_quark, NULL);
81 }
82
83 static gboolean
84 is_visited (gpointer object)
85 {
86   return g_object_get_qdata (object, visited_quark) != NULL;
87 }
88
89 static void
90 add_group_to_closure (GtkSizeGroup    *group,
91                       GtkSizeGroupMode mode,
92                       GSList         **groups,
93                       GSList         **widgets)
94 {
95   GSList *tmp_widgets;
96   
97   *groups = g_slist_prepend (*groups, group);
98   mark_visited (group);
99
100   tmp_widgets = group->widgets;
101   while (tmp_widgets)
102     {
103       GtkWidget *tmp_widget = tmp_widgets->data;
104       
105       if (!is_visited (tmp_widget))
106         add_widget_to_closure (tmp_widget, mode, groups, widgets);
107       
108       tmp_widgets = tmp_widgets->next;
109     }
110 }
111
112 static void
113 add_widget_to_closure (GtkWidget       *widget,
114                        GtkSizeGroupMode mode,
115                        GSList         **groups,
116                        GSList         **widgets)
117 {
118   GSList *tmp_groups;
119
120   *widgets = g_slist_prepend (*widgets, widget);
121   mark_visited (widget);
122
123   tmp_groups = get_size_groups (widget);
124   while (tmp_groups)
125     {
126       GtkSizeGroup *tmp_group = tmp_groups->data;
127       
128       if ((tmp_group->mode == GTK_SIZE_GROUP_BOTH || tmp_group->mode == mode) &&
129           !is_visited (tmp_group))
130         add_group_to_closure (tmp_group, mode, groups, widgets);
131
132       tmp_groups = tmp_groups->next;
133     }
134 }
135
136 static void
137 real_queue_resize (GtkWidget *widget)
138 {
139   GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
140   GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
141   
142   if (widget->parent)
143     _gtk_container_queue_resize (GTK_CONTAINER (widget->parent));
144   else if (GTK_WIDGET_TOPLEVEL (widget) && GTK_IS_CONTAINER (widget))
145     _gtk_container_queue_resize (GTK_CONTAINER (widget));
146 }
147
148 static void
149 reset_group_sizes (GSList *groups)
150 {
151   GSList *tmp_list = groups;
152   while (tmp_list)
153     {
154       GtkSizeGroup *tmp_group = tmp_list->data;
155
156       tmp_group->have_width = FALSE;
157       tmp_group->have_height = FALSE;
158       
159       tmp_list = tmp_list->next;
160     }
161 }
162
163 static void
164 queue_resize_on_widget (GtkWidget *widget,
165                         gboolean   check_siblings)
166 {
167   GtkWidget *parent = widget;
168   GSList *tmp_list;
169
170   while (parent)
171     {
172       GSList *widget_groups;
173       GSList *groups;
174       GSList *widgets;
175       
176       if (widget == parent && !check_siblings)
177         {
178           real_queue_resize (widget);
179           parent = parent->parent;
180           continue;
181         }
182       
183       widget_groups = get_size_groups (parent);
184       if (!widget_groups)
185         {
186           if (widget == parent)
187             real_queue_resize (widget);
188
189           parent = parent->parent;
190           continue;
191         }
192
193       groups = NULL;
194       widgets = NULL;
195           
196       add_widget_to_closure (parent, GTK_SIZE_GROUP_HORIZONTAL, &groups, &widgets);
197       g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
198       g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
199
200       reset_group_sizes (groups);
201               
202       tmp_list = widgets;
203       while (tmp_list)
204         {
205           if (tmp_list->data == parent)
206             {
207               if (widget == parent)
208                 real_queue_resize (parent);
209             }
210           else
211             queue_resize_on_widget (tmp_list->data, FALSE);
212
213           tmp_list = tmp_list->next;
214         }
215       
216       g_slist_free (widgets);
217       g_slist_free (groups);
218               
219       groups = NULL;
220       widgets = NULL;
221               
222       add_widget_to_closure (parent, GTK_SIZE_GROUP_VERTICAL, &groups, &widgets);
223       g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
224       g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
225
226       reset_group_sizes (groups);
227               
228       tmp_list = widgets;
229       while (tmp_list)
230         {
231           if (tmp_list->data == parent)
232             {
233               if (widget == parent)
234                 real_queue_resize (parent);
235             }
236           else
237             queue_resize_on_widget (tmp_list->data, FALSE);
238
239           tmp_list = tmp_list->next;
240         }
241       
242       g_slist_free (widgets);
243       g_slist_free (groups);
244       
245       parent = parent->parent;
246     }
247 }
248
249 static void
250 queue_resize_on_group (GtkSizeGroup *size_group)
251 {
252   if (size_group->widgets)
253     queue_resize_on_widget (size_group->widgets->data, TRUE);
254 }
255
256 static void
257 gtk_size_group_class_init (GtkSizeGroupClass *klass)
258 {
259   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
260
261   gobject_class->set_property = gtk_size_group_set_property;
262   gobject_class->get_property = gtk_size_group_get_property;
263   
264   g_object_class_install_property (gobject_class,
265                                    PROP_MODE,
266                                    g_param_spec_enum ("mode",
267                                                       P_("Mode"),
268                                                       P_("The directions in which the size group affects the requested sizes"
269                                                         " of its component widgets"),
270                                                       GTK_TYPE_SIZE_GROUP_MODE,
271                                                       GTK_SIZE_GROUP_HORIZONTAL,
272                                                       GTK_PARAM_READWRITE));
273
274   /**
275    * GtkSizeGroup:ignore-hidden:
276    *
277    * If %TRUE, hidden widgets are ignored when determining 
278    * the size of the group.
279    *
280    * Since: 2.8
281    */
282   g_object_class_install_property (gobject_class,
283                                    PROP_IGNORE_HIDDEN,
284                                    g_param_spec_boolean ("ignore-hidden",
285                                                          P_("Ignore hidden"),
286                                                          P_("If TRUE, hidden widgets are ignored "
287                                                             "when determining the size of the group"),
288                                                          FALSE,
289                                                          GTK_PARAM_READWRITE));
290
291   size_groups_quark = g_quark_from_static_string (size_groups_tag);
292   visited_quark = g_quark_from_string (visited_tag);
293 }
294
295 static void
296 gtk_size_group_init (GtkSizeGroup *size_group)
297 {
298   size_group->widgets = NULL;
299   size_group->mode = GTK_SIZE_GROUP_HORIZONTAL;
300   size_group->have_width = 0;
301   size_group->have_height = 0;
302   size_group->ignore_hidden = 0;
303 }
304
305 GType
306 gtk_size_group_get_type (void)
307 {
308   static GType size_group_type = 0;
309
310   if (!size_group_type)
311     {
312       static const GTypeInfo size_group_info =
313       {
314         sizeof (GtkSizeGroupClass),
315         NULL,           /* base_init */
316         NULL,           /* base_finalize */
317         (GClassInitFunc) gtk_size_group_class_init,
318         NULL,           /* class_finalize */
319         NULL,           /* class_data */
320         sizeof (GtkSizeGroup),
321         16,             /* n_preallocs */
322         (GInstanceInitFunc) gtk_size_group_init,
323       };
324
325       size_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkSizeGroup"),
326                                                 &size_group_info, 0);
327     }
328
329   return size_group_type;
330 }
331
332 static void
333 gtk_size_group_set_property (GObject      *object,
334                              guint         prop_id,
335                              const GValue *value,
336                              GParamSpec   *pspec)
337 {
338   GtkSizeGroup *size_group = GTK_SIZE_GROUP (object);
339
340   switch (prop_id)
341     {
342     case PROP_MODE:
343       gtk_size_group_set_mode (size_group, g_value_get_enum (value));
344       break;
345     case PROP_IGNORE_HIDDEN:
346       gtk_size_group_set_ignore_hidden (size_group, g_value_get_boolean (value));
347       break;
348     default:
349       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
350       break;
351     }
352 }
353
354 static void
355 gtk_size_group_get_property (GObject      *object,
356                              guint         prop_id,
357                              GValue       *value,
358                              GParamSpec   *pspec)
359 {
360   GtkSizeGroup *size_group = GTK_SIZE_GROUP (object);
361
362   switch (prop_id)
363     {
364     case PROP_MODE:
365       g_value_set_enum (value, size_group->mode);
366       break;
367     case PROP_IGNORE_HIDDEN:
368       g_value_set_boolean (value, size_group->ignore_hidden);
369       break;
370     default:
371       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
372       break;
373     }
374 }
375
376 /**
377  * gtk_size_group_new:
378  * @mode: the mode for the new size group.
379  * 
380  * Create a new #GtkSizeGroup.
381  
382  * Return value: a newly created #GtkSizeGroup
383  **/
384 GtkSizeGroup *
385 gtk_size_group_new (GtkSizeGroupMode  mode)
386 {
387   GtkSizeGroup *size_group = g_object_new (GTK_TYPE_SIZE_GROUP, NULL);
388
389   size_group->mode = mode;
390
391   return size_group;
392 }
393
394 /**
395  * gtk_size_group_set_mode:
396  * @size_group: a #GtkSizeGroup
397  * @mode: the mode to set for the size group.
398  * 
399  * Sets the #GtkSizeGroupMode of the size group. The mode of the size
400  * group determines whether the widgets in the size group should
401  * all have the same horizontal requisition (%GTK_SIZE_GROUP_MODE_HORIZONTAL)
402  * all have the same vertical requisition (%GTK_SIZE_GROUP_MODE_VERTICAL),
403  * or should all have the same requisition in both directions
404  * (%GTK_SIZE_GROUP_MODE_BOTH).
405  **/
406 void
407 gtk_size_group_set_mode (GtkSizeGroup     *size_group,
408                          GtkSizeGroupMode  mode)
409 {
410   g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
411
412   if (size_group->mode != mode)
413     {
414       if (size_group->mode != GTK_SIZE_GROUP_NONE)
415         queue_resize_on_group (size_group);
416       size_group->mode = mode;
417       if (size_group->mode != GTK_SIZE_GROUP_NONE)
418         queue_resize_on_group (size_group);
419
420       g_object_notify (G_OBJECT (size_group), "mode");
421     }
422 }
423
424 /**
425  * gtk_size_group_get_mode:
426  * @size_group: a #GtkSizeGroup
427  * 
428  * Gets the current mode of the size group. See gtk_size_group_set_mode().
429  * 
430  * Return value: the current mode of the size group.
431  **/
432 GtkSizeGroupMode
433 gtk_size_group_get_mode (GtkSizeGroup *size_group)
434 {
435   g_return_val_if_fail (GTK_IS_SIZE_GROUP (size_group), GTK_SIZE_GROUP_BOTH);
436
437   return size_group->mode;
438 }
439
440 /**
441  * gtk_size_group_set_ignore_hidden:
442  * @size_group: a #GtkSizeGroup
443  * @ignore_hidden: whether hidden widgets should be ignored
444  *   when calculating the size
445  * 
446  * Sets whether invisible widgets should be ignored when
447  * calculating the size.
448  *
449  * Since: 2.8 
450  */
451 void
452 gtk_size_group_set_ignore_hidden (GtkSizeGroup *size_group,
453                                   gboolean      ignore_hidden)
454 {
455   g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
456   
457   ignore_hidden = ignore_hidden != FALSE;
458
459   if (size_group->ignore_hidden != ignore_hidden)
460     {
461       size_group->ignore_hidden = ignore_hidden;
462
463       g_object_notify (G_OBJECT (size_group), "ignore-hidden");
464     }
465 }
466
467 /**
468  * gtk_size_group_get_ignore_hidden:
469  * @size_group: a #GtkSizeGroup
470  *
471  * Returns if invisible widgets are ignored when calculating the size.
472  *
473  * Returns: %TRUE if invisible widgets are ignored.
474  *
475  * Since: 2.8
476  */
477 gboolean
478 gtk_size_group_get_ignore_hidden (GtkSizeGroup *size_group)
479 {
480   g_return_val_if_fail (GTK_IS_SIZE_GROUP (size_group), FALSE);
481
482   return size_group->ignore_hidden;
483 }
484
485 static void
486 gtk_size_group_widget_destroyed (GtkWidget    *widget,
487                                  GtkSizeGroup *size_group)
488 {
489   gtk_size_group_remove_widget (size_group, widget);
490 }
491
492 /**
493  * gtk_size_group_add_widget:
494  * @size_group: a #GtkSizeGroup
495  * @widget: the #GtkWidget to add
496  * 
497  * Adds a widget to a #GtkSizeGroup. In the future, the requisition
498  * of the widget will be determined as the maximum of its requisition
499  * and the requisition of the other widgets in the size group.
500  * Whether this applies horizontally, vertically, or in both directions
501  * depends on the mode of the size group. See gtk_size_group_set_mode().
502  **/
503 void
504 gtk_size_group_add_widget (GtkSizeGroup     *size_group,
505                            GtkWidget        *widget)
506 {
507   GSList *groups;
508   
509   g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
510   g_return_if_fail (GTK_IS_WIDGET (widget));
511   
512   groups = get_size_groups (widget);
513
514   if (!g_slist_find (groups, size_group))
515     {
516       groups = g_slist_prepend (groups, size_group);
517       set_size_groups (widget, groups);
518
519       size_group->widgets = g_slist_prepend (size_group->widgets, widget);
520
521       g_signal_connect (widget, "destroy",
522                         G_CALLBACK (gtk_size_group_widget_destroyed),
523                         size_group);
524
525       g_object_ref (size_group);
526     }
527   
528   queue_resize_on_group (size_group);
529 }
530
531 /**
532  * gtk_size_group_remove_widget:
533  * @size_group: a #GtkSizeGrup
534  * @widget: the #GtkWidget to remove
535  * 
536  * Removes a widget from a #GtkSizeGroup.
537  **/
538 void
539 gtk_size_group_remove_widget (GtkSizeGroup     *size_group,
540                               GtkWidget        *widget)
541 {
542   GSList *groups;
543   
544   g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
545   g_return_if_fail (GTK_IS_WIDGET (widget));
546   g_return_if_fail (g_slist_find (size_group->widgets, widget));
547
548   g_signal_handlers_disconnect_by_func (widget,
549                                         gtk_size_group_widget_destroyed,
550                                         size_group);
551   
552   groups = get_size_groups (widget);
553   groups = g_slist_remove (groups, size_group);
554   set_size_groups (widget, groups);
555
556   size_group->widgets = g_slist_remove (size_group->widgets, widget);
557   queue_resize_on_group (size_group);
558   gtk_widget_queue_resize (widget);
559
560   g_object_unref (size_group);
561 }
562
563 /**
564  * gtk_size_group_get_widgets:
565  * @size_group: a #GtkSizeGrup
566  * 
567  * Returns the list of widgets associated with @size_group.
568  *
569  * Return value: a #GSList of widgets. The list is owned by GTK+ 
570  *   and should not be modified.
571  *
572  * Since: 2.10
573  **/
574 GSList *
575 gtk_size_group_get_widgets (GtkSizeGroup *size_group)
576 {
577      return size_group->widgets;
578 }
579
580 static gint
581 get_base_dimension (GtkWidget        *widget,
582                     GtkSizeGroupMode  mode)
583 {
584   GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
585
586   if (mode == GTK_SIZE_GROUP_HORIZONTAL)
587     {
588       if (aux_info && aux_info->width > 0)
589         return aux_info->width;
590       else
591         return widget->requisition.width;
592     }
593   else
594     {
595       if (aux_info && aux_info->height > 0)
596         return aux_info->height;
597       else
598         return widget->requisition.height;
599     }
600 }
601
602 static void
603 do_size_request (GtkWidget *widget)
604 {
605   if (GTK_WIDGET_REQUEST_NEEDED (widget))
606     {
607       gtk_widget_ensure_style (widget);      
608       GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
609       g_signal_emit_by_name (widget,
610                              "size_request",
611                              &widget->requisition);
612     }
613 }
614
615 static gint
616 compute_base_dimension (GtkWidget        *widget,
617                         GtkSizeGroupMode  mode)
618 {
619   do_size_request (widget);
620
621   return get_base_dimension (widget, mode);
622 }
623
624 static gint
625 compute_dimension (GtkWidget        *widget,
626                    GtkSizeGroupMode  mode)
627 {
628   GSList *widgets = NULL;
629   GSList *groups = NULL;
630   GSList *tmp_list;
631   gint result = 0;
632
633   add_widget_to_closure (widget, mode, &groups, &widgets);
634
635   g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
636   g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
637   
638   g_slist_foreach (widgets, (GFunc)g_object_ref, NULL);
639   
640   if (!groups)
641     {
642       result = compute_base_dimension (widget, mode);
643     }
644   else
645     {
646       GtkSizeGroup *group = groups->data;
647
648       if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
649         result = group->requisition.width;
650       else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
651         result = group->requisition.height;
652       else
653         {
654           tmp_list = widgets;
655           while (tmp_list)
656             {
657               GtkWidget *tmp_widget = tmp_list->data;
658
659               gint dimension = compute_base_dimension (tmp_widget, mode);
660
661               if (GTK_WIDGET_VISIBLE (tmp_widget) || !group->ignore_hidden)
662                 {
663                   if (dimension > result)
664                     result = dimension;
665                 }
666
667               tmp_list = tmp_list->next;
668             }
669
670           tmp_list = groups;
671           while (tmp_list)
672             {
673               GtkSizeGroup *tmp_group = tmp_list->data;
674
675               if (mode == GTK_SIZE_GROUP_HORIZONTAL)
676                 {
677                   tmp_group->have_width = TRUE;
678                   tmp_group->requisition.width = result;
679                 }
680               else
681                 {
682                   tmp_group->have_height = TRUE;
683                   tmp_group->requisition.height = result;
684                 }
685               
686               tmp_list = tmp_list->next;
687             }
688         }
689     }
690
691   g_slist_foreach (widgets, (GFunc)g_object_unref, NULL);
692
693   g_slist_free (widgets);
694   g_slist_free (groups);
695
696   return result;
697 }
698
699 static gint
700 get_dimension (GtkWidget        *widget,
701                GtkSizeGroupMode  mode)
702 {
703   GSList *widgets = NULL;
704   GSList *groups = NULL;
705   gint result = 0;
706
707   add_widget_to_closure (widget, mode, &groups, &widgets);
708
709   g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
710   g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);  
711
712   if (!groups)
713     {
714       result = get_base_dimension (widget, mode);
715     }
716   else
717     {
718       GtkSizeGroup *group = groups->data;
719
720       if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
721         result = group->requisition.width;
722       else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
723         result = group->requisition.height;
724     }
725
726   g_slist_free (widgets);
727   g_slist_free (groups);
728
729   return result;
730 }
731
732 static void
733 get_fast_child_requisition (GtkWidget      *widget,
734                             GtkRequisition *requisition)
735 {
736   GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
737   
738   *requisition = widget->requisition;
739   
740   if (aux_info)
741     {
742       if (aux_info->width > 0)
743         requisition->width = aux_info->width;
744       if (aux_info && aux_info->height > 0)
745         requisition->height = aux_info->height;
746     }
747 }
748
749 /**
750  * _gtk_size_group_get_child_requisition:
751  * @widget: a #GtkWidget
752  * @requisition: location to store computed requisition.
753  * 
754  * Retrieve the "child requisition" of the widget, taking account grouping
755  * of the widget's requisition with other widgets.
756  **/
757 void
758 _gtk_size_group_get_child_requisition (GtkWidget      *widget,
759                                        GtkRequisition *requisition)
760 {
761   if (requisition)
762     {
763       if (get_size_groups (widget))
764         {
765           requisition->width = get_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
766           requisition->height = get_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
767
768           /* Only do the full computation if we actually have size groups */
769         }
770       else
771         get_fast_child_requisition (widget, requisition);
772     }
773 }
774
775 /**
776  * _gtk_size_group_compute_requisition:
777  * @widget: a #GtkWidget
778  * @requisition: location to store computed requisition.
779  * 
780  * Compute the requisition of a widget taking into account grouping of
781  * the widget's requisition with other widgets.
782  **/
783 void
784 _gtk_size_group_compute_requisition (GtkWidget      *widget,
785                                      GtkRequisition *requisition)
786 {
787   gint width;
788   gint height;
789
790   if (get_size_groups (widget))
791     {
792       /* Only do the full computation if we actually have size groups */
793       
794       width = compute_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
795       height = compute_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
796
797       if (requisition)
798         {
799           requisition->width = width;
800           requisition->height = height;
801         }
802     }
803   else
804     {
805       do_size_request (widget);
806       
807       if (requisition)
808         get_fast_child_requisition (widget, requisition);
809     }
810 }
811
812 /**
813  * _gtk_size_group_queue_resize:
814  * @widget: a #GtkWidget
815  * 
816  * Queue a resize on a widget, and on all other widgets grouped with this widget.
817  **/
818 void
819 _gtk_size_group_queue_resize (GtkWidget *widget)
820 {
821   queue_resize_on_widget (widget, TRUE);
822 }
823
824 #define __GTK_SIZE_GROUP_C__
825 #include "gtkaliasdef.c"