1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
5 * Copyright (C) 1998 Shawn T. Amundson, James S. Mitchell, Michael L. Staiger
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
25 * This file contains modified code derived from Tk 8.0. Below is the header of
26 * the relevant file. The file 'license.terms' is included inline below.
30 * This file contains code to implement the "packer"
31 * geometry manager for Tk.
33 * Copyright (c) 1990-1994 The Regents of the University of California.
34 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
36 * See the file "license.terms" for information on usage and redistribution
37 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
39 * SCCS: @(#) tkPack.c 1.64 96/05/03 10:51:52
41 * The file license.terms is below. NOTE: THE FOLLOWING APPLIES ONLY TO
42 * PORTIONS DERIVED FROM TK 8.0. THE LICENSE FOR THIS FILE IS LGPL, AS
43 * STATED ABOVE AND ALLOWED BELOW.
44 -- BEGIN license.terms --
45 This software is copyrighted by the Regents of the University of
46 California, Sun Microsystems, Inc., and other parties. The following
47 terms apply to all files associated with the software unless explicitly
48 disclaimed in individual files.
50 The authors hereby grant permission to use, copy, modify, distribute,
51 and license this software and its documentation for any purpose, provided
52 that existing copyright notices are retained in all copies and that this
53 notice is included verbatim in any distributions. No written agreement,
54 license, or royalty fee is required for any of the authorized uses.
55 Modifications to this software may be copyrighted by their authors
56 and need not follow the licensing terms described here, provided that
57 the new terms are clearly indicated on the first page of each file where
60 IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
61 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
62 ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
63 DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
64 POSSIBILITY OF SUCH DAMAGE.
66 THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
67 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
68 FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
69 IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
70 NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
73 GOVERNMENT USE: If you are acquiring this software on behalf of the
74 U.S. government, the Government shall have only "Restricted Rights"
75 in the software and related documentation as defined in the Federal
76 Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
77 are acquiring the software on behalf of the Department of Defense, the
78 software shall be classified as "Commercial Computer Software" and the
79 Government shall have only "Restricted Rights" as defined in Clause
80 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
81 authors grant the U.S. Government and others acting in its behalf
82 permission to use and distribute the software in accordance with the
83 terms specified in this license.
84 -- END license.terms --
89 #include "gtkpacker.h"
109 CHILD_ARG_USE_DEFAULT,
110 CHILD_ARG_BORDER_WIDTH,
118 static void gtk_packer_class_init (GtkPackerClass *klass);
119 static void gtk_packer_init (GtkPacker *packer);
120 static void gtk_packer_map (GtkWidget *widget);
121 static void gtk_packer_unmap (GtkWidget *widget);
122 static void gtk_packer_draw (GtkWidget *widget,
124 static gint gtk_packer_expose (GtkWidget *widget,
125 GdkEventExpose *event);
126 static void gtk_packer_size_request (GtkWidget *widget,
127 GtkRequisition *requisition);
128 static void gtk_packer_size_allocate (GtkWidget *widget,
129 GtkAllocation *allocation);
130 static void gtk_packer_container_add (GtkContainer *container,
132 static void gtk_packer_remove (GtkContainer *container,
134 static void gtk_packer_forall (GtkContainer *container,
135 gboolean include_internals,
136 GtkCallback callback,
137 gpointer callback_data);
138 static void gtk_packer_set_arg (GtkObject *object,
141 static void gtk_packer_get_arg (GtkObject *object,
144 static void gtk_packer_get_child_arg (GtkContainer *container,
148 static void gtk_packer_set_child_arg (GtkContainer *container,
152 static GtkType gtk_packer_child_type (GtkContainer *container);
155 static GtkPackerClass *parent_class;
158 gtk_packer_get_type (void)
160 static GtkType packer_type = 0;
164 GtkTypeInfo packer_info =
168 sizeof (GtkPackerClass),
169 (GtkClassInitFunc) gtk_packer_class_init,
170 (GtkObjectInitFunc) gtk_packer_init,
171 /* reserved_1 */ NULL,
172 /* reserved_2 */ NULL,
173 (GtkClassInitFunc) NULL,
176 packer_type = gtk_type_unique (GTK_TYPE_CONTAINER, &packer_info);
183 gtk_packer_class_init (GtkPackerClass *klass)
185 GtkObjectClass *object_class;
186 GtkWidgetClass *widget_class;
187 GtkContainerClass *container_class;
189 object_class = (GtkObjectClass*) klass;
190 widget_class = (GtkWidgetClass*) klass;
191 container_class = (GtkContainerClass*) klass;
192 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
194 gtk_object_add_arg_type ("GtkPacker::spacing", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_SPACING);
195 gtk_object_add_arg_type ("GtkPacker::default_border_width", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_BORDER_WIDTH);
196 gtk_object_add_arg_type ("GtkPacker::default_pad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_PAD_X);
197 gtk_object_add_arg_type ("GtkPacker::default_pad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_PAD_Y);
198 gtk_object_add_arg_type ("GtkPacker::default_ipad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_IPAD_X);
199 gtk_object_add_arg_type ("GtkPacker::default_ipad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_IPAD_Y);
201 gtk_container_add_child_arg_type ("GtkPacker::side", GTK_TYPE_SIDE_TYPE, GTK_ARG_READWRITE, CHILD_ARG_SIDE);
202 gtk_container_add_child_arg_type ("GtkPacker::anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, CHILD_ARG_ANCHOR);
203 gtk_container_add_child_arg_type ("GtkPacker::expand", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_EXPAND);
204 gtk_container_add_child_arg_type ("GtkPacker::fill_x", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FILL_X);
205 gtk_container_add_child_arg_type ("GtkPacker::fill_y", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FILL_Y);
206 gtk_container_add_child_arg_type ("GtkPacker::use_default", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_USE_DEFAULT);
207 gtk_container_add_child_arg_type ("GtkPacker::border_width", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_BORDER_WIDTH);
208 gtk_container_add_child_arg_type ("GtkPacker::pad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_PAD_X);
209 gtk_container_add_child_arg_type ("GtkPacker::pad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_PAD_Y);
210 gtk_container_add_child_arg_type ("GtkPacker::ipad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_I_PAD_X);
211 gtk_container_add_child_arg_type ("GtkPacker::ipad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_I_PAD_Y);
212 gtk_container_add_child_arg_type ("GtkPacker::position", GTK_TYPE_LONG, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
214 object_class->set_arg = gtk_packer_set_arg;
215 object_class->get_arg = gtk_packer_get_arg;
217 widget_class->map = gtk_packer_map;
218 widget_class->unmap = gtk_packer_unmap;
219 widget_class->draw = gtk_packer_draw;
220 widget_class->expose_event = gtk_packer_expose;
222 widget_class->size_request = gtk_packer_size_request;
223 widget_class->size_allocate = gtk_packer_size_allocate;
225 container_class->add = gtk_packer_container_add;
226 container_class->remove = gtk_packer_remove;
227 container_class->forall = gtk_packer_forall;
228 container_class->child_type = gtk_packer_child_type;
229 container_class->get_child_arg = gtk_packer_get_child_arg;
230 container_class->set_child_arg = gtk_packer_set_child_arg;
234 gtk_packer_set_arg (GtkObject *object,
240 packer = GTK_PACKER (object);
245 gtk_packer_set_spacing (packer, GTK_VALUE_UINT (*arg));
247 case ARG_D_BORDER_WIDTH:
248 gtk_packer_set_default_border_width (packer, GTK_VALUE_UINT (*arg));
251 gtk_packer_set_default_pad (packer,
252 GTK_VALUE_UINT (*arg),
253 packer->default_pad_y);
256 gtk_packer_set_default_pad (packer,
257 packer->default_pad_x,
258 GTK_VALUE_UINT (*arg));
261 gtk_packer_set_default_ipad (packer,
262 GTK_VALUE_UINT (*arg),
263 packer->default_i_pad_y);
266 gtk_packer_set_default_ipad (packer,
267 packer->default_i_pad_x,
268 GTK_VALUE_UINT (*arg));
276 gtk_packer_get_arg (GtkObject *object,
282 packer = GTK_PACKER (object);
287 GTK_VALUE_UINT (*arg) = packer->spacing;
289 case ARG_D_BORDER_WIDTH:
290 GTK_VALUE_UINT (*arg) = packer->default_border_width;
293 GTK_VALUE_UINT (*arg) = packer->default_pad_x;
296 GTK_VALUE_UINT (*arg) = packer->default_pad_y;
299 GTK_VALUE_UINT (*arg) = packer->default_i_pad_x;
302 GTK_VALUE_UINT (*arg) = packer->default_i_pad_y;
305 arg->type = GTK_TYPE_INVALID;
311 gtk_packer_child_type (GtkContainer *container)
313 return GTK_TYPE_WIDGET;
317 gtk_packer_set_child_arg (GtkContainer *container,
323 GtkPackerChild *child_info = NULL;
325 packer = GTK_PACKER (container);
327 if (arg_id != CHILD_ARG_POSITION)
331 list = packer->children;
334 child_info = list->data;
335 if (child_info->widget == child)
347 child_info->side = GTK_VALUE_ENUM (*arg);
349 case CHILD_ARG_ANCHOR:
350 child_info->anchor = GTK_VALUE_ENUM (*arg);
352 case CHILD_ARG_EXPAND:
353 if (GTK_VALUE_BOOL (*arg))
354 child_info->options |= GTK_PACK_EXPAND;
356 child_info->options &= ~GTK_PACK_EXPAND;
358 case CHILD_ARG_FILL_X:
359 if (GTK_VALUE_BOOL (*arg))
360 child_info->options |= GTK_FILL_X;
362 child_info->options &= ~GTK_FILL_X;
364 case CHILD_ARG_FILL_Y:
365 if (GTK_VALUE_BOOL (*arg))
366 child_info->options |= GTK_FILL_Y;
368 child_info->options &= ~GTK_FILL_Y;
370 case CHILD_ARG_USE_DEFAULT:
371 child_info->use_default = (GTK_VALUE_BOOL (*arg) != 0);
373 case CHILD_ARG_BORDER_WIDTH:
374 if (!child_info->use_default)
375 child_info->border_width = GTK_VALUE_UINT (*arg);
377 case CHILD_ARG_PAD_X:
378 if (!child_info->use_default)
379 child_info->pad_x = GTK_VALUE_UINT (*arg);
381 case CHILD_ARG_PAD_Y:
382 if (!child_info->use_default)
383 child_info->pad_y = GTK_VALUE_UINT (*arg);
385 case CHILD_ARG_I_PAD_X:
386 if (!child_info->use_default)
387 child_info->i_pad_x = GTK_VALUE_UINT (*arg);
389 case CHILD_ARG_I_PAD_Y:
390 if (!child_info->use_default)
391 child_info->i_pad_y = GTK_VALUE_UINT (*arg);
393 case CHILD_ARG_POSITION:
394 gtk_packer_reorder_child (packer,
396 GTK_VALUE_LONG (*arg));
402 if (arg_id != CHILD_ARG_POSITION &&
403 GTK_WIDGET_VISIBLE (packer) &&
404 GTK_WIDGET_VISIBLE (child))
405 gtk_widget_queue_resize (child);
409 gtk_packer_get_child_arg (GtkContainer *container,
415 GtkPackerChild *child_info = NULL;
418 packer = GTK_PACKER (container);
420 if (arg_id != CHILD_ARG_POSITION)
422 list = packer->children;
425 child_info = list->data;
426 if (child_info->widget == child)
433 arg->type = GTK_TYPE_INVALID;
441 GTK_VALUE_ENUM (*arg) = child_info->side;
443 case CHILD_ARG_ANCHOR:
444 GTK_VALUE_ENUM (*arg) = child_info->anchor;
446 case CHILD_ARG_EXPAND:
447 GTK_VALUE_BOOL (*arg) = (child_info->options & GTK_PACK_EXPAND) != 0;
449 case CHILD_ARG_FILL_X:
450 GTK_VALUE_BOOL (*arg) = (child_info->options & GTK_FILL_X) != 0;
452 case CHILD_ARG_FILL_Y:
453 GTK_VALUE_BOOL (*arg) = (child_info->options & GTK_FILL_Y) != 0;
455 case CHILD_ARG_USE_DEFAULT:
456 GTK_VALUE_BOOL (*arg) = child_info->use_default;
458 case CHILD_ARG_BORDER_WIDTH:
459 GTK_VALUE_UINT (*arg) = child_info->border_width;
461 case CHILD_ARG_PAD_X:
462 GTK_VALUE_UINT (*arg) = child_info->pad_x;
464 case CHILD_ARG_PAD_Y:
465 GTK_VALUE_UINT (*arg) = child_info->pad_y;
467 case CHILD_ARG_I_PAD_X:
468 GTK_VALUE_UINT (*arg) = child_info->i_pad_x;
470 case CHILD_ARG_I_PAD_Y:
471 GTK_VALUE_UINT (*arg) = child_info->i_pad_y;
473 case CHILD_ARG_POSITION:
474 GTK_VALUE_LONG (*arg) = 0;
475 for (list = packer->children; list; list = list->next)
477 child_info = list->data;
478 if (child_info->widget == child)
480 GTK_VALUE_LONG (*arg)++;
483 GTK_VALUE_LONG (*arg) = -1;
486 arg->type = GTK_TYPE_INVALID;
492 gtk_packer_init (GtkPacker *packer)
494 GTK_WIDGET_SET_FLAGS (packer, GTK_NO_WINDOW);
496 packer->children = NULL;
501 gtk_packer_set_spacing (GtkPacker *packer,
504 g_return_if_fail (packer != NULL);
505 g_return_if_fail (GTK_IS_PACKER (packer));
507 if (spacing != packer->spacing)
509 packer->spacing = spacing;
510 gtk_widget_queue_resize (GTK_WIDGET (packer));
515 gtk_packer_new (void)
517 return GTK_WIDGET (gtk_type_new (GTK_TYPE_PACKER));
521 redo_defaults_children (GtkPacker *packer)
524 GtkPackerChild *child;
526 list = g_list_first(packer->children);
531 if (child->use_default)
533 child->border_width = packer->default_border_width;
534 child->pad_x = packer->default_pad_x;
535 child->pad_y = packer->default_pad_y;
536 child->i_pad_x = packer->default_i_pad_x;
537 child->i_pad_y = packer->default_i_pad_y;
538 gtk_widget_queue_resize (GTK_WIDGET (child->widget));
540 list = g_list_next(list);
545 gtk_packer_set_default_border_width (GtkPacker *packer,
548 g_return_if_fail (packer != NULL);
549 g_return_if_fail (GTK_IS_PACKER (packer));
551 if (packer->default_border_width != border)
553 packer->default_border_width = border;;
554 redo_defaults_children (packer);
558 gtk_packer_set_default_pad (GtkPacker *packer,
562 g_return_if_fail (packer != NULL);
563 g_return_if_fail (GTK_IS_PACKER (packer));
565 if (packer->default_pad_x != pad_x ||
566 packer->default_pad_y != pad_y)
568 packer->default_pad_x = pad_x;
569 packer->default_pad_y = pad_y;
570 redo_defaults_children (packer);
575 gtk_packer_set_default_ipad (GtkPacker *packer,
579 g_return_if_fail (packer != NULL);
580 g_return_if_fail (GTK_IS_PACKER (packer));
582 if (packer->default_i_pad_x != i_pad_x ||
583 packer->default_i_pad_y != i_pad_y) {
585 packer->default_i_pad_x = i_pad_x;
586 packer->default_i_pad_y = i_pad_y;
587 redo_defaults_children (packer);
592 gtk_packer_container_add (GtkContainer *packer, GtkWidget *child)
594 gtk_packer_add_defaults(GTK_PACKER(packer), child,
595 GTK_SIDE_TOP, GTK_ANCHOR_CENTER, 0);
599 gtk_packer_add_defaults (GtkPacker *packer,
602 GtkAnchorType anchor,
603 GtkPackerOptions options)
605 GtkPackerChild *pchild;
607 g_return_if_fail (packer != NULL);
608 g_return_if_fail (GTK_IS_PACKER (packer));
609 g_return_if_fail (child != NULL);
610 g_return_if_fail (GTK_IS_WIDGET (child));
612 pchild = (GtkPackerChild*) g_malloc(sizeof(GtkPackerChild));
614 pchild->widget = child;
616 pchild->options = options;
617 pchild->anchor = anchor;
619 pchild->use_default = 1;
621 pchild->border_width = packer->default_border_width;
622 pchild->pad_x = packer->default_pad_x;
623 pchild->pad_y = packer->default_pad_y;
624 pchild->i_pad_x = packer->default_i_pad_x;
625 pchild->i_pad_y = packer->default_i_pad_y;
627 packer->children = g_list_append(packer->children, (gpointer) pchild);
629 gtk_widget_set_parent (child, GTK_WIDGET (packer));
631 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (packer)))
633 if (GTK_WIDGET_REALIZED (GTK_WIDGET (packer)) &&
634 !GTK_WIDGET_REALIZED (child))
635 gtk_widget_realize (child);
637 if (GTK_WIDGET_MAPPED (GTK_WIDGET (packer)) &&
638 !GTK_WIDGET_MAPPED (child))
639 gtk_widget_map (child);
642 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
643 gtk_widget_queue_resize (child);
648 gtk_packer_add (GtkPacker *packer,
651 GtkAnchorType anchor,
652 GtkPackerOptions options,
659 GtkPackerChild *pchild;
661 g_return_if_fail (packer != NULL);
662 g_return_if_fail (GTK_IS_PACKER (packer));
663 g_return_if_fail (child != NULL);
664 g_return_if_fail (GTK_IS_WIDGET (child));
666 pchild = (GtkPackerChild*) g_malloc(sizeof(GtkPackerChild));
668 pchild->widget = child;
670 pchild->options = options;
671 pchild->anchor = anchor;
673 pchild->use_default = 0;
675 pchild->border_width = border_width;
676 pchild->pad_x = pad_x;
677 pchild->pad_y = pad_y;
678 pchild->i_pad_x = i_pad_x;
679 pchild->i_pad_y = i_pad_y;
681 packer->children = g_list_append(packer->children, (gpointer) pchild);
683 gtk_widget_set_parent (child, GTK_WIDGET (packer));
685 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (packer)))
687 if (GTK_WIDGET_REALIZED (GTK_WIDGET (packer)) &&
688 !GTK_WIDGET_REALIZED (child))
689 gtk_widget_realize (child);
691 if (GTK_WIDGET_MAPPED (GTK_WIDGET (packer)) &&
692 !GTK_WIDGET_MAPPED (child))
693 gtk_widget_map (child);
696 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
697 gtk_widget_queue_resize (child);
702 gtk_packer_configure (GtkPacker *packer,
705 GtkAnchorType anchor,
706 GtkPackerOptions options,
714 GtkPackerChild *pchild;
716 g_return_if_fail (packer != NULL);
717 g_return_if_fail (GTK_IS_PACKER (packer));
718 g_return_if_fail (child != NULL);
720 list = g_list_first(packer->children);
723 pchild = (GtkPackerChild*) list->data;
724 if (pchild->widget == child)
727 pchild->anchor = anchor;
728 pchild->options = options;
730 pchild->use_default = 0;
732 pchild->border_width = border_width;
733 pchild->pad_x = pad_x;
734 pchild->pad_y = pad_y;
735 pchild->i_pad_x = i_pad_x;
736 pchild->i_pad_y = i_pad_y;
738 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
739 gtk_widget_queue_resize (child);
742 list = g_list_next(list);
745 g_warning ("gtk_packer_configure(): couldn't find child `%s' amongst the packer's children", gtk_type_name (GTK_OBJECT_TYPE (child)));
750 gtk_packer_reorder_child (GtkPacker *packer,
756 g_return_if_fail (packer != NULL);
757 g_return_if_fail (GTK_IS_PACKER (packer));
758 g_return_if_fail (child != NULL);
760 list = packer->children;
763 GtkPackerChild *child_info;
765 child_info = list->data;
766 if (child_info->widget == child)
772 if (list && packer->children->next)
777 list->next->prev = list->prev;
779 list->prev->next = list->next;
781 packer->children = list->next;
783 tmp_list = packer->children;
784 while (position && tmp_list->next)
787 tmp_list = tmp_list->next;
792 tmp_list->next = list;
793 list->prev = tmp_list;
799 tmp_list->prev->next = list;
801 packer->children = list;
802 list->prev = tmp_list->prev;
803 tmp_list->prev = list;
804 list->next = tmp_list;
807 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
808 gtk_widget_queue_resize (child);
813 gtk_packer_remove (GtkContainer *container,
817 GtkPackerChild *child;
821 g_return_if_fail (container != NULL);
822 g_return_if_fail (widget != NULL);
824 packer = GTK_PACKER (container);
826 children = g_list_first(packer->children);
829 child = children->data;
831 if (child->widget == widget)
833 visible = GTK_WIDGET_VISIBLE (widget);
834 gtk_widget_unparent (widget);
836 packer->children = g_list_remove_link (packer->children, children);
837 g_list_free (children);
840 if (visible && GTK_WIDGET_VISIBLE (container))
841 gtk_widget_queue_resize (GTK_WIDGET (container));
846 children = g_list_next(children);
851 gtk_packer_map (GtkWidget *widget)
854 GtkPackerChild *child;
857 g_return_if_fail (widget != NULL);
858 g_return_if_fail (GTK_IS_PACKER (widget));
860 packer = GTK_PACKER (widget);
861 GTK_WIDGET_SET_FLAGS (packer, GTK_MAPPED);
863 children = g_list_first(packer->children);
864 while (children != NULL)
866 child = children->data;
867 children = g_list_next(children);
869 if (GTK_WIDGET_VISIBLE (child->widget) &&
870 !GTK_WIDGET_MAPPED (child->widget))
871 gtk_widget_map (child->widget);
876 gtk_packer_unmap (GtkWidget *widget)
879 GtkPackerChild *child;
882 g_return_if_fail (widget != NULL);
883 g_return_if_fail (GTK_IS_PACKER (widget));
885 packer = GTK_PACKER (widget);
886 GTK_WIDGET_UNSET_FLAGS (packer, GTK_MAPPED);
888 children = g_list_first(packer->children);
891 child = children->data;
892 children = g_list_next(children);
894 if (GTK_WIDGET_VISIBLE (child->widget) &&
895 GTK_WIDGET_MAPPED (child->widget))
896 gtk_widget_unmap (child->widget);
901 gtk_packer_draw (GtkWidget *widget, GdkRectangle *area)
904 GtkPackerChild *child;
905 GdkRectangle child_area;
908 g_return_if_fail (widget != NULL);
909 g_return_if_fail (GTK_IS_PACKER (widget));
911 if (GTK_WIDGET_DRAWABLE (widget))
913 packer = GTK_PACKER (widget);
915 children = g_list_first(packer->children);
916 while (children != NULL)
918 child = children->data;
919 children = g_list_next(children);
921 if (gtk_widget_intersect (child->widget, area, &child_area))
922 gtk_widget_draw (child->widget, &child_area);
929 gtk_packer_expose (GtkWidget *widget, GdkEventExpose *event)
932 GtkPackerChild *child;
933 GdkEventExpose child_event;
936 g_return_val_if_fail (widget != NULL, FALSE);
937 g_return_val_if_fail (GTK_IS_PACKER (widget), FALSE);
938 g_return_val_if_fail (event != NULL, FALSE);
940 if (GTK_WIDGET_DRAWABLE (widget))
942 packer = GTK_PACKER (widget);
944 child_event = *event;
946 children = g_list_first(packer->children);
949 child = children->data;
950 children = g_list_next(children);
952 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
953 gtk_widget_intersect (child->widget, &event->area, &child_event.area))
954 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
962 gtk_packer_size_request (GtkWidget *widget, GtkRequisition *requisition)
965 GtkContainer *container;
966 GtkPackerChild *child;
968 gint nvis_vert_children;
969 gint nvis_horz_children;
971 gint maxWidth, maxHeight;
973 g_return_if_fail (widget != NULL);
974 g_return_if_fail (GTK_IS_PACKER (widget));
975 g_return_if_fail (requisition != NULL);
977 packer = GTK_PACKER (widget);
978 container = GTK_CONTAINER (widget);
980 requisition->width = 0;
981 requisition->height = 0;
982 nvis_vert_children = 0;
983 nvis_horz_children = 0;
985 width = height = maxWidth = maxHeight = 0;
987 children = g_list_first(packer->children);
988 while (children != NULL)
990 child = children->data;
992 if (GTK_WIDGET_VISIBLE (child->widget))
994 gtk_widget_size_request (child->widget, &child->widget->requisition);
996 if((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
998 maxWidth = MAX (maxWidth,
999 (child->widget->requisition.width +
1000 2 * child->border_width +
1001 child->pad_x + child->i_pad_x +
1003 height += (child->widget->requisition.height +
1004 2 * child->border_width +
1005 child->pad_y + child->i_pad_y);
1009 maxHeight = MAX (maxHeight,
1010 (child->widget->requisition.height +
1011 2 * child->border_width +
1012 child->pad_y + child->i_pad_y +
1014 width += (child->widget->requisition.width +
1015 2 * child->border_width +
1016 child->pad_x + child->i_pad_x);
1020 children = g_list_next(children);
1023 requisition->width = MAX (maxWidth, width) + 2 * container->border_width;
1024 requisition->height = MAX (maxHeight, height) + 2 * container->border_width;
1028 YExpansion (GList *children, gint cavityHeight)
1031 GtkPackerChild *child;
1033 gint numExpand, minExpand, curExpand;
1036 minExpand = cavityHeight;
1040 while (list != NULL)
1043 widget = child->widget;
1044 childHeight = (widget->requisition.height +
1045 2 * child->border_width +
1048 if ((child->side == GTK_SIDE_LEFT) || (child->side == GTK_SIDE_RIGHT))
1050 curExpand = (cavityHeight - childHeight)/numExpand;
1051 minExpand = MIN(minExpand, curExpand);
1055 cavityHeight -= childHeight;
1056 if (child->options & GTK_PACK_EXPAND)
1059 list = g_list_next(list);
1061 curExpand = cavityHeight/numExpand;
1062 if (curExpand < minExpand)
1063 minExpand = curExpand;
1064 return (minExpand < 0) ? 0 : minExpand;
1068 XExpansion (GList *children, gint cavityWidth)
1071 GtkPackerChild *child;
1073 gint numExpand, minExpand, curExpand;
1076 minExpand = cavityWidth;
1080 while (list != NULL)
1083 widget = child->widget;
1084 childWidth = (widget->requisition.width +
1085 2 * child->border_width +
1089 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1091 curExpand = (cavityWidth - childWidth)/numExpand;
1092 minExpand = MIN(minExpand, curExpand);
1096 cavityWidth -= childWidth;
1097 if (child->options & GTK_PACK_EXPAND)
1100 list = g_list_next(list);
1102 curExpand = cavityWidth/numExpand;
1103 if (curExpand < minExpand)
1104 minExpand = curExpand;
1105 return (minExpand < 0) ? 0 : minExpand;
1109 gtk_packer_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
1112 GtkContainer *container;
1113 GtkAllocation child_allocation;
1115 GtkPackerChild *child;
1116 gint cavityX, cavityY;
1117 gint cavityWidth, cavityHeight;
1118 gint width, height, x, y;
1119 gint frameHeight, frameWidth, frameX, frameY;
1120 gint borderX, borderY;
1122 g_return_if_fail (widget != NULL);
1123 g_return_if_fail (GTK_IS_PACKER (widget));
1124 g_return_if_fail (allocation != NULL);
1126 packer = GTK_PACKER (widget);
1127 container = GTK_CONTAINER (widget);
1131 widget->allocation = *allocation;
1133 cavityX = widget->allocation.x + container->border_width;
1134 cavityY = widget->allocation.y + container->border_width;
1135 cavityWidth = widget->allocation.width - 2 * container->border_width;
1136 cavityHeight = widget->allocation.height - 2 * container->border_width;
1138 list = g_list_first (packer->children);
1139 while (list != NULL)
1143 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1145 frameWidth = cavityWidth;
1146 frameHeight = (child->widget->requisition.height +
1147 2 * child->border_width +
1150 if (child->options & GTK_PACK_EXPAND)
1151 frameHeight += YExpansion(list, cavityHeight);
1152 cavityHeight -= frameHeight;
1153 if (cavityHeight < 0)
1155 frameHeight += cavityHeight;
1159 if (child->side == GTK_SIDE_TOP)
1162 cavityY += frameHeight;
1166 frameY = cavityY + cavityHeight;
1171 frameHeight = cavityHeight;
1172 frameWidth = (child->widget->requisition.width +
1173 2 * child->border_width +
1176 if (child->options & GTK_PACK_EXPAND)
1177 frameWidth += XExpansion(list, cavityWidth);
1178 cavityWidth -= frameWidth;
1179 if (cavityWidth < 0) {
1180 frameWidth += cavityWidth;
1184 if (child->side == GTK_SIDE_LEFT)
1187 cavityX += frameWidth;
1191 frameX = cavityX + cavityWidth;
1195 borderX = child->pad_x + 2 * child->border_width;
1196 borderY = child->pad_y + 2 * child->border_width;
1198 width = (child->widget->requisition.width +
1199 2 * child->border_width +
1201 if ((child->options & GTK_FILL_X) || (width > (frameWidth - borderX)))
1202 width = frameWidth - borderX;
1204 height = (child->widget->requisition.height +
1205 2 * child->border_width +
1207 if ((child->options & GTK_FILL_Y) || (height > (frameHeight - borderY)))
1208 height = frameHeight - borderY;
1212 switch (child->anchor)
1215 x = frameX + (frameWidth - width)/2;
1216 y = frameY + borderY;
1219 x = frameX + frameWidth - width - borderX;
1220 y = frameY + borderY;
1223 x = frameX + frameWidth - width - borderX;
1224 y = frameY + (frameHeight - height)/2;
1227 x = frameX + frameWidth - width - borderX;
1228 y = frameY + frameHeight - height - borderY;
1231 x = frameX + (frameWidth - width)/2;
1232 y = frameY + frameHeight - height - borderY;
1235 x = frameX + borderX;
1236 y = frameY + frameHeight - height - borderY;
1239 x = frameX + borderX;
1240 y = frameY + (frameHeight - height)/2;
1243 x = frameX + borderX;
1244 y = frameY + borderY;
1246 case GTK_ANCHOR_CENTER:
1247 x = frameX + (frameWidth - width)/2;
1248 y = frameY + (frameHeight - height)/2;
1251 g_warning ("gtk_packer_size_allocate(): bad anchor type: %d", child->anchor);
1254 if (width <= 0 || height <= 0)
1256 gtk_widget_unmap(child->widget);
1260 child_allocation.x = x;
1261 child_allocation.y = y;
1262 child_allocation.width = width;
1263 child_allocation.height = height;
1264 gtk_widget_size_allocate (child->widget, &child_allocation);
1266 if (GTK_WIDGET_MAPPED (widget) &&
1267 !(GTK_WIDGET_MAPPED (child->widget)))
1268 gtk_widget_map(child->widget);
1271 list = g_list_next(list);
1276 gtk_packer_forall (GtkContainer *container,
1277 gboolean include_internals,
1278 GtkCallback callback,
1279 gpointer callback_data)
1282 GtkPackerChild *child;
1285 g_return_if_fail (container != NULL);
1286 g_return_if_fail (GTK_IS_PACKER (container));
1287 g_return_if_fail (callback != NULL);
1289 packer = GTK_PACKER (container);
1291 children = g_list_first (packer->children);
1292 while (children != NULL)
1294 child = children->data;
1295 children = g_list_next(children);
1297 (* callback) (child->widget, callback_data);