Re: GtkSizeGroup



Here's my initial implementation of GtkSizeGroup; gtksizegroup.c isn't 
particularly pretty or particularly efficient:

 - The interfaces
 - The way GtkSizeGroup hooks into GTK+'s geometry system
 - The example programs, test programs, and docs

Should be pretty much finished here.

The implementation here probably could go in for now, there are some
quick optimizations so that it doesn't hurt performance when there are
no size groups.

Trying to be smarter should probably be done in conjunction with improving
GTK's size requisition system so that this code doens't need to
be so smart.

In particular I'm thinking of:

 - Keep flag indicating whether widget->requisition is up to dat; clear
   this flag from a widget and its parents when gtk_widget_queue_resize
   is called.

 - Always size allocate the resize containers and remove current "cleverness"
   which causes the annoying size hysteresis phenomena.

Regards,
                                              Owen

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.1961
diff -u -u -r1.1961 ChangeLog
--- ChangeLog	2001/05/16 00:23:28	1.1961
+++ ChangeLog	2001/05/16 16:34:39
@@ -1,3 +1,13 @@
+Tue May 15 17:17:01 2001  Owen Taylor  <otaylor redhat com>
+
+	* gtk/gtkcontainer.c (gtk_container_init): Remove reallocate-redraws
+	property. Doesn't make sense as a property - it's something that would
+	be set on a custom container widget in some circumstances.
+
+	* gtk/gtkcontainer.c (gtk_container_resize_children): s/anchestry/ancestry/.
+
+	* gtk/gtksignal.c (gtk_signal_emitv): Handle G_SIGNAL_TYPE_STATIC_SCOPE.
+
 Tue May 15 20:13:24 2001  Jonathan Blandford  <jrb redhat com>
 
 	* gtk/gtktreeviewcolumn.c: You can now set all sorts of properties
Index: demos/gtk-demo/Makefile.am
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/Makefile.am,v
retrieving revision 1.12
diff -u -u -r1.12 Makefile.am
--- demos/gtk-demo/Makefile.am	2001/05/07 15:58:31	1.12
+++ demos/gtk-demo/Makefile.am	2001/05/16 16:34:39
@@ -14,6 +14,7 @@
 	menus.c		\
 	panes.c		\
 	pixbufs.c	\
+	sizegroup.c	\
 	textview.c	\
 @STRIP_END@
 
Index: demos/gtk-demo/main.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/main.c,v
retrieving revision 1.19
diff -u -u -r1.19 main.c
--- demos/gtk-demo/main.c	2001/05/07 15:58:31	1.19
+++ demos/gtk-demo/main.c	2001/05/16 16:34:39
@@ -1,5 +1,6 @@
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
@@ -282,7 +283,7 @@
 
 	      gtk_signal_connect (GTK_OBJECT (window),
                                   "destroy",
-                                  window_closed_cb,
+                                  GTK_SIGNAL_FUNC (window_closed_cb),
                                   cbdata);
 	    }
 	  else
@@ -334,7 +335,7 @@
       
       gtk_signal_connect (GTK_OBJECT (window),
 			  "destroy",
-			  window_closed_cb,
+			  GTK_SIGNAL_FUNC (window_closed_cb),
 			  cbdata);
     }
 }
@@ -450,7 +451,7 @@
   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
 			       GTK_TREE_VIEW_COLUMN (column));
 
-  gtk_signal_connect (GTK_OBJECT (selection), "selection_changed", selection_cb, model);
+  gtk_signal_connect (GTK_OBJECT (selection), "selection_changed", GTK_SIGNAL_FUNC (selection_cb), model);
   gtk_signal_connect (GTK_OBJECT (tree_view), "row_activated", GTK_SIGNAL_FUNC (row_activated_cb), model);
 
   return tree_view;
Index: demos/gtk-demo/pixbufs.c
===================================================================
RCS file: /cvs/gnome/gtk+/demos/gtk-demo/pixbufs.c,v
retrieving revision 1.1
diff -u -u -r1.1 pixbufs.c
--- demos/gtk-demo/pixbufs.c	2001/04/18 18:09:15	1.1
+++ demos/gtk-demo/pixbufs.c	2001/05/16 16:34:39
@@ -49,7 +49,7 @@
 #define N_IMAGES G_N_ELEMENTS (relative_image_names)
 
 /* demo window */
-static GtkWindow *window = NULL;
+static GtkWidget *window = NULL;
 
 /* Current frame */
 static GdkPixbuf *frame;
