summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2001-05-18 18:30:59 +0000
committerOwen Taylor <otaylor@src.gnome.org>2001-05-18 18:30:59 +0000
commit50512ddcd2b2cb156d4a4e13a9f6ac21aae30ddf (patch)
tree1e34849888cd77ec1cb4c71c4ecacd48d4fcb1b4 /gtk
parent02d5f41c9ea5116977c68fef42a984c180c04d84 (diff)
downloadgdk-pixbuf-50512ddcd2b2cb156d4a4e13a9f6ac21aae30ddf.tar.gz
Remove reallocate-redraws property. This is something that only a widget
Fri May 18 14:25:20 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkcontainer.c: Remove reallocate-redraws property. This is something that only a widget writer would ever want to change. * gtk/gtksignal.c: Handle G_SIGNAL_TYPE_STATIC_SCOPE for gtk_signal_emit_by_name(). * gtk/gtkviewport.c: Fix some warnings. * gtk/gtkwidget.c gtk/gtksizegroup.c: Add "size group" facility allowing the requisitions of multiple widgets to be grouped together. * tests/testgtk.c: Add GtkSizeGroup test * demos/gtk-demo/sizegroup.c: Add GtkSizeGroup demo. * demos/gtk-demo/main.c demos/gtk-demo/pixbufs.c: Fix some warnings. * configure.in: Switch to using AM_GLIB_GNU_GETTEXT.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkcontainer.c34
-rw-r--r--gtk/gtksignal.c5
-rw-r--r--gtk/gtksizegroup.c679
-rw-r--r--gtk/gtksizegroup.h100
-rw-r--r--gtk/gtkviewport.c4
-rw-r--r--gtk/gtkwidget.c32
8 files changed, 799 insertions, 58 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 1eaa30036..50d2261f3 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -142,6 +142,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtkseparator.h \
gtksettings.h \
gtksignal.h \
+ gtksizegroup.h \
gtksocket.h \
gtkspinbutton.h \
gtkstyle.h \
@@ -301,6 +302,7 @@ gtk_c_sources = @STRIP_BEGIN@ \
gtkseparator.c \
gtksettings.c \
gtksignal.c \
+ gtksizegroup.c \
gtkspinbutton.c \
gtkstock.c \
gtkstyle.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 5c50ce22c..534d61d60 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -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>
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 3c80e9a69..2029e7f16 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -49,7 +49,6 @@ enum {
PROP_BORDER_WIDTH,
PROP_RESIZE_MODE,
PROP_CHILD,
- PROP_REALLOCATE_REDRAWS
};
typedef struct _GtkChildArgInfo GtkChildArgInfo;
@@ -200,13 +199,7 @@ gtk_container_class_init (GtkContainerClass *class)
_("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 @@ gtk_container_set_property (GObject *object,
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 @@ gtk_container_get_property (GObject *object,
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 @@ gtk_container_set_reallocate_redraws (GtkContainer *container,
{
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 @@ gtk_container_resize_children (GtkContainer *container)
/* 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 @@ gtk_container_resize_children (GtkContainer *container)
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 @@ gtk_container_resize_children (GtkContainer *container)
}
/* 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)
diff --git a/gtk/gtksignal.c b/gtk/gtksignal.c
index 54a6c14f3..b7ed0fb1f 100644
--- a/gtk/gtksignal.c
+++ b/gtk/gtksignal.c
@@ -321,11 +321,12 @@ gtk_signal_emitv (GtkObject *object,
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;
}
}
diff --git a/gtk/gtksizegroup.c b/gtk/gtksizegroup.c
new file mode 100644
index 000000000..ccd710068
--- /dev/null
+++ b/gtk/gtksizegroup.c
@@ -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, TRUE);
+}
+
+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);
+}
diff --git a/gtk/gtksizegroup.h b/gtk/gtksizegroup.h
new file mode 100644
index 000000000..32d3ec21a
--- /dev/null
+++ b/gtk/gtksizegroup.h
@@ -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__ */
diff --git a/gtk/gtkviewport.c b/gtk/gtkviewport.c
index c370e9d2b..34dd90c80 100644
--- a/gtk/gtkviewport.c
+++ b/gtk/gtkviewport.c
@@ -203,10 +203,10 @@ gtk_viewport_get_property (GObject *object,
switch (prop_id)
{
case PROP_HADJUSTMENT:
- g_value_set_object (value, viewport->hadjustment);
+ g_value_set_object (value, G_OBJECT (viewport->hadjustment));
break;
case PROP_VADJUSTMENT:
- g_value_set_object (value, viewport->vadjustment);
+ g_value_set_object (value, G_OBJECT (viewport->vadjustment));
break;
case PROP_SHADOW_TYPE:
g_value_set_enum (value, viewport->shadow_type);
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 345b430db..dd09db96c 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -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 @@ gtk_widget_queue_resize (GtkWidget *widget)
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 @@ gtk_widget_size_request (GtkWidget *widget,
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 @@ void
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);
}
/**