diff options
Diffstat (limited to 'gtk/gtkcontainer.c')
-rw-r--r-- | gtk/gtkcontainer.c | 273 |
1 files changed, 175 insertions, 98 deletions
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index 8b4db22d6..7b03cb639 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -26,7 +26,7 @@ enum { ADD, REMOVE, - NEED_RESIZE, + CHECK_RESIZE, FOREACH, FOCUS, SET_FOCUS_CHILD, @@ -35,8 +35,6 @@ enum { enum { ARG_0, ARG_BORDER_WIDTH, - ARG_AUTO_RESIZE, - ARG_BLOCK_RESIZE, ARG_CHILD }; @@ -78,10 +76,6 @@ static void gtk_container_marshal_signal_3 (GtkObject *object, GtkSignalFunc func, gpointer func_data, GtkArg *args); -static void gtk_container_marshal_signal_4 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args); static void gtk_container_class_init (GtkContainerClass *klass); @@ -97,7 +91,7 @@ static void gtk_container_add_unimplemented (GtkContainer *container, GtkWidget *widget); static void gtk_container_remove_unimplemented (GtkContainer *container, GtkWidget *widget); -static gint gtk_container_real_need_resize (GtkContainer *container); +static void gtk_container_real_check_resize (GtkContainer *container); static gint gtk_container_real_focus (GtkContainer *container, GtkDirectionType direction); static void gtk_container_real_set_focus_child (GtkContainer *container, @@ -174,8 +168,6 @@ gtk_container_class_init (GtkContainerClass *class) hadjustment_key_id = gtk_object_data_force_id (hadjustment_key); gtk_object_add_arg_type ("GtkContainer::border_width", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_BORDER_WIDTH); - gtk_object_add_arg_type ("GtkContainer::auto_resize", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_AUTO_RESIZE); - gtk_object_add_arg_type ("GtkContainer::block_resize", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_BLOCK_RESIZE); gtk_object_add_arg_type ("GtkContainer::child", GTK_TYPE_WIDGET, GTK_ARG_WRITABLE, ARG_CHILD); container_signals[ADD] = @@ -194,13 +186,13 @@ gtk_container_class_init (GtkContainerClass *class) gtk_container_marshal_signal_1, GTK_TYPE_NONE, 1, GTK_TYPE_WIDGET); - container_signals[NEED_RESIZE] = - gtk_signal_new ("need_resize", + container_signals[CHECK_RESIZE] = + gtk_signal_new ("check_resize", GTK_RUN_LAST, object_class->type, - GTK_SIGNAL_OFFSET (GtkContainerClass, need_resize), - gtk_container_marshal_signal_4, - GTK_TYPE_BOOL, 0); + GTK_SIGNAL_OFFSET (GtkContainerClass, check_resize), + gtk_signal_default_marshaller, + GTK_TYPE_NONE, 0); container_signals[FOREACH] = gtk_signal_new ("foreach", GTK_RUN_FIRST, @@ -238,7 +230,7 @@ gtk_container_class_init (GtkContainerClass *class) class->add = gtk_container_add_unimplemented; class->remove = gtk_container_remove_unimplemented; - class->need_resize = gtk_container_real_need_resize; + class->check_resize = gtk_container_real_check_resize; class->foreach = NULL; class->focus = gtk_container_real_focus; class->set_focus_child = gtk_container_real_set_focus_child; @@ -671,31 +663,24 @@ gtk_container_init (GtkContainer *container) { container->focus_child = NULL; container->border_width = 0; - container->auto_resize = TRUE; container->need_resize = FALSE; - container->block_resize = FALSE; + container->resize_mode = GTK_RESIZE_PARENT; container->resize_widgets = NULL; } static void gtk_container_destroy (GtkObject *object) { - GSList *node; - + GtkContainer *container; + g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_CONTAINER (object)); - for (node = GTK_CONTAINER (object)->resize_widgets; node; node = node->next) - { - GtkWidget *child; - - child = (GtkWidget*) node->data; - GTK_PRIVATE_UNSET_FLAG (child, GTK_RESIZE_NEEDED); - } - g_slist_free (GTK_CONTAINER (object)->resize_widgets); - GTK_CONTAINER (object)->resize_widgets = NULL; + container = GTK_CONTAINER (object); - gtk_container_foreach (GTK_CONTAINER (object), + gtk_container_clear_resize_widgets (container); + + gtk_container_foreach (container, (GtkCallback) gtk_widget_destroy, NULL); if (GTK_OBJECT_CLASS (parent_class)->destroy) @@ -712,18 +697,6 @@ gtk_container_set_arg (GtkContainer *container, case ARG_BORDER_WIDTH: gtk_container_border_width (container, GTK_VALUE_ULONG (*arg)); break; - case ARG_AUTO_RESIZE: - if (GTK_VALUE_BOOL (*arg)) - gtk_container_enable_resize (container); - else - gtk_container_disable_resize (container); - break; - case ARG_BLOCK_RESIZE: - if (GTK_VALUE_BOOL (*arg)) - gtk_container_block_resize (container); - else - gtk_container_unblock_resize (container); - break; case ARG_CHILD: gtk_container_add (container, GTK_WIDGET (GTK_VALUE_OBJECT (*arg))); break; @@ -742,12 +715,6 @@ gtk_container_get_arg (GtkContainer *container, case ARG_BORDER_WIDTH: GTK_VALUE_ULONG (*arg) = container->border_width; break; - case ARG_AUTO_RESIZE: - GTK_VALUE_BOOL (*arg) = container->auto_resize; - break; - case ARG_BLOCK_RESIZE: - GTK_VALUE_BOOL (*arg) = container->block_resize; - break; default: arg->type = GTK_TYPE_INVALID; break; @@ -799,65 +766,202 @@ gtk_container_remove (GtkContainer *container, void gtk_container_disable_resize (GtkContainer *container) { + g_warning ("gtk_container_disable_resize does nothing!"); +} + +void +gtk_container_enable_resize (GtkContainer *container) +{ + g_warning ("gtk_container_enable_resize does nothing!"); +} + +void +gtk_container_block_resize (GtkContainer *container) +{ g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); - container->auto_resize = FALSE; } void -gtk_container_enable_resize (GtkContainer *container) +gtk_container_unblock_resize (GtkContainer *container) { g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); + +} + +void +gtk_container_clear_resize_widgets (GtkContainer *container) +{ + GSList *node; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_CONTAINER (container)); - container->auto_resize = TRUE; - if (container->need_resize) + node = container->resize_widgets; + + while (node) { - container->need_resize = FALSE; - gtk_widget_queue_resize (GTK_WIDGET (container)); + GtkWidget *widget = node->data; + + GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED); + node = node->next; } + + g_slist_free (container->resize_widgets); + container->resize_widgets = NULL; } void -gtk_container_block_resize (GtkContainer *container) +gtk_container_set_resize_mode (GtkContainer *container, + GtkResizeMode resize_mode) { g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); + g_return_if_fail (!(GTK_WIDGET_TOPLEVEL (container) && + resize_mode == GTK_RESIZE_PARENT)); + + container->resize_mode = resize_mode; - container->block_resize = TRUE; + if (container->resize_widgets != NULL) + { + if (resize_mode == GTK_RESIZE_IMMEDIATE) + gtk_container_check_resize (container); + else if (resize_mode == GTK_RESIZE_PARENT) + { + gtk_widget_queue_resize (GTK_WIDGET (container)); + container->resize_widgets = NULL; + } + } } void -gtk_container_unblock_resize (GtkContainer *container) +gtk_container_check_resize (GtkContainer *container) { g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); + + gtk_signal_emit (GTK_OBJECT (container), container_signals[CHECK_RESIZE]); +} + +gint +gtk_container_need_resize (GtkContainer *container) +{ + gtk_container_check_resize (container); + return TRUE; +} + +static void +gtk_container_real_check_resize (GtkContainer *container) +{ + GtkWidget *widget; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_CONTAINER (container)); + + widget = GTK_WIDGET (container); + + gtk_widget_size_request (widget, &widget->requisition); - container->block_resize = FALSE; + if ((widget->requisition.width > widget->allocation.width) || + (widget->requisition.height > widget->allocation.height)) + { + gtk_container_clear_resize_widgets (container); + gtk_widget_queue_resize (widget); + } + else + { + gtk_container_resize_children (container); + } } -gint -gtk_container_need_resize (GtkContainer *container) +/* The window hasn't changed size but one of its children + * queued a resize request. Which means that the allocation + * is not sufficient for the requisition of some child. + * We've already performed a size request at this point, + * so we simply need to run through the list of resize + * widgets and reallocate their sizes appropriately. We + * make the optimization of not performing reallocation + * for a widget who also has a parent in the resize widgets + * list. GTK_RESIZE_NEEDED is used for flagging those + * parents inside this function. + */ +void +gtk_container_resize_children (GtkContainer *container) { - gint return_val; + GtkWidget *widget; + GSList *resize_widgets; + GSList *resize_containers; + GSList *node; - g_return_val_if_fail (container != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE); + resize_widgets = container->resize_widgets; + container->resize_widgets = NULL; - return_val = FALSE; + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_CONTAINER (container)); + + for (node = resize_widgets; node; node = node->next) + { + widget = node->data; + + GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED); + + while (widget && widget->parent && + ((widget->allocation.width < widget->requisition.width) || + (widget->allocation.height < widget->requisition.height))) + widget = widget->parent; + + GTK_PRIVATE_SET_FLAG (widget, GTK_RESIZE_NEEDED); + node->data = widget; + } + + resize_containers = NULL; - if (!container->block_resize) + for (node = resize_widgets; node; node = node->next) { - if (container->auto_resize) - gtk_signal_emit (GTK_OBJECT (container), - container_signals[NEED_RESIZE], - &return_val); + GtkWidget *resize_container; + + widget = node->data; + + if (!GTK_WIDGET_RESIZE_NEEDED (widget)) + continue; + + resize_container = widget->parent; + + if (resize_container) + { + GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED); + widget = resize_container->parent; + + while (widget) + { + if (GTK_WIDGET_RESIZE_NEEDED (widget)) + { + GTK_PRIVATE_UNSET_FLAG (resize_container, GTK_RESIZE_NEEDED); + resize_container = widget; + } + widget = widget->parent; + } + } else - container->need_resize = TRUE; + resize_container = widget; + + if (!g_slist_find (resize_containers, resize_container)) + resize_containers = g_slist_prepend (resize_containers, + resize_container); } + g_slist_free (resize_widgets); - return return_val; + for (node = resize_containers; node; node = node->next) + { + widget = node->data; + + GTK_PRIVATE_UNSET_FLAG (widget, GTK_RESIZE_NEEDED); + gtk_widget_size_allocate (widget, &widget->allocation); + gtk_widget_queue_draw (widget); + } + g_slist_free (resize_containers); } void @@ -1082,33 +1186,6 @@ gtk_container_marshal_signal_3 (GtkObject *object, *return_val = (* rfunc) (object, GTK_VALUE_ENUM(args[0]), func_data); } -static void -gtk_container_marshal_signal_4 (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args) -{ - GtkContainerSignal4 rfunc; - gint *return_val; - - rfunc = (GtkContainerSignal4) func; - return_val = GTK_RETLOC_BOOL (args[0]); - - *return_val = (* rfunc) (object, func_data); -} - -static gint -gtk_container_real_need_resize (GtkContainer *container) -{ - g_return_val_if_fail (container != NULL, FALSE); - g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE); - - if (GTK_WIDGET_VISIBLE (container) && container->widget.parent) - return gtk_container_need_resize (GTK_CONTAINER (container->widget.parent)); - - return FALSE; -} - static gint gtk_container_real_focus (GtkContainer *container, GtkDirectionType direction) |