Index: demos/gtk-demo/sizegroup.c
===================================================================
RCS file: sizegroup.c
diff -N sizegroup.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ sizegroup.c	Wed May 16 12:34:39 2001
@@ -0,0 +1,172 @@
+/* Size Groups
+ *
+ * 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 GtkTable widget.
+ * 
+ * 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.
+ */
+
+#include <gtk/gtk.h>
+
+static GtkWidget *window = NULL;
+
+/* Convenience function to create an option menu holding a number of strings
+ */
+GtkWidget *
+create_option_menu (const char **strings)
+{
+  GtkWidget *menu;
+  GtkWidget *option_menu;
+  const char **str;
+
+  menu = gtk_menu_new ();
+  
+  for (str = strings; *str; str++)
+    {
+      GtkWidget *menu_item = gtk_menu_item_new_with_label (*str);
+      gtk_widget_show (menu_item);
+
+      gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+    }
+
+  option_menu = gtk_option_menu_new ();
+  gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
+
+  return option_menu;
+}
+
+static void
+add_row (GtkTable     *table,
+	 int           row,
+	 GtkSizeGroup *size_group,
+	 const char   *label_text,
+	 const char  **options)
+{
+  GtkWidget *option_menu;
+  GtkWidget *label;
+
+  label = gtk_label_new (label_text);
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 1);
+  gtk_table_attach (GTK_TABLE (table), label,
+		    0, 1,                  row, row + 1,
+		    GTK_EXPAND | GTK_FILL, 0,
+		    0,                     0);
+  
+  option_menu = create_option_menu (options);
+  gtk_size_group_add_widget (size_group, option_menu);
+  gtk_table_attach (GTK_TABLE (table), option_menu,
+		    1, 2,                  row, row + 1,
+		    GTK_FILL,              0,
+		    0,                     0);
+}
+
+static void
+toggle_grouping (GtkToggleButton *check_button,
+		 GtkSizeGroup    *size_group)
+{
+  GtkSizeGroupMode new_mode;
+
+  /* GTK_SIZE_GROUP_NONE is not generally useful, but is useful
+   * here to show the effect of GTK_SIZE_GROUP_HORIZONTAL by
+   * contrast.
+   */
+  if (gtk_toggle_button_get_active (check_button))
+    new_mode = GTK_SIZE_GROUP_HORIZONTAL;
+  else
+    new_mode = GTK_SIZE_GROUP_NONE;
+  
+  gtk_size_group_set_mode (size_group, new_mode);
+}
+
+GtkWidget *
+do_sizegroup (void)
+{
+  GtkWidget *table;
+  GtkWidget *frame;
+  GtkWidget *vbox;
+  GtkWidget *check_button;
+  GtkSizeGroup *size_group;
+
+  static const char *color_options[] = {
+    "Red", "Green", "Blue", NULL
+  };
+  
+  static const char *dash_options[] = {
+    "Solid", "Dashed", "Dotted", NULL
+  };
+  
+  static const char *end_options[] = {
+    "Square", "Round", "Arrow", NULL
+  };
+  
+  if (!window)
+    {
+      window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
+					    NULL, 0,
+					    GTK_STOCK_BUTTON_CLOSE,
+					    GTK_RESPONSE_NONE,
+					    NULL);
+      gtk_window_set_resizeable (GTK_WINDOW (window), FALSE);
+      
+      gtk_signal_connect (GTK_OBJECT (window), "response",
+			  GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
+      gtk_signal_connect (GTK_OBJECT (window), "destroy",
+			  GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window);
+
+      vbox = gtk_vbox_new (FALSE, 5);
+      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0);
+      gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+
+      size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+      
+      /* Create one frame holding color options
+       */
+      frame = gtk_frame_new ("Color Options");
+      gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
+
+      table = gtk_table_new (2, 2, FALSE);
+      gtk_container_set_border_width (GTK_CONTAINER (table), 5);
+      gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+      gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+      gtk_container_add (GTK_CONTAINER (frame), table);
+
+      add_row (GTK_TABLE (table), 0, size_group, "Foreground", color_options);
+      add_row (GTK_TABLE (table), 1, size_group, "Background", color_options);
+
+      /* And another frame holding line style options
+       */
+      frame = gtk_frame_new ("Line Options");
+      gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
+
+      table = gtk_table_new (2, 2, FALSE);
+      gtk_container_set_border_width (GTK_CONTAINER (table), 5);
+      gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+      gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+      gtk_container_add (GTK_CONTAINER (frame), table);
+
+      add_row (GTK_TABLE (table), 0, size_group, "Dashing", dash_options);
+      add_row (GTK_TABLE (table), 1, size_group, "Line ends", end_options);
+
+      /* And a check button to turn grouping on and off */
+      check_button = gtk_check_button_new_with_label ("Enable grouping");
+      gtk_box_pack_start (GTK_BOX (vbox), check_button, FALSE, FALSE, 0);
+      
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
+      gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+			  GTK_SIGNAL_FUNC (toggle_grouping), size_group);
+    }
+
+  if (!GTK_WIDGET_VISIBLE (window))
+    gtk_widget_show_all (window);
+  else
+    gtk_widget_destroy (window);
+
+  return window;
+}
Index: docs/reference/gtk/gtk-docs.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/gtk-docs.sgml,v
retrieving revision 1.16
diff -u -u -r1.16 gtk-docs.sgml
--- docs/reference/gtk/gtk-docs.sgml	2001/03/23 22:21:05	1.16
+++ docs/reference/gtk/gtk-docs.sgml	2001/05/16 16:34:39
@@ -75,6 +75,7 @@
 <!entity GtkScrollbar SYSTEM "sgml/gtkscrollbar.sgml">
 <!entity GtkScrolledWindow SYSTEM "sgml/gtkscrolledwindow.sgml">
 <!entity GtkSeparator SYSTEM "sgml/gtkseparator.sgml">
+<!entity GtkSizeGroup SYSTEM "sgml/gtksizegroup.sgml">
 <!entity GtkSocket SYSTEM "sgml/gtksocket.sgml">
 <!entity GtkSpinButton SYSTEM "sgml/gtkspinbutton.sgml">
 <!entity GtkStatusbar SYSTEM "sgml/gtkstatusbar.sgml">
@@ -352,6 +353,7 @@
         &GtkHandleBox;
         &GtkIMContext;
         &GtkIMMulticontext;
+        &GtkSizeGroup;
         &GtkTooltips;
         &GtkViewport;
     </sect1>
Index: docs/reference/gtk/gtk-sections.txt
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/gtk-sections.txt,v
retrieving revision 1.19
diff -u -u -r1.19 gtk-sections.txt
--- docs/reference/gtk/gtk-sections.txt	2001/05/11 17:13:43	1.19
+++ docs/reference/gtk/gtk-sections.txt	2001/05/16 16:34:39
@@ -1917,7 +1917,24 @@
 gtk_settings_get_type
 </SECTION>
 
-
+<SECTION>
+<FILE>gtksizegroup</FILE>
+<TITLE>GtkSizeGroup</TITLE>
+GtkSizeGroupMode
+gtk_size_group_new
+gtk_size_group_set_mode
+gtk_size_group_get_mode
+gtk_size_group_add_widget
+gtk_size_group_remove_widget
+<SUBSECTION Standard>
+GTK_SIZE_GROUP
+GTK_IS_SIZE_GROUP
+GTK_TYPE_SIZE_GROUP
+gtk_size_group_get_type
+GTK_SIZE_GROUP_CLASS
+GTK_IS_SIZE_GROUP_CLASS
+GTK_SIZE_GROUP_GET_CLASS
+</SECTION>
 
 <SECTION>
 <FILE>gtksocket</FILE>
Index: docs/reference/gtk/gtk.types
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/gtk.types,v
retrieving revision 1.4
diff -u -u -r1.4 gtk.types
--- docs/reference/gtk/gtk.types	2001/03/15 19:02:17	1.4
+++ docs/reference/gtk/gtk.types	2001/05/16 16:34:39
@@ -73,6 +73,7 @@
 gtk_scrollbar_get_type
 gtk_scrolled_window_get_type
 gtk_separator_get_type
+gtk_size_group_get_type
 gtk_socket_get_type
 gtk_spin_button_get_type
 gtk_statusbar_get_type
Index: docs/reference/gtk/tmpl/gtk-unused.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtk-unused.sgml,v
retrieving revision 1.39
diff -u -u -r1.39 gtk-unused.sgml
--- docs/reference/gtk/tmpl/gtk-unused.sgml	2001/05/10 23:22:14	1.39
+++ docs/reference/gtk/tmpl/gtk-unused.sgml	2001/05/16 16:34:39
@@ -301,6 +301,18 @@
 
 @a: 
 
