1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
36 static void gtk_box_class_init (GtkBoxClass *klass);
37 static void gtk_box_init (GtkBox *box);
38 static void gtk_box_get_arg (GtkObject *object,
41 static void gtk_box_set_arg (GtkObject *object,
44 static void gtk_box_map (GtkWidget *widget);
45 static void gtk_box_unmap (GtkWidget *widget);
46 static void gtk_box_draw (GtkWidget *widget,
48 static gint gtk_box_expose (GtkWidget *widget,
49 GdkEventExpose *event);
50 static void gtk_box_add (GtkContainer *container,
52 static void gtk_box_remove (GtkContainer *container,
54 static void gtk_box_forall (GtkContainer *container,
55 gboolean include_internals,
57 gpointer callback_data);
58 static void gtk_box_set_child_arg (GtkContainer *container,
62 static void gtk_box_get_child_arg (GtkContainer *container,
66 static GtkType gtk_box_child_type (GtkContainer *container);
69 static GtkContainerClass *parent_class = NULL;
73 gtk_box_get_type (void)
75 static GtkType box_type = 0;
79 GtkTypeInfo box_info =
84 (GtkClassInitFunc) gtk_box_class_init,
85 (GtkObjectInitFunc) gtk_box_init,
86 /* reserved_1 */ NULL,
87 /* reserved_2 */ NULL,
88 (GtkClassInitFunc) NULL,
91 box_type = gtk_type_unique (GTK_TYPE_CONTAINER, &box_info);
98 gtk_box_class_init (GtkBoxClass *class)
100 GtkObjectClass *object_class;
101 GtkWidgetClass *widget_class;
102 GtkContainerClass *container_class;
104 object_class = (GtkObjectClass*) class;
105 widget_class = (GtkWidgetClass*) class;
106 container_class = (GtkContainerClass*) class;
108 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
110 gtk_object_add_arg_type ("GtkBox::spacing", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_SPACING);
111 gtk_object_add_arg_type ("GtkBox::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
112 gtk_container_add_child_arg_type ("GtkBox::expand", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_EXPAND);
113 gtk_container_add_child_arg_type ("GtkBox::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FILL);
114 gtk_container_add_child_arg_type ("GtkBox::padding", GTK_TYPE_ULONG, GTK_ARG_READWRITE, CHILD_ARG_PADDING);
115 gtk_container_add_child_arg_type ("GtkBox::pack_type", GTK_TYPE_PACK_TYPE, GTK_ARG_READWRITE, CHILD_ARG_PACK_TYPE);
116 gtk_container_add_child_arg_type ("GtkBox::position", GTK_TYPE_LONG, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
118 object_class->set_arg = gtk_box_set_arg;
119 object_class->get_arg = gtk_box_get_arg;
121 widget_class->map = gtk_box_map;
122 widget_class->unmap = gtk_box_unmap;
123 widget_class->draw = gtk_box_draw;
124 widget_class->expose_event = gtk_box_expose;
126 container_class->add = gtk_box_add;
127 container_class->remove = gtk_box_remove;
128 container_class->forall = gtk_box_forall;
129 container_class->child_type = gtk_box_child_type;
130 container_class->set_child_arg = gtk_box_set_child_arg;
131 container_class->get_child_arg = gtk_box_get_child_arg;
135 gtk_box_init (GtkBox *box)
137 GTK_WIDGET_SET_FLAGS (box, GTK_NO_WINDOW | GTK_BASIC);
139 box->children = NULL;
141 box->homogeneous = FALSE;
145 gtk_box_set_arg (GtkObject *object,
151 box = GTK_BOX (object);
156 gtk_box_set_spacing (box, GTK_VALUE_INT (*arg));
158 case ARG_HOMOGENEOUS:
159 gtk_box_set_homogeneous (box, GTK_VALUE_BOOL (*arg));
167 gtk_box_get_arg (GtkObject *object,
173 box = GTK_BOX (object);
178 GTK_VALUE_INT (*arg) = box->spacing;
180 case ARG_HOMOGENEOUS:
181 GTK_VALUE_BOOL (*arg) = box->homogeneous;
184 arg->type = GTK_TYPE_INVALID;
190 gtk_box_child_type (GtkContainer *container)
192 return GTK_TYPE_WIDGET;
196 gtk_box_set_child_arg (GtkContainer *container,
204 GtkPackType pack_type = 0;
206 if (arg_id != CHILD_ARG_POSITION)
207 gtk_box_query_child_packing (GTK_BOX (container),
216 case CHILD_ARG_EXPAND:
217 gtk_box_set_child_packing (GTK_BOX (container),
219 GTK_VALUE_BOOL (*arg),
225 gtk_box_set_child_packing (GTK_BOX (container),
228 GTK_VALUE_BOOL (*arg),
232 case CHILD_ARG_PADDING:
233 gtk_box_set_child_packing (GTK_BOX (container),
237 GTK_VALUE_ULONG (*arg),
240 case CHILD_ARG_PACK_TYPE:
241 gtk_box_set_child_packing (GTK_BOX (container),
246 GTK_VALUE_ENUM (*arg));
248 case CHILD_ARG_POSITION:
249 gtk_box_reorder_child (GTK_BOX (container),
251 GTK_VALUE_LONG (*arg));
259 gtk_box_get_child_arg (GtkContainer *container,
267 GtkPackType pack_type = 0;
270 if (arg_id != CHILD_ARG_POSITION)
271 gtk_box_query_child_packing (GTK_BOX (container),
280 case CHILD_ARG_EXPAND:
281 GTK_VALUE_BOOL (*arg) = expand;
284 GTK_VALUE_BOOL (*arg) = fill;
286 case CHILD_ARG_PADDING:
287 GTK_VALUE_ULONG (*arg) = padding;
289 case CHILD_ARG_PACK_TYPE:
290 GTK_VALUE_ENUM (*arg) = pack_type;
292 case CHILD_ARG_POSITION:
293 GTK_VALUE_LONG (*arg) = 0;
294 for (list = GTK_BOX (container)->children; list; list = list->next)
296 GtkBoxChild *child_entry;
298 child_entry = list->data;
299 if (child_entry->widget == child)
301 GTK_VALUE_LONG (*arg)++;
304 GTK_VALUE_LONG (*arg) = -1;
307 arg->type = GTK_TYPE_INVALID;
313 gtk_box_pack_start (GtkBox *box,
319 GtkBoxChild *child_info;
321 g_return_if_fail (box != NULL);
322 g_return_if_fail (GTK_IS_BOX (box));
323 g_return_if_fail (child != NULL);
324 g_return_if_fail (child->parent == NULL);
326 child_info = g_new (GtkBoxChild, 1);
327 child_info->widget = child;
328 child_info->padding = padding;
329 child_info->expand = expand ? TRUE : FALSE;
330 child_info->fill = fill ? TRUE : FALSE;
331 child_info->pack = GTK_PACK_START;
333 box->children = g_list_append (box->children, child_info);
335 gtk_widget_set_parent (child, GTK_WIDGET (box));
337 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (box)))
339 if (GTK_WIDGET_REALIZED (GTK_WIDGET (box)) &&
340 !GTK_WIDGET_REALIZED (child))
341 gtk_widget_realize (child);
343 if (GTK_WIDGET_MAPPED (GTK_WIDGET (box)) &&
344 !GTK_WIDGET_MAPPED (child))
345 gtk_widget_map (child);
348 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
349 gtk_widget_queue_resize (child);
353 gtk_box_pack_end (GtkBox *box,
359 GtkBoxChild *child_info;
361 g_return_if_fail (box != NULL);
362 g_return_if_fail (GTK_IS_BOX (box));
363 g_return_if_fail (child != NULL);
364 g_return_if_fail (child->parent == NULL);
366 child_info = g_new (GtkBoxChild, 1);
367 child_info->widget = child;
368 child_info->padding = padding;
369 child_info->expand = expand ? TRUE : FALSE;
370 child_info->fill = fill ? TRUE : FALSE;
371 child_info->pack = GTK_PACK_END;
373 box->children = g_list_append (box->children, child_info);
375 gtk_widget_set_parent (child, GTK_WIDGET (box));
377 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (box)))
379 if (GTK_WIDGET_REALIZED (GTK_WIDGET (box)) &&
380 !GTK_WIDGET_REALIZED (child))
381 gtk_widget_realize (child);
383 if (GTK_WIDGET_MAPPED (GTK_WIDGET (box)) &&
384 !GTK_WIDGET_MAPPED (child))
385 gtk_widget_map (child);
388 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
389 gtk_widget_queue_resize (child);
393 gtk_box_pack_start_defaults (GtkBox *box,
396 g_return_if_fail (box != NULL);
397 g_return_if_fail (GTK_IS_BOX (box));
398 g_return_if_fail (child != NULL);
400 gtk_box_pack_start (box, child, TRUE, TRUE, 0);
404 gtk_box_pack_end_defaults (GtkBox *box,
407 g_return_if_fail (box != NULL);
408 g_return_if_fail (GTK_IS_BOX (box));
409 g_return_if_fail (child != NULL);
411 gtk_box_pack_end (box, child, TRUE, TRUE, 0);
415 gtk_box_set_homogeneous (GtkBox *box,
416 gboolean homogeneous)
418 g_return_if_fail (box != NULL);
419 g_return_if_fail (GTK_IS_BOX (box));
421 if ((homogeneous ? TRUE : FALSE) != box->homogeneous)
423 box->homogeneous = homogeneous ? TRUE : FALSE;
424 gtk_widget_queue_resize (GTK_WIDGET (box));
429 gtk_box_set_spacing (GtkBox *box,
432 g_return_if_fail (box != NULL);
433 g_return_if_fail (GTK_IS_BOX (box));
435 if (spacing != box->spacing)
437 box->spacing = spacing;
438 gtk_widget_queue_resize (GTK_WIDGET (box));
443 gtk_box_reorder_child (GtkBox *box,
449 g_return_if_fail (box != NULL);
450 g_return_if_fail (GTK_IS_BOX (box));
451 g_return_if_fail (child != NULL);
453 list = box->children;
456 GtkBoxChild *child_info;
458 child_info = list->data;
459 if (child_info->widget == child)
465 if (list && box->children->next)
470 list->next->prev = list->prev;
472 list->prev->next = list->next;
474 box->children = list->next;
476 tmp_list = box->children;
477 while (position && tmp_list->next)
480 tmp_list = tmp_list->next;
485 tmp_list->next = list;
486 list->prev = tmp_list;
492 tmp_list->prev->next = list;
494 box->children = list;
495 list->prev = tmp_list->prev;
496 tmp_list->prev = list;
497 list->next = tmp_list;
500 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
501 gtk_widget_queue_resize (child);
506 gtk_box_query_child_packing (GtkBox *box,
511 GtkPackType *pack_type)
514 GtkBoxChild *child_info;
516 g_return_if_fail (box != NULL);
517 g_return_if_fail (GTK_IS_BOX (box));
518 g_return_if_fail (child != NULL);
520 list = box->children;
523 child_info = list->data;
524 if (child_info->widget == child)
533 *expand = child_info->expand;
535 *fill = child_info->fill;
537 *padding = child_info->padding;
539 *pack_type = child_info->pack;
544 gtk_box_set_child_packing (GtkBox *box,
549 GtkPackType pack_type)
552 GtkBoxChild *child_info;
554 g_return_if_fail (box != NULL);
555 g_return_if_fail (GTK_IS_BOX (box));
556 g_return_if_fail (child != NULL);
558 list = box->children;
561 child_info = list->data;
562 if (child_info->widget == child)
570 child_info->expand = expand != FALSE;
571 child_info->fill = fill != FALSE;
572 child_info->padding = padding;
573 if (pack_type == GTK_PACK_END)
574 child_info->pack = GTK_PACK_END;
576 child_info->pack = GTK_PACK_START;
578 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
579 gtk_widget_queue_resize (child);
584 gtk_box_map (GtkWidget *widget)
590 g_return_if_fail (widget != NULL);
591 g_return_if_fail (GTK_IS_BOX (widget));
593 box = GTK_BOX (widget);
594 GTK_WIDGET_SET_FLAGS (box, GTK_MAPPED);
596 children = box->children;
599 child = children->data;
600 children = children->next;
602 if (GTK_WIDGET_VISIBLE (child->widget) &&
603 !GTK_WIDGET_MAPPED (child->widget))
604 gtk_widget_map (child->widget);
609 gtk_box_unmap (GtkWidget *widget)
615 g_return_if_fail (widget != NULL);
616 g_return_if_fail (GTK_IS_BOX (widget));
618 box = GTK_BOX (widget);
619 GTK_WIDGET_UNSET_FLAGS (box, GTK_MAPPED);
621 children = box->children;
624 child = children->data;
625 children = children->next;
627 if (GTK_WIDGET_VISIBLE (child->widget) &&
628 GTK_WIDGET_MAPPED (child->widget))
629 gtk_widget_unmap (child->widget);
634 gtk_box_draw (GtkWidget *widget,
639 GdkRectangle child_area;
642 g_return_if_fail (widget != NULL);
643 g_return_if_fail (GTK_IS_BOX (widget));
645 if (GTK_WIDGET_DRAWABLE (widget))
647 box = GTK_BOX (widget);
649 children = box->children;
652 child = children->data;
653 children = children->next;
655 if (gtk_widget_intersect (child->widget, area, &child_area))
656 gtk_widget_draw (child->widget, &child_area);
662 gtk_box_expose (GtkWidget *widget,
663 GdkEventExpose *event)
667 GdkEventExpose child_event;
670 g_return_val_if_fail (widget != NULL, FALSE);
671 g_return_val_if_fail (GTK_IS_BOX (widget), FALSE);
672 g_return_val_if_fail (event != NULL, FALSE);
674 if (GTK_WIDGET_DRAWABLE (widget))
676 box = GTK_BOX (widget);
678 child_event = *event;
680 children = box->children;
683 child = children->data;
684 children = children->next;
686 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
687 gtk_widget_intersect (child->widget, &event->area, &child_event.area))
688 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
696 gtk_box_add (GtkContainer *container,
699 g_return_if_fail (container != NULL);
700 g_return_if_fail (GTK_IS_BOX (container));
701 g_return_if_fail (widget != NULL);
703 gtk_box_pack_start_defaults (GTK_BOX (container), widget);
707 gtk_box_remove (GtkContainer *container,
714 g_return_if_fail (container != NULL);
715 g_return_if_fail (GTK_IS_BOX (container));
716 g_return_if_fail (widget != NULL);
718 box = GTK_BOX (container);
720 children = box->children;
723 child = children->data;
725 if (child->widget == widget)
727 gboolean was_visible;
729 was_visible = GTK_WIDGET_VISIBLE (widget);
730 gtk_widget_unparent (widget);
732 box->children = g_list_remove_link (box->children, children);
733 g_list_free (children);
736 /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
737 * since that's what is needed by toplevels.
740 gtk_widget_queue_resize (GTK_WIDGET (container));
745 children = children->next;
750 gtk_box_forall (GtkContainer *container,
751 gboolean include_internals,
752 GtkCallback callback,
753 gpointer callback_data)
759 g_return_if_fail (container != NULL);
760 g_return_if_fail (GTK_IS_BOX (container));
761 g_return_if_fail (callback != NULL);
763 box = GTK_BOX (container);
765 children = box->children;
768 child = children->data;
769 children = children->next;
771 if (child->pack == GTK_PACK_START)
772 (* callback) (child->widget, callback_data);
775 children = g_list_last (box->children);
778 child = children->data;
779 children = children->prev;
781 if (child->pack == GTK_PACK_END)
782 (* callback) (child->widget, callback_data);