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.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
44 static void gtk_box_class_init (GtkBoxClass *klass);
45 static void gtk_box_init (GtkBox *box);
46 static void gtk_box_get_arg (GtkObject *object,
49 static void gtk_box_set_arg (GtkObject *object,
52 static void gtk_box_map (GtkWidget *widget);
53 static void gtk_box_unmap (GtkWidget *widget);
54 static void gtk_box_draw (GtkWidget *widget,
56 static gint gtk_box_expose (GtkWidget *widget,
57 GdkEventExpose *event);
58 static void gtk_box_add (GtkContainer *container,
60 static void gtk_box_remove (GtkContainer *container,
62 static void gtk_box_forall (GtkContainer *container,
63 gboolean include_internals,
65 gpointer callback_data);
66 static void gtk_box_set_child_arg (GtkContainer *container,
70 static void gtk_box_get_child_arg (GtkContainer *container,
74 static GtkType gtk_box_child_type (GtkContainer *container);
77 static GtkContainerClass *parent_class = NULL;
81 gtk_box_get_type (void)
83 static GtkType box_type = 0;
87 static const GtkTypeInfo box_info =
92 (GtkClassInitFunc) gtk_box_class_init,
93 (GtkObjectInitFunc) gtk_box_init,
94 /* reserved_1 */ NULL,
95 /* reserved_2 */ NULL,
96 (GtkClassInitFunc) NULL,
99 box_type = gtk_type_unique (GTK_TYPE_CONTAINER, &box_info);
106 gtk_box_class_init (GtkBoxClass *class)
108 GtkObjectClass *object_class;
109 GtkWidgetClass *widget_class;
110 GtkContainerClass *container_class;
112 object_class = (GtkObjectClass*) class;
113 widget_class = (GtkWidgetClass*) class;
114 container_class = (GtkContainerClass*) class;
116 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
118 gtk_object_add_arg_type ("GtkBox::spacing", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_SPACING);
119 gtk_object_add_arg_type ("GtkBox::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
120 gtk_container_add_child_arg_type ("GtkBox::expand", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_EXPAND);
121 gtk_container_add_child_arg_type ("GtkBox::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FILL);
122 gtk_container_add_child_arg_type ("GtkBox::padding", GTK_TYPE_ULONG, GTK_ARG_READWRITE, CHILD_ARG_PADDING);
123 gtk_container_add_child_arg_type ("GtkBox::pack_type", GTK_TYPE_PACK_TYPE, GTK_ARG_READWRITE, CHILD_ARG_PACK_TYPE);
124 gtk_container_add_child_arg_type ("GtkBox::position", GTK_TYPE_LONG, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
126 object_class->set_arg = gtk_box_set_arg;
127 object_class->get_arg = gtk_box_get_arg;
129 widget_class->map = gtk_box_map;
130 widget_class->unmap = gtk_box_unmap;
131 widget_class->draw = gtk_box_draw;
132 widget_class->expose_event = gtk_box_expose;
134 container_class->add = gtk_box_add;
135 container_class->remove = gtk_box_remove;
136 container_class->forall = gtk_box_forall;
137 container_class->child_type = gtk_box_child_type;
138 container_class->set_child_arg = gtk_box_set_child_arg;
139 container_class->get_child_arg = gtk_box_get_child_arg;
143 gtk_box_init (GtkBox *box)
145 GTK_WIDGET_SET_FLAGS (box, GTK_NO_WINDOW);
147 box->children = NULL;
149 box->homogeneous = FALSE;
153 gtk_box_set_arg (GtkObject *object,
159 box = GTK_BOX (object);
164 gtk_box_set_spacing (box, GTK_VALUE_INT (*arg));
166 case ARG_HOMOGENEOUS:
167 gtk_box_set_homogeneous (box, GTK_VALUE_BOOL (*arg));
175 gtk_box_get_arg (GtkObject *object,
181 box = GTK_BOX (object);
186 GTK_VALUE_INT (*arg) = box->spacing;
188 case ARG_HOMOGENEOUS:
189 GTK_VALUE_BOOL (*arg) = box->homogeneous;
192 arg->type = GTK_TYPE_INVALID;
198 gtk_box_child_type (GtkContainer *container)
200 return GTK_TYPE_WIDGET;
204 gtk_box_set_child_arg (GtkContainer *container,
212 GtkPackType pack_type = 0;
214 if (arg_id != CHILD_ARG_POSITION)
215 gtk_box_query_child_packing (GTK_BOX (container),
224 case CHILD_ARG_EXPAND:
225 gtk_box_set_child_packing (GTK_BOX (container),
227 GTK_VALUE_BOOL (*arg),
233 gtk_box_set_child_packing (GTK_BOX (container),
236 GTK_VALUE_BOOL (*arg),
240 case CHILD_ARG_PADDING:
241 gtk_box_set_child_packing (GTK_BOX (container),
245 GTK_VALUE_ULONG (*arg),
248 case CHILD_ARG_PACK_TYPE:
249 gtk_box_set_child_packing (GTK_BOX (container),
254 GTK_VALUE_ENUM (*arg));
256 case CHILD_ARG_POSITION:
257 gtk_box_reorder_child (GTK_BOX (container),
259 GTK_VALUE_LONG (*arg));
267 gtk_box_get_child_arg (GtkContainer *container,
275 GtkPackType pack_type = 0;
278 if (arg_id != CHILD_ARG_POSITION)
279 gtk_box_query_child_packing (GTK_BOX (container),
288 case CHILD_ARG_EXPAND:
289 GTK_VALUE_BOOL (*arg) = expand;
292 GTK_VALUE_BOOL (*arg) = fill;
294 case CHILD_ARG_PADDING:
295 GTK_VALUE_ULONG (*arg) = padding;
297 case CHILD_ARG_PACK_TYPE:
298 GTK_VALUE_ENUM (*arg) = pack_type;
300 case CHILD_ARG_POSITION:
301 GTK_VALUE_LONG (*arg) = 0;
302 for (list = GTK_BOX (container)->children; list; list = list->next)
304 GtkBoxChild *child_entry;
306 child_entry = list->data;
307 if (child_entry->widget == child)
309 GTK_VALUE_LONG (*arg)++;
312 GTK_VALUE_LONG (*arg) = -1;
315 arg->type = GTK_TYPE_INVALID;
321 gtk_box_pack_start (GtkBox *box,
327 GtkBoxChild *child_info;
329 g_return_if_fail (box != NULL);
330 g_return_if_fail (GTK_IS_BOX (box));
331 g_return_if_fail (child != NULL);
332 g_return_if_fail (child->parent == NULL);
334 child_info = g_new (GtkBoxChild, 1);
335 child_info->widget = child;
336 child_info->padding = padding;
337 child_info->expand = expand ? TRUE : FALSE;
338 child_info->fill = fill ? TRUE : FALSE;
339 child_info->pack = GTK_PACK_START;
341 box->children = g_list_append (box->children, child_info);
343 gtk_widget_set_parent (child, GTK_WIDGET (box));
345 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (box)))
347 if (GTK_WIDGET_REALIZED (GTK_WIDGET (box)) &&
348 !GTK_WIDGET_REALIZED (child))
349 gtk_widget_realize (child);
351 if (GTK_WIDGET_MAPPED (GTK_WIDGET (box)) &&
352 !GTK_WIDGET_MAPPED (child))
353 gtk_widget_map (child);
356 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
357 gtk_widget_queue_resize (child);
361 gtk_box_pack_end (GtkBox *box,
367 GtkBoxChild *child_info;
369 g_return_if_fail (box != NULL);
370 g_return_if_fail (GTK_IS_BOX (box));
371 g_return_if_fail (child != NULL);
372 g_return_if_fail (child->parent == NULL);
374 child_info = g_new (GtkBoxChild, 1);
375 child_info->widget = child;
376 child_info->padding = padding;
377 child_info->expand = expand ? TRUE : FALSE;
378 child_info->fill = fill ? TRUE : FALSE;
379 child_info->pack = GTK_PACK_END;
381 box->children = g_list_append (box->children, child_info);
383 gtk_widget_set_parent (child, GTK_WIDGET (box));
385 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (box)))
387 if (GTK_WIDGET_REALIZED (GTK_WIDGET (box)) &&
388 !GTK_WIDGET_REALIZED (child))
389 gtk_widget_realize (child);
391 if (GTK_WIDGET_MAPPED (GTK_WIDGET (box)) &&
392 !GTK_WIDGET_MAPPED (child))
393 gtk_widget_map (child);
396 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
397 gtk_widget_queue_resize (child);
401 gtk_box_pack_start_defaults (GtkBox *box,
404 g_return_if_fail (box != NULL);
405 g_return_if_fail (GTK_IS_BOX (box));
406 g_return_if_fail (child != NULL);
408 gtk_box_pack_start (box, child, TRUE, TRUE, 0);
412 gtk_box_pack_end_defaults (GtkBox *box,
415 g_return_if_fail (box != NULL);
416 g_return_if_fail (GTK_IS_BOX (box));
417 g_return_if_fail (child != NULL);
419 gtk_box_pack_end (box, child, TRUE, TRUE, 0);
423 gtk_box_set_homogeneous (GtkBox *box,
424 gboolean homogeneous)
426 g_return_if_fail (box != NULL);
427 g_return_if_fail (GTK_IS_BOX (box));
429 if ((homogeneous ? TRUE : FALSE) != box->homogeneous)
431 box->homogeneous = homogeneous ? TRUE : FALSE;
432 gtk_widget_queue_resize (GTK_WIDGET (box));
437 gtk_box_set_spacing (GtkBox *box,
440 g_return_if_fail (box != NULL);
441 g_return_if_fail (GTK_IS_BOX (box));
443 if (spacing != box->spacing)
445 box->spacing = spacing;
446 gtk_widget_queue_resize (GTK_WIDGET (box));
451 gtk_box_reorder_child (GtkBox *box,
457 g_return_if_fail (box != NULL);
458 g_return_if_fail (GTK_IS_BOX (box));
459 g_return_if_fail (child != NULL);
461 list = box->children;
464 GtkBoxChild *child_info;
466 child_info = list->data;
467 if (child_info->widget == child)
473 if (list && box->children->next)
478 list->next->prev = list->prev;
480 list->prev->next = list->next;
482 box->children = list->next;
484 tmp_list = box->children;
485 while (position && tmp_list->next)
488 tmp_list = tmp_list->next;
493 tmp_list->next = list;
494 list->prev = tmp_list;
500 tmp_list->prev->next = list;
502 box->children = list;
503 list->prev = tmp_list->prev;
504 tmp_list->prev = list;
505 list->next = tmp_list;
508 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
509 gtk_widget_queue_resize (child);
514 gtk_box_query_child_packing (GtkBox *box,
519 GtkPackType *pack_type)
522 GtkBoxChild *child_info = NULL;
524 g_return_if_fail (box != NULL);
525 g_return_if_fail (GTK_IS_BOX (box));
526 g_return_if_fail (child != NULL);
528 list = box->children;
531 child_info = list->data;
532 if (child_info->widget == child)
541 *expand = child_info->expand;
543 *fill = child_info->fill;
545 *padding = child_info->padding;
547 *pack_type = child_info->pack;
552 gtk_box_set_child_packing (GtkBox *box,
557 GtkPackType pack_type)
560 GtkBoxChild *child_info = NULL;
562 g_return_if_fail (box != NULL);
563 g_return_if_fail (GTK_IS_BOX (box));
564 g_return_if_fail (child != NULL);
566 list = box->children;
569 child_info = list->data;
570 if (child_info->widget == child)
578 child_info->expand = expand != FALSE;
579 child_info->fill = fill != FALSE;
580 child_info->padding = padding;
581 if (pack_type == GTK_PACK_END)
582 child_info->pack = GTK_PACK_END;
584 child_info->pack = GTK_PACK_START;
586 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
587 gtk_widget_queue_resize (child);
592 gtk_box_map (GtkWidget *widget)
598 g_return_if_fail (widget != NULL);
599 g_return_if_fail (GTK_IS_BOX (widget));
601 box = GTK_BOX (widget);
602 GTK_WIDGET_SET_FLAGS (box, GTK_MAPPED);
604 children = box->children;
607 child = children->data;
608 children = children->next;
610 if (GTK_WIDGET_VISIBLE (child->widget) &&
611 !GTK_WIDGET_MAPPED (child->widget))
612 gtk_widget_map (child->widget);
617 gtk_box_unmap (GtkWidget *widget)
623 g_return_if_fail (widget != NULL);
624 g_return_if_fail (GTK_IS_BOX (widget));
626 box = GTK_BOX (widget);
627 GTK_WIDGET_UNSET_FLAGS (box, GTK_MAPPED);
629 children = box->children;
632 child = children->data;
633 children = children->next;
635 if (GTK_WIDGET_VISIBLE (child->widget) &&
636 GTK_WIDGET_MAPPED (child->widget))
637 gtk_widget_unmap (child->widget);
642 gtk_box_draw (GtkWidget *widget,
647 GdkRectangle child_area;
650 g_return_if_fail (widget != NULL);
651 g_return_if_fail (GTK_IS_BOX (widget));
653 if (GTK_WIDGET_DRAWABLE (widget))
655 box = GTK_BOX (widget);
657 children = box->children;
660 child = children->data;
661 children = children->next;
663 if (gtk_widget_intersect (child->widget, area, &child_area))
664 gtk_widget_draw (child->widget, &child_area);
670 gtk_box_expose (GtkWidget *widget,
671 GdkEventExpose *event)
675 GdkEventExpose child_event;
678 g_return_val_if_fail (widget != NULL, FALSE);
679 g_return_val_if_fail (GTK_IS_BOX (widget), FALSE);
680 g_return_val_if_fail (event != NULL, FALSE);
682 if (GTK_WIDGET_DRAWABLE (widget))
684 box = GTK_BOX (widget);
686 child_event = *event;
688 children = box->children;
691 child = children->data;
692 children = children->next;
694 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
695 gtk_widget_intersect (child->widget, &event->area, &child_event.area))
696 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
704 gtk_box_add (GtkContainer *container,
707 g_return_if_fail (container != NULL);
708 g_return_if_fail (GTK_IS_BOX (container));
709 g_return_if_fail (widget != NULL);
711 gtk_box_pack_start_defaults (GTK_BOX (container), widget);
715 gtk_box_remove (GtkContainer *container,
722 g_return_if_fail (container != NULL);
723 g_return_if_fail (GTK_IS_BOX (container));
724 g_return_if_fail (widget != NULL);
726 box = GTK_BOX (container);
728 children = box->children;
731 child = children->data;
733 if (child->widget == widget)
735 gboolean was_visible;
737 was_visible = GTK_WIDGET_VISIBLE (widget);
738 gtk_widget_unparent (widget);
740 box->children = g_list_remove_link (box->children, children);
741 g_list_free (children);
744 /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
745 * since that's what is needed by toplevels.
748 gtk_widget_queue_resize (GTK_WIDGET (container));
753 children = children->next;
758 gtk_box_forall (GtkContainer *container,
759 gboolean include_internals,
760 GtkCallback callback,
761 gpointer callback_data)
767 g_return_if_fail (container != NULL);
768 g_return_if_fail (GTK_IS_BOX (container));
769 g_return_if_fail (callback != NULL);
771 box = GTK_BOX (container);
773 children = box->children;
776 child = children->data;
777 children = children->next;
779 if (child->pack == GTK_PACK_START)
780 (* callback) (child->widget, callback_data);
783 children = g_list_last (box->children);
786 child = children->data;
787 children = children->prev;
789 if (child->pack == GTK_PACK_END)
790 (* callback) (child->widget, callback_data);