+<!-- ##### ARG GtkAccelLabel:accel-width ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ARG GtkContainer:reallocate-redraws ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### STRUCT GtkData ##### -->
 <para>
 The #GtkData-struct struct contains no public fields.
Index: docs/reference/gtk/tmpl/gtkcontainer.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkcontainer.sgml,v
retrieving revision 1.7
diff -u -u -r1.7 gtkcontainer.sgml
--- docs/reference/gtk/tmpl/gtkcontainer.sgml	2001/04/01 04:05:41	1.7
+++ docs/reference/gtk/tmpl/gtkcontainer.sgml	2001/05/16 16:34:39
@@ -422,8 +422,3 @@
 
 </para>
 
-<!-- ##### ARG GtkContainer:reallocate-redraws ##### -->
-<para>
-
-</para>
-
Index: docs/reference/gtk/tmpl/gtkpaned.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkpaned.sgml,v
retrieving revision 1.6
diff -u -u -r1.6 gtkpaned.sgml
--- docs/reference/gtk/tmpl/gtkpaned.sgml	2001/04/03 04:29:57	1.6
+++ docs/reference/gtk/tmpl/gtkpaned.sgml	2001/05/16 16:34:39
@@ -168,3 +168,13 @@
 @Returns: 
 
 
+<!-- ##### ARG GtkPaned:position ##### -->
+<para>
+
+</para>
+
+<!-- ##### ARG GtkPaned:position-set ##### -->
+<para>
+
+</para>
+
Index: docs/reference/gtk/tmpl/gtkrc.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtkrc.sgml,v
retrieving revision 1.23
diff -u -u -r1.23 gtkrc.sgml
--- docs/reference/gtk/tmpl/gtkrc.sgml	2001/05/07 15:58:38	1.23
+++ docs/reference/gtk/tmpl/gtkrc.sgml	2001/05/16 16:34:39
@@ -495,7 +495,6 @@
 #GtkRcStyle structures to form a #GtkStyle.
 </para>
 
- parent_instance: 
 @name: 
 @bg_pixmap_name: 
 @font_desc: 
Index: docs/reference/gtk/tmpl/gtksizegroup.sgml
===================================================================
RCS file: gtksizegroup.sgml
diff -N gtksizegroup.sgml
--- /dev/null	Tue May  5 16:32:27 1998
+++ gtksizegroup.sgml	Wed May 16 12:34:39 2001
@@ -0,0 +1,113 @@
+<!-- ##### SECTION Title ##### -->
+GtkSizeGroup
+
+<!-- ##### SECTION Short_Description ##### -->
+Grouping widgets so they request the same size
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+#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 #GtkTable widget.
+</para>
+<para>
+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.
+</para>
+<para>
+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.
+</para>
+<para>
+#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.
+</para>
+<para>
+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.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### ENUM GtkSizeGroupMode ##### -->
+<para>
+
+</para>
+
+ GTK_SIZE_GROUP_NONE: 
+ GTK_SIZE_GROUP_HORIZONTAL: 
+ GTK_SIZE_GROUP_VERTICAL: 
+ GTK_SIZE_GROUP_BOTH: 
+
+<!-- ##### FUNCTION gtk_size_group_new ##### -->
+<para>
+
+</para>
+
+ mode: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gtk_size_group_set_mode ##### -->
+<para>
+
+</para>
+
+ size_group: 
+ type: 
+
+
+<!-- ##### FUNCTION gtk_size_group_get_mode ##### -->
+<para>
+
+</para>
+
+ size_group: 
+ Returns: 
+
+
+<!-- ##### FUNCTION gtk_size_group_add_widget ##### -->
+<para>
+
+</para>
+
+ size_group: 
+ widget: 
+
+
+<!-- ##### FUNCTION gtk_size_group_remove_widget ##### -->
+<para>
+
+</para>
+
+ size_group: 
+ widget: 
+
+
+<!-- ##### ARG GtkSizeGroup:mode ##### -->
+<para>
+
+</para>
+
Index: docs/reference/gtk/tmpl/gtktogglebutton.sgml
===================================================================
RCS file: /cvs/gnome/gtk+/docs/reference/gtk/tmpl/gtktogglebutton.sgml,v
retrieving revision 1.5
diff -u -u -r1.5 gtktogglebutton.sgml
--- docs/reference/gtk/tmpl/gtktogglebutton.sgml	2001/03/23 22:21:05	1.5
+++ docs/reference/gtk/tmpl/gtktogglebutton.sgml	2001/05/16 16:34:39
@@ -174,6 +174,11 @@
 Sets whether the toggle button should be pressed in or not.
 </para>
 
+<!-- ##### ARG GtkToggleButton:inconsistent ##### -->
+<para>
+
+</para>
+
 <!-- ##### ARG GtkToggleButton:draw-indicator ##### -->
 <para>
 A value of TRUE causes the toggle button to be invisible. FALSE displays it
Index: gtk/Makefile.am
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/Makefile.am,v
retrieving revision 1.169
diff -u -u -r1.169 Makefile.am
--- gtk/Makefile.am	2001/05/03 20:11:07	1.169
+++ gtk/Makefile.am	2001/05/16 16:34:39
@@ -140,6 +140,7 @@
 	gtkseparator.h		\
 	gtksettings.h		\
 	gtksignal.h		\
+	gtksizegroup.h		\
 	gtksocket.h		\
 	gtkspinbutton.h		\
 	gtkstyle.h		\
@@ -299,6 +300,7 @@
 	gtkseparator.c		\
 	gtksettings.c		\
 	gtksignal.c		\
+	gtksizegroup.c		\
 	gtkspinbutton.c		\
 	gtkstock.c		\
 	gtkstyle.c		\
Index: gtk/gtk.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk.h,v
retrieving revision 1.50
diff -u -u -r1.50 gtk.h
--- gtk/gtk.h	2001/05/03 20:11:07	1.50
+++ gtk/gtk.h	2001/05/16 16:34:39
@@ -125,6 +125,7 @@
 #include <gtk/gtkseparatormenuitem.h>
 #include <gtk/gtksettings.h>
 #include <gtk/gtksignal.h>
+#include <gtk/gtksizegroup.h>
 #include <gtk/gtksocket.h>
 #include <gtk/gtkspinbutton.h>
 #include <gtk/gtkstock.h>
Index: gtk/gtkcontainer.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcontainer.c,v
retrieving revision 1.74
diff -u -u -r1.74 gtkcontainer.c
--- gtk/gtkcontainer.c	2001/03/30 15:46:14	1.74
+++ gtk/gtkcontainer.c	2001/05/16 16:34:39
@@ -49,7 +49,6 @@
   PROP_BORDER_WIDTH,
   PROP_RESIZE_MODE,
   PROP_CHILD,
