diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index 66b8c37bfc..85198bb112 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -107,6 +107,13 @@ static gint gtk_container_expose (GtkWidget *widget, GdkEventExpose *event); static void gtk_container_map (GtkWidget *widget); static void gtk_container_unmap (GtkWidget *widget); +static void gtk_container_adjust_size_request (GtkWidget *widget, + GtkOrientation orientation, + gint for_size, + gint *minimum_size, + gint *natural_size); +static void gtk_container_adjust_size_allocation (GtkWidget *widget, + GtkAllocation *allocation); static gchar* gtk_container_child_default_composite_name (GtkContainer *container, GtkWidget *child); @@ -233,7 +240,10 @@ gtk_container_class_init (GtkContainerClass *class) widget_class->map = gtk_container_map; widget_class->unmap = gtk_container_unmap; widget_class->focus = gtk_container_focus; - + + widget_class->adjust_size_request = gtk_container_adjust_size_request; + widget_class->adjust_size_allocation = gtk_container_adjust_size_allocation; + class->add = gtk_container_add_unimplemented; class->remove = gtk_container_remove_unimplemented; class->check_resize = gtk_container_real_check_resize; @@ -1521,6 +1531,103 @@ gtk_container_resize_children (GtkContainer *container) gtk_widget_set_allocation (widget, &allocation); } +static void +gtk_container_adjust_size_request (GtkWidget *widget, + GtkOrientation orientation, + gint for_size, + gint *minimum_size, + gint *natural_size) +{ + GtkContainer *container; + + container = GTK_CONTAINER (widget); + + if (GTK_CONTAINER_GET_CLASS (widget)->handle_border_width) + { + int border_width; + + border_width = container->priv->border_width; + + *minimum_size += border_width * 2; + *natural_size += border_width * 2; + } + + /* chain up last so gtk_widget_set_size_request() values + * will have a chance to overwrite our border width. + */ + parent_class->adjust_size_request (widget, orientation, for_size, + minimum_size, natural_size); +} + +static void +gtk_container_adjust_size_allocation (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkContainer *container; + int border_width; + + container = GTK_CONTAINER (widget); + + parent_class->adjust_size_allocation (widget, allocation); + + if (!GTK_CONTAINER_GET_CLASS (widget)->handle_border_width) + return; + + border_width = container->priv->border_width; + + allocation->width -= border_width * 2; + allocation->height -= border_width * 2; + + /* If we get a pathological too-small allocation to hold + * even the border width, leave all allocation to the actual + * widget, and leave x,y unchanged. (GtkWidget's min size is + * 1x1 if you're wondering why <1 and not <0) + * + * As long as we have space, set x,y properly. + */ + + if (allocation->width < 1) + { + allocation->width += border_width * 2; + } + else + { + allocation->x += border_width; + } + + if (allocation->height < 1) + { + allocation->height += border_width * 2; + } + else + { + allocation->y += border_width; + } +} + +/** + * gtk_container_class_handle_border_width: + * @klass: the class struct of a #GtkContainer subclass + * + * Modifies a subclass of #GtkContainerClass to automatically add and + * remove the border-width setting on GtkContainer. This allows the + * subclass to ignore the border width in its size request and + * allocate methods. The intent is for a subclass to invoke this + * in its class_init function. + * + * gtk_container_class_handle_border_width() is necessary because it + * would break API too badly to make this behavior the default. So + * subclasses must "opt in" to the parent class handling border_width + * for them. + */ +void +gtk_container_class_handle_border_width (GtkContainerClass *klass) +{ + g_return_if_fail (GTK_IS_CONTAINER_CLASS (klass)); + + klass->handle_border_width = TRUE; +} + /** * gtk_container_forall: * @container: a #GtkContainer diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h index ff84ac8ff0..f4376759a6 100644 --- a/gtk/gtkcontainer.h +++ b/gtk/gtkcontainer.h @@ -62,6 +62,8 @@ struct _GtkContainerClass { GtkWidgetClass parent_class; + unsigned int handle_border_width : 1; + void (*add) (GtkContainer *container, GtkWidget *widget); void (*remove) (GtkContainer *container, @@ -194,6 +196,8 @@ void gtk_container_forall (GtkContainer *container, GtkCallback callback, gpointer callback_data); +void gtk_container_class_handle_border_width (GtkContainerClass *klass); + /* Non-public methods */ void _gtk_container_queue_resize (GtkContainer *container); void _gtk_container_clear_resize_widgets (GtkContainer *container);