-  PROP_REALLOCATE_REDRAWS
 };
 
 typedef struct _GtkChildArgInfo	GtkChildArgInfo;
@@ -200,13 +199,7 @@
                                                       _("Can be used to add a new child to the container."),
                                                       GTK_TYPE_WIDGET,
 						      G_PARAM_WRITABLE));
-  g_object_class_install_property (gobject_class,
-                                   PROP_REALLOCATE_REDRAWS,
-                                   g_param_spec_boolean ("reallocate_redraws",
-							 _("Reallocate redraws"),
-							 _("Whether redraws should be reallocated"),
-							 FALSE,
-							 G_PARAM_READWRITE));
+
   object_class->destroy = gtk_container_destroy;
 
   widget_class->show_all = gtk_container_show_all;
@@ -689,10 +682,6 @@
     case PROP_RESIZE_MODE:
       gtk_container_set_resize_mode (container, g_value_get_enum (value));
       break;
-    case PROP_REALLOCATE_REDRAWS:
-      gtk_container_set_reallocate_redraws (container, 
-					    g_value_get_boolean (value));
-      break;
     case PROP_CHILD:
       gtk_container_add (container, GTK_WIDGET (g_value_get_object (value)));
       break;
@@ -720,9 +709,6 @@
     case PROP_RESIZE_MODE:
       g_value_set_enum (value, container->resize_mode);
       break;
-    case PROP_REALLOCATE_REDRAWS:
-      g_value_set_boolean (value, container->reallocate_redraws);
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -889,15 +875,7 @@
 {
   g_return_if_fail (GTK_IS_CONTAINER (container));
 
-  needs_redraws = needs_redraws ? TRUE : FALSE;
-  if (needs_redraws != container->reallocate_redraws)
-    {
-      container->reallocate_redraws = needs_redraws;
-      g_object_notify (G_OBJECT (container), "reallocate_redraws");
-      
-      if (container->reallocate_redraws)
-	gtk_widget_queue_draw (GTK_WIDGET (container));
-    }
+  container->reallocate_redraws = needs_redraws ? TRUE : FALSE;
 }
 
 static GtkContainer*
@@ -1092,7 +1070,7 @@
 
   /* we first check out if we actually need to perform a resize,
    * which is not the case if we got another container queued for
-   * a resize in our anchestry. also we can skip the whole
+   * a resize in our ancestry. also we can skip the whole
    * resize_widgets checks if we are a toplevel and NEED_RESIZE.
    * this code assumes that our allocation is sufficient for our
    * requisition, since otherwise we would NEED_RESIZE.
@@ -1119,7 +1097,7 @@
 
   resize_container = GTK_WIDGET (container);
 
-  /* we now walk the anchestry for all resize widgets as long
+  /* we now walk the ancestry for all resize widgets as long
    * as they are our children and as long as their allocation
    * is insufficient, since we don't need to reallocate below that.
    */
@@ -1141,9 +1119,9 @@
     }
 
   /* for the newly setup resize_widgets list, we now walk each widget's
-   * anchestry to sort those widgets out that have RESIZE_NEEDED parents.
+   * ancestry to sort those widgets out that have RESIZE_NEEDED parents.
    * we can safely stop the walk if we are the parent, since we checked
-   * our own anchestry already.
+   * our own ancestry already.
    */
   resize_containers = NULL;
   for (node = resize_widgets; node; node = node->next)
Index: gtk/gtksignal.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksignal.c,v
retrieving revision 1.71
diff -u -u -r1.71 gtksignal.c
--- gtk/gtksignal.c	2001/03/08 16:36:16	1.71
+++ gtk/gtksignal.c	2001/05/16 16:34:39
@@ -321,11 +321,12 @@
       GValue *value = params + 1 + i;
       GtkArg *arg = args + i;
       
-      g_value_init (value, arg->type);
+      g_value_init (value, arg->type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
       if (!gtk_arg_static_to_value (arg, value))
 	{
 	  g_warning ("%s: failed to convert arg type `%s' to value type `%s'",
-		     G_STRLOC, g_type_name (arg->type), g_type_name (G_VALUE_TYPE (value)));
+		     G_STRLOC, g_type_name (arg->type & ~G_SIGNAL_TYPE_STATIC_SCOPE),
+		     g_type_name (G_VALUE_TYPE (value)));
 	  return;
 	}
     }
Index: gtk/gtksizegroup.c
===================================================================
RCS file: gtksizegroup.c
diff -N gtksizegroup.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ gtksizegroup.c	Wed May 16 12:34:39 2001
@@ -0,0 +1,679 @@
+/* GTK - The GIMP Toolkit
+ * gtksizegroup.c: 
+ * Copyright (C) 2001 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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.
+ */
+
+#include "gtkcontainer.h"
+#include "gtkintl.h"
+#include "gtksignal.h"
+#include "gtksizegroup.h"
+
+enum {
+  PROP_0,
+  PROP_MODE
+};
+
+static void gtk_size_group_set_property (GObject      *object,
+					 guint         prop_id,
+					 const GValue *value,
+					 GParamSpec   *pspec);
+static void gtk_size_group_get_property (GObject      *object,
+					 guint         prop_id,
+					 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);
+
+static GQuark size_groups_quark;
+static const gchar *size_groups_tag = "gtk-size-groups";
+
+static GSList *
+get_size_groups (GtkWidget *widget)
+{
+  if (!size_groups_quark)
+    size_groups_quark = g_quark_from_string (size_groups_tag);
+  
+  return g_object_get_qdata (G_OBJECT (widget), size_groups_quark);
+}
+
+static void
+set_size_groups (GtkWidget *widget,
+		 GSList    *groups)
+{
+  if (!size_groups_quark)
+    size_groups_quark = g_quark_from_string (size_groups_tag);
+
+  g_object_set_qdata (G_OBJECT (widget), size_groups_quark, groups);
+}
+
+static void
+add_group_to_closure (GtkSizeGroup    *group,
+		      GtkSizeGroupMode mode,
+		      GSList         **groups,
+		      GSList         **widgets)
+{
+  GSList *tmp_widgets;
+  
+  *groups = g_slist_prepend (*groups, group);
+
+  tmp_widgets = group->widgets;
+  while (tmp_widgets)
+    {
+      GtkWidget *tmp_widget = tmp_widgets->data;
+      
+      if (!g_slist_find (*widgets, tmp_widget))
+	add_widget_to_closure (tmp_widget, mode, groups, widgets);
+      
+      tmp_widgets = tmp_widgets->next;
+    }
+}
+
+static void
+add_widget_to_closure (GtkWidget       *widget,
+		       GtkSizeGroupMode mode,
+		       GSList         **groups,
+		       GSList         **widgets)
+{
+  GSList *tmp_groups;
+
+  *widgets = g_slist_prepend (*widgets, widget);
+
+  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) &&
+	  !g_slist_find (*groups, tmp_group))
+	add_group_to_closure (tmp_group, mode, groups, widgets);
+
+      tmp_groups = tmp_groups->next;
+    }
+}
+
+static void
+real_queue_resize (GtkWidget *widget)
+{
+  if (GTK_IS_RESIZE_CONTAINER (widget))
+    gtk_container_clear_resize_widgets (GTK_CONTAINER (widget));
+  
+  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));
+}
+
+static void
+reset_group_sizes (GSList *groups)
+{
+  GSList *tmp_list = groups;
+  while (tmp_list)
+    {
+      GtkSizeGroup *tmp_group = tmp_list->data;
+
+      tmp_group->have_width = FALSE;
+      tmp_group->have_height = FALSE;
+      
+      tmp_list = tmp_list->next;
+    }
+}
+
+static void
+queue_resize_on_widget (GtkWidget *widget,
+			gboolean   check_siblings)
+{
+  GtkWidget *parent = widget;
+  GSList *tmp_list;
+
+  while (parent)
+    {
+      GSList *widget_groups;
+      GSList *groups;
+      GSList *widgets;
+      
+      if (widget == parent && !check_siblings)
+	{
+	  real_queue_resize (widget);
+	  parent = parent->parent;
+	  continue;
+	}
+      
+      widget_groups = get_size_groups (parent);
+      if (!widget_groups)
+	{
+	  if (widget == parent)
+	    real_queue_resize (widget);
+
+	  parent = parent->parent;
+	  continue;
+	}
+
+      groups = NULL;
+      widgets = NULL;
+	  
+      add_widget_to_closure (parent, GTK_SIZE_GROUP_HORIZONTAL, &groups, &widgets);
+      reset_group_sizes (groups);
+	      
+      tmp_list = widgets;
+      while (tmp_list)
+	{
+	  if (tmp_list->data == parent)
+	    {
+	      if (widget == parent)
+		real_queue_resize (parent);
+	    }
+	  else
+	    queue_resize_on_widget (tmp_list->data, FALSE);
+
+	  tmp_list = tmp_list->next;
+	}
+      
+      g_slist_free (widgets);
+      g_slist_free (groups);
+	      
+      groups = NULL;
+      widgets = NULL;
+	      
+      add_widget_to_closure (parent, GTK_SIZE_GROUP_VERTICAL, &groups, &widgets);
+      reset_group_sizes (groups);
+	      
+      tmp_list = widgets;
+      while (tmp_list)
+	{
+	  if (tmp_list->data == parent)
+	    {
+	      if (widget == parent)
+		real_queue_resize (parent);
+	    }
+	  else
+	    queue_resize_on_widget (tmp_list->data, FALSE);
+
+	  tmp_list = tmp_list->next;
+	}
+      
+      g_slist_free (widgets);
+      g_slist_free (groups);
+      
+      parent = parent->parent;
+    }
+}
+
+static void
+queue_resize_on_group (GtkSizeGroup *size_group)
+{
+  if (size_group->widgets)
+    queue_resize_on_widget (size_group->widgets->data);
+}
+
+static void
+gtk_size_group_class_init (GtkSizeGroupClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gtk_size_group_set_property;
+  gobject_class->get_property = gtk_size_group_get_property;
+  
+  g_object_class_install_property (gobject_class,
+				   PROP_MODE,
+				   g_param_spec_enum ("mode",
+						      _("Mode"),
+						      _("The the directions in which the size group effects the requested sizes"
+							" of its component widgets."),
+						      GTK_TYPE_SIZE_GROUP_MODE,
+						      GTK_SIZE_GROUP_HORIZONTAL,
+						      G_PARAM_READWRITE));
+}
+
+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;
+}
+
+GtkType
+gtk_size_group_get_type (void)
+{
+  static GtkType size_group_type = 0;
+
+  if (!size_group_type)
+    {
+      static const GTypeInfo size_group_info =
+      {
+	sizeof (GtkSizeGroupClass),
+	NULL,		/* base_init */
+	NULL,		/* base_finalize */
+	(GClassInitFunc) gtk_size_group_class_init,
+	NULL,		/* class_finalize */
+	NULL,		/* class_data */
+	sizeof (GtkSizeGroup),
+	16,		/* n_preallocs */
+	(GInstanceInitFunc) gtk_size_group_init,
+      };
+
+      size_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkSizeGroup", &size_group_info, 0);
+    }
+
+  return size_group_type;
+}
+
+static void
+gtk_size_group_set_property (GObject      *object,
+			     guint         prop_id,
+			     const GValue *value,
+			     GParamSpec   *pspec)
+{
+  GtkSizeGroup *size_group = GTK_SIZE_GROUP (object);
+
+  switch (prop_id)
+    {
+    case PROP_MODE:
+      gtk_size_group_set_mode (size_group, g_value_get_enum (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_size_group_get_property (GObject      *object,
+			     guint         prop_id,
+			     GValue       *value,
+			     GParamSpec   *pspec)
+{
+  GtkSizeGroup *size_group = GTK_SIZE_GROUP (object);
+
+  switch (prop_id)
+    {
+    case PROP_MODE:
+      g_value_set_enum (value, size_group->mode);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/**
+ * gtk_size_group_new:
+ * @mode: the mode for the new size group.
+ * 
+ * Create a new #GtkSizeGroup.
+ 
+ * Return value: a newly created #GtkSizeGroup
+ **/
+GtkSizeGroup *
+gtk_size_group_new (GtkSizeGroupMode  mode)
+{
+  GtkSizeGroup *size_group = g_object_new (GTK_TYPE_SIZE_GROUP, NULL);
+
+  size_group->mode = mode;
+
+  return size_group;
+}
+
+/**
+ * gtk_size_group_set_mode:
+ * @size_group: a #GtkSizeGroup
+ * @mode: the mode to set for the size group.
+ * 
+ * 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),
+ * or should all have the same requisition in both directions.
+ * (%GTK_SIZE_GROUP_MODE_BOTH).
+ **/
+void
+gtk_size_group_set_mode (GtkSizeGroup     *size_group,
+			 GtkSizeGroupMode  mode)
+{
+  g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
+
+  if (size_group->mode != mode)
+    {
+      size_group->mode = mode;
+      queue_resize_on_group (size_group);
+    }
+}
+
+/**
+ * gtk_size_group_get_mode:
+ * @size_group: a #GtkSizeGroup
+ * 
+ * Gets the current mode of the size group. See gtk_size_group_set_mode().
+ * 
+ * Return value: the current mode of the size group.
+ **/
+GtkSizeGroupMode
+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;
+}
+
+static void
+gtk_size_group_widget_destroyed (GtkWidget    *widget,
+				 GtkSizeGroup *size_group)
+{
+  gtk_size_group_remove_widget (size_group, widget);
+}
+
+/**
+ * gtk_size_group_add_widget:
+ * @size_group: a #GtkSizeGroup
+ * @widget: the #GtkWidget to add
+ * 
+ * Adds a widget to a #GtkSizeGroup. In the future, the requisition
+ * of the widget will be determined as the maximum of its requisition
+ * and the requisition of the other widgets in the size group.
+ * Whether this applies horizontally, vertically, or in both directions
+ * depends on the mode of the size group. See gtk_size_group_set_mode().
+ **/
+void
+gtk_size_group_add_widget (GtkSizeGroup     *size_group,
+			   GtkWidget        *widget)
+{
+  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);
+
+  if (!g_slist_find (groups, widget))
+    {
+      groups = g_slist_prepend (groups, size_group);
+      set_size_groups (widget, groups);
+
+      size_group->widgets = g_slist_prepend (size_group->widgets, widget);
+
+      gtk_signal_connect (GTK_OBJECT (widget), "destroy",
+			  GTK_SIGNAL_FUNC (gtk_size_group_widget_destroyed), size_group);
+
+      g_object_ref (G_OBJECT (size_group));
+    }
+  
+  queue_resize_on_group (size_group);
+}
+
+/**
+ * gtk_size_group_remove_widget:
+ * @size_group: a #GtkSizeGrup
+ * @widget: the #GtkWidget to remove
+ * 
+ * Removes a widget from a #GtkSizeGroup.
+ **/
+void
+gtk_size_group_remove_widget (GtkSizeGroup     *size_group,
+			      GtkWidget        *widget)
+{
+  GSList *groups;
+  
+  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));
+
+  gtk_signal_disconnect_by_func (GTK_OBJECT (widget), 
+				 GTK_SIGNAL_FUNC (gtk_size_group_widget_destroyed), size_group);
+  
+  groups = get_size_groups (widget);
+  groups = g_slist_remove (groups, size_group);
+  set_size_groups (widget, groups);
+
+  size_group->widgets = g_slist_remove (size_group->widgets, widget);
+  queue_resize_on_group (size_group);
+  gtk_widget_queue_resize (widget);
+
+  g_object_unref (G_OBJECT (size_group));
+}
+
+static gint
+get_base_dimension (GtkWidget        *widget,
+		    GtkSizeGroupMode  mode)
+{
+  GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
+
+  if (mode == GTK_SIZE_GROUP_HORIZONTAL)
+    {
+      if (aux_info && aux_info->width > 0)
+	return aux_info->width;
+      else
+	return widget->requisition.width;
+    }
+  else
+    {
+      if (aux_info && aux_info->height > 0)
+	return aux_info->height;
+      else
+	return widget->requisition.height;
+    }
+}
+
+static gint
+compute_base_dimension (GtkWidget        *widget,
+			GtkSizeGroupMode  mode)
+{
+  gtk_widget_ensure_style (widget);
+  gtk_signal_emit_by_name (GTK_OBJECT (widget), "size_request", &widget->requisition);
+
+  return get_base_dimension (widget, mode);
+}
+
+static gint
+compute_dimension (GtkWidget        *widget,
+		   GtkSizeGroupMode  mode)
+{
+  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)g_object_ref, NULL);
+  
+  if (!groups)
+    {
+      result = compute_base_dimension (widget, mode);
+    }
+  else
+    {
+      GtkSizeGroup *group = groups->data;
+
+      if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
+	result = group->requisition.width;
+      else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
+	result = group->requisition.height;
+      else
+	{
+	  tmp_list = widgets;
+	  while (tmp_list)
+	    {
+	      GtkWidget *tmp_widget = tmp_list->data;
+
+	      gint dimension = compute_base_dimension (tmp_widget, mode);
+
+	      if (dimension > result)
+		result = dimension;
+	      
+	      tmp_list = tmp_list->next;
+	    }
+
+	  tmp_list = groups;
+	  while (tmp_list)
+	    {
+	      GtkSizeGroup *tmp_group = tmp_list->data;
+
+	      if (mode == GTK_SIZE_GROUP_HORIZONTAL)
+		{
+		  tmp_group->have_width = TRUE;
+		  tmp_group->requisition.width = result;
+		}
+	      else
+		{
+		  tmp_group->have_height = TRUE;
+		  tmp_group->requisition.height = result;
+		}
+	      
+	      tmp_list = tmp_list->next;
+	    }
+	}
+    }
+
+  g_slist_foreach (widgets, (GFunc)g_object_unref, NULL);
+  
+  g_slist_free (widgets);
+  g_slist_free (groups);
+
+  return result;
+}
+
+static gint
+get_dimension (GtkWidget        *widget,
+	       GtkSizeGroupMode  mode)
+{
+  GSList *widgets = NULL;
+  GSList *groups = NULL;
+  gint result = 0;
+
+  add_widget_to_closure (widget, mode, &groups, &widgets);
+
+  if (!groups)
+    {
+      result = get_base_dimension (widget, mode);
+    }
+  else
+    {
+      GtkSizeGroup *group = groups->data;
+
+      if (mode == GTK_SIZE_GROUP_HORIZONTAL && group->have_width)
+	result = group->requisition.width;
+      else if (mode == GTK_SIZE_GROUP_VERTICAL && group->have_height)
+	result = group->requisition.height;
+    }
+
+  g_slist_free (widgets);
+  g_slist_free (groups);
+
+  return result;
+}
+
+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 && aux_info->height > 0)
+	requisition->height = aux_info->height;
+    }
+}
+
+/**
+ * _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)
+{
+  if (requisition)
+    {
+      if (get_size_groups (widget))
+	{
+	  requisition->width = get_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
+	  requisition->height = get_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
+
+	  /* Only do the full computation if we actually have size groups */
+	}
+      else
+	get_fast_child_requisition (widget, requisition);
+    }
+}
+
+/**
+ * _gtk_size_group_compute_requisition:
+ * @widget: a #GtkWidget
+ * @requisition: location to store computed requisition.
+ * 
+ * Compute the requisition of a widget taking into account grouping of
+ * the widget's requisition with other widgets.
+ **/
+void
+_gtk_size_group_compute_requisition (GtkWidget      *widget,
+				     GtkRequisition *requisition)
+{
+  gint width;
+  gint height;
+
+  if (get_size_groups (widget))
+    {
+      /* Only do the full computation if we actually have size groups */
+      
+      width = compute_dimension (widget, GTK_SIZE_GROUP_HORIZONTAL);
+      height = compute_dimension (widget, GTK_SIZE_GROUP_VERTICAL);
+
+      if (requisition)
+	{
+	  requisition->width = width;
+	  requisition->height = height;
+	}
+    }
+  else
+    {
+      gtk_widget_ensure_style (widget);
+      gtk_signal_emit_by_name (GTK_OBJECT (widget), "size_request", &widget->requisition);
+
+      if (requisition)
+	get_fast_child_requisition (widget, requisition);
+    }
+}
+
+/**
+ * _gtk_size_group_queue_resize:
+ * @widget: a #GtkWidget
+ * 
+ * Queue a resize on a widget, and on all other widgets grouped with this widget.
+ **/
+void
+_gtk_size_group_queue_resize (GtkWidget *widget)
+{
+  queue_resize_on_widget (widget, TRUE);
+}
Index: gtk/gtksizegroup.h
===================================================================
RCS file: gtksizegroup.h
diff -N gtksizegroup.h
--- /dev/null	Tue May  5 16:32:27 1998
+++ gtksizegroup.h	Wed May 16 12:34:39 2001
@@ -0,0 +1,100 @@
+/* GTK - The GIMP Toolkit
+ * gtksizegroup.h: 
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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.
+ */
+
+#ifndef __GTK_SIZE_GROUP_H__
+#define __GTK_SIZE_GROUP_H__
+
+#include <gtk/gtkwidget.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GTK_TYPE_SIZE_GROUP            (gtk_size_group_get_type ())
+#define GTK_SIZE_GROUP(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_SIZE_GROUP, GtkSizeGroup))
+#define GTK_SIZE_GROUP_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_SIZE_GROUP, GtkSizeGroupClass))
+#define GTK_IS_SIZE_GROUP(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_SIZE_GROUP))
+#define GTK_IS_SIZE_GROUP_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SIZE_GROUP))
+#define GTK_SIZE_GROUP_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_SIZE_GROUP, GtkSizeGroupClass))
+
+
+typedef struct _GtkSizeGroup       GtkSizeGroup;
+typedef struct _GtkSizeGroupClass  GtkSizeGroupClass;
+
+struct _GtkSizeGroup
+{
+  GObject parent_instance;
+
+  GSList *widgets;
+
+  guint8 mode;
+  
+  guint have_width : 1;
+  guint have_height : 1;
+
+  GtkRequisition requisition;
+};
+
+struct _GtkSizeGroupClass
+{
+  GObjectClass parent_class;
+};
+
+/**
+ * GtkSizeGroupMode:
+ * @GTK_SIZE_GROUP_NONE: group has no effect  
+ * @GTK_SIZE_GROUP_HORIZONTAL: group effects horizontal requisition
+ * @GTK_SIZE_GROUP_VERTICAL: group effects vertical requisition
+ * @GTK_SIZE_GROUP_BOTH: group effects both horizontal and vertical requisition
+ * 
+ * The mode of the size group determines the directions in which the size
+ * group effects the requested sizes of its component widgets.
+ **/
+typedef enum {
+  GTK_SIZE_GROUP_NONE,
+  GTK_SIZE_GROUP_HORIZONTAL,
+  GTK_SIZE_GROUP_VERTICAL,
+  GTK_SIZE_GROUP_BOTH
+} GtkSizeGroupMode;
+
+GType            gtk_size_group_get_type      (void) G_GNUC_CONST;;
+
+GtkSizeGroup *   gtk_size_group_new           (GtkSizeGroupMode  mode);
+void             gtk_size_group_set_mode      (GtkSizeGroup     *size_group,
+					       GtkSizeGroupMode  type);
+GtkSizeGroupMode gtk_size_group_get_mode      (GtkSizeGroup     *size_group);
+void             gtk_size_group_add_widget    (GtkSizeGroup     *size_group,
+					       GtkWidget        *widget);
+void             gtk_size_group_remove_widget (GtkSizeGroup     *size_group,
+					       GtkWidget        *widget);
+
+
+void _gtk_size_group_get_child_requisition (GtkWidget      *widget,
+					    GtkRequisition *requisition);
+void _gtk_size_group_compute_requisition   (GtkWidget      *widget,
+					    GtkRequisition *requisition);
+void _gtk_size_group_queue_resize          (GtkWidget      *widget);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_SIZE_GROUP_H__ */
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.214
diff -u -u -r1.214 gtkwidget.c
--- gtk/gtkwidget.c	2001/05/03 20:11:07	1.214
+++ gtk/gtkwidget.c	2001/05/16 16:34:39
@@ -34,6 +34,7 @@
 #include "gtkrc.h"
 #include "gtkselection.h"
 #include "gtksettings.h"
+#include "gtksizegroup.h"
 #include "gtksignal.h"
 #include "gtkwidget.h"
 #include "gtkwindow.h"
@@ -2081,15 +2082,9 @@
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_WIDGET (widget));
 
-  if (GTK_IS_RESIZE_CONTAINER (widget))
-    gtk_container_clear_resize_widgets (GTK_CONTAINER (widget));
-
   gtk_widget_queue_clear (widget);
 
-  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));
+  _gtk_size_group_queue_resize (widget);
 }
 
 /**
@@ -2149,15 +2144,14 @@
     g_warning ("gtk_widget_size_request() called on child widget with request equal\n to widget->requisition. gtk_widget_set_usize() may not work properly.");
 #endif /* G_ENABLE_DEBUG */
 
-  gtk_widget_ref (widget);
-  gtk_widget_ensure_style (widget);
-  gtk_signal_emit (GTK_OBJECT (widget), widget_signals[SIZE_REQUEST],
-		   &widget->requisition);
+  _gtk_size_group_compute_requisition (widget, requisition);
 
+#if 0  
   if (requisition)
     gtk_widget_get_child_requisition (widget, requisition);
 
   gtk_widget_unref (widget);
+#endif  
 }
 
 /**
@@ -2174,21 +2168,7 @@
 gtk_widget_get_child_requisition (GtkWidget	 *widget,
 				  GtkRequisition *requisition)
 {
-  GtkWidgetAuxInfo *aux_info;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-
-  *requisition = widget->requisition;
-  
-  aux_info =_gtk_widget_get_aux_info (widget, FALSE);
-  if (aux_info)
-    {
-      if (aux_info->width > 0)
-	requisition->width = aux_info->width;
-      if (aux_info->height > 0)
-	requisition->height = aux_info->height;
-    }
+  _gtk_size_group_get_child_requisition (widget, requisition);
 }
 
 /**
Index: tests/testgtk.c
===================================================================
RCS file: /cvs/gnome/gtk+/tests/testgtk.c,v
retrieving revision 1.250
diff -u -u -r1.250 testgtk.c
--- tests/testgtk.c	2001/05/14 19:14:57	1.250
+++ tests/testgtk.c	2001/05/16 16:34:39
@@ -3636,6 +3636,169 @@
 }
 
 /*
+ * GtkSizeGroup
+ */
+
+#define SIZE_GROUP_INITIAL_SIZE 50
+
+static void
+size_group_hsize_changed (GtkSpinButton *spin_button,
+			  GtkWidget     *button)
+{
+  gtk_widget_set_usize (GTK_BIN (button)->child,
+			gtk_spin_button_get_value_as_int (spin_button),
+			-2);
+}
+
+static void
+size_group_vsize_changed (GtkSpinButton *spin_button,
+			  GtkWidget     *button)
+{
+  gtk_widget_set_usize (GTK_BIN (button)->child,
+			-2,
+			gtk_spin_button_get_value_as_int (spin_button));
+}
+
+static GtkWidget *
+create_size_group_window (GtkSizeGroup *master_size_group)
+{
+  GtkWidget *window;
+  GtkWidget *table;
+  GtkWidget *main_button;
+  GtkWidget *button;
+  GtkWidget *spin_button;
+  GtkWidget *hbox;
+  GtkSizeGroup *hgroup1;
+  GtkSizeGroup *hgroup2;
+  GtkSizeGroup *vgroup1;
+  GtkSizeGroup *vgroup2;
+
+  window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
+					NULL, 0,
+					GTK_STOCK_BUTTON_CLOSE,
+					GTK_RESPONSE_NONE,
+					NULL);
+
+  gtk_window_set_resizeable (GTK_WINDOW (window), FALSE);
+
+  gtk_signal_connect (GTK_OBJECT (window), "response",
+		      GTK_SIGNAL_FUNC (gtk_widget_destroy),
+		      NULL);
+
+  table = gtk_table_new (2, 2, FALSE);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table, TRUE, TRUE, 0);
+
+  gtk_table_set_row_spacings (GTK_TABLE (table), 5);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 5);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 5);
+  gtk_widget_set_usize (table, 250, 250);
+
+  hgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+  hgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+  vgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+  vgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+
+  main_button = gtk_button_new_with_label ("X");
+  
+  gtk_table_attach (GTK_TABLE (table), main_button,
+		    0, 1,       0, 1,
+		    GTK_EXPAND, GTK_EXPAND,
+		    0,          0);
+  gtk_size_group_add_widget (master_size_group, main_button);
+  gtk_size_group_add_widget (hgroup1, main_button);
+  gtk_size_group_add_widget (vgroup1, main_button);
+  gtk_widget_set_usize (GTK_BIN (main_button)->child, SIZE_GROUP_INITIAL_SIZE, SIZE_GROUP_INITIAL_SIZE);
+
+  button = gtk_button_new ();
+  gtk_table_attach (GTK_TABLE (table), button,
+		    1, 2,       0, 1,
+		    GTK_EXPAND, GTK_EXPAND,
+		    0,          0);
+  gtk_size_group_add_widget (vgroup1, button);
+  gtk_size_group_add_widget (vgroup2, button);
+
+  button = gtk_button_new ();
+  gtk_table_attach (GTK_TABLE (table), button,
+		    0, 1,       1, 2,
+		    GTK_EXPAND, GTK_EXPAND,
+		    0,          0);
+  gtk_size_group_add_widget (hgroup1, button);
+  gtk_size_group_add_widget (hgroup2, button);
+
+  button = gtk_button_new ();
+  gtk_table_attach (GTK_TABLE (table), button,
+		    1, 2,       1, 2,
+		    GTK_EXPAND, GTK_EXPAND,
+		    0,          0);
+  gtk_size_group_add_widget (hgroup2, button);
+  gtk_size_group_add_widget (vgroup2, button);
+
+  g_object_unref (G_OBJECT (hgroup1));
+  g_object_unref (G_OBJECT (hgroup2));
+  g_object_unref (G_OBJECT (vgroup1));
+  g_object_unref (G_OBJECT (vgroup2));
+  
+  hbox = gtk_hbox_new (FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox, FALSE, FALSE, 0);
+  
+  spin_button = gtk_spin_button_new_with_range (1, 100, 1);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
+  gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (spin_button), "value_changed",
+		      GTK_SIGNAL_FUNC (size_group_hsize_changed), main_button);
+
+  spin_button = gtk_spin_button_new_with_range (1, 100, 1);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
+  gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
+  gtk_signal_connect (GTK_OBJECT (spin_button), "value_changed",
+		      GTK_SIGNAL_FUNC (size_group_vsize_changed), main_button);
+
+  return window;
+}
+
+static void
+create_size_groups (void)
+{
+  static GtkWidget *window1 = NULL;
+  static GtkWidget *window2 = NULL;
+  static GtkSizeGroup *master_size_group;
+
+  if (!master_size_group)
+    master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+  
+  if (!window1)
+    {
+      window1 = create_size_group_window (master_size_group);
+
+      gtk_signal_connect (GTK_OBJECT (window1), "destroy",
+			  GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+			  &window1);
+    }
+
+  if (!window2)
+    {
+      window2 = create_size_group_window (master_size_group);
+
+      gtk_signal_connect (GTK_OBJECT (window2), "destroy",
+			  GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+			  &window2);
+    }
+
+  if (GTK_WIDGET_VISIBLE (window1) && GTK_WIDGET_VISIBLE (window2))
+    {
+      gtk_widget_destroy (window1);
+      gtk_widget_destroy (window2);
+    }
+  else
+    {
+      if (!GTK_WIDGET_VISIBLE (window1))
+	gtk_widget_show_all (window1);
+      if (!GTK_WIDGET_VISIBLE (window2))
+	gtk_widget_show_all (window2);
+    }
+}
+
+/*
  * GtkSpinButton
  */
 
@@ -10181,6 +10344,7 @@
       { "saved position", create_saved_position },
       { "scrolled windows", create_scrolled_windows },
       { "shapes", create_shapes },
+      { "size groups", create_size_groups },
       { "spinbutton", create_spins },
       { "statusbar", create_statusbar },
       { "styles", create_styles },


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]