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 static const 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_set_child_packing (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 ("couldn't find child `%s' amongst the packer's children", gtk_type_name (GTK_OBJECT_TYPE (child)));
749 gtk_packer_reorder_child (GtkPacker *packer,
755 g_return_if_fail (packer != NULL);
756 g_return_if_fail (GTK_IS_PACKER (packer));
757 g_return_if_fail (child != NULL);
759 list = packer->children;
762 GtkPackerChild *child_info;
764 child_info = list->data;
765 if (child_info->widget == child)
771 if (list && packer->children->next)
776 list->next->prev = list->prev;
778 list->prev->next = list->next;
780 packer->children = list->next;
782 tmp_list = packer->children;
783 while (position && tmp_list->next)
786 tmp_list = tmp_list->next;
791 tmp_list->next = list;
792 list->prev = tmp_list;
798 tmp_list->prev->next = list;
800 packer->children = list;
801 list->prev = tmp_list->prev;
802 tmp_list->prev = list;
803 list->next = tmp_list;
806 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
807 gtk_widget_queue_resize (child);
812 gtk_packer_remove (GtkContainer *container,
816 GtkPackerChild *child;
820 g_return_if_fail (container != NULL);
821 g_return_if_fail (widget != NULL);
823 packer = GTK_PACKER (container);
825 children = g_list_first(packer->children);
828 child = children->data;
830 if (child->widget == widget)
832 visible = GTK_WIDGET_VISIBLE (widget);
833 gtk_widget_unparent (widget);
835 packer->children = g_list_remove_link (packer->children, children);
836 g_list_free (children);
839 if (visible && GTK_WIDGET_VISIBLE (container))
840 gtk_widget_queue_resize (GTK_WIDGET (container));
845 children = g_list_next(children);
850 gtk_packer_map (GtkWidget *widget)
853 GtkPackerChild *child;
856 g_return_if_fail (widget != NULL);
857 g_return_if_fail (GTK_IS_PACKER (widget));
859 packer = GTK_PACKER (widget);
860 GTK_WIDGET_SET_FLAGS (packer, GTK_MAPPED);
862 children = g_list_first(packer->children);
863 while (children != NULL)
865 child = children->data;
866 children = g_list_next(children);
868 if (GTK_WIDGET_VISIBLE (child->widget) &&
869 !GTK_WIDGET_MAPPED (child->widget))
870 gtk_widget_map (child->widget);
875 gtk_packer_unmap (GtkWidget *widget)
878 GtkPackerChild *child;
881 g_return_if_fail (widget != NULL);
882 g_return_if_fail (GTK_IS_PACKER (widget));
884 packer = GTK_PACKER (widget);
885 GTK_WIDGET_UNSET_FLAGS (packer, GTK_MAPPED);
887 children = g_list_first(packer->children);
890 child = children->data;
891 children = g_list_next(children);
893 if (GTK_WIDGET_VISIBLE (child->widget) &&
894 GTK_WIDGET_MAPPED (child->widget))
895 gtk_widget_unmap (child->widget);
900 gtk_packer_draw (GtkWidget *widget,
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,
930 GdkEventExpose *event)
933 GtkPackerChild *child;
934 GdkEventExpose child_event;
937 g_return_val_if_fail (widget != NULL, FALSE);
938 g_return_val_if_fail (GTK_IS_PACKER (widget), FALSE);
939 g_return_val_if_fail (event != NULL, FALSE);
941 if (GTK_WIDGET_DRAWABLE (widget))
943 packer = GTK_PACKER (widget);
945 child_event = *event;
947 children = g_list_first(packer->children);
950 child = children->data;
951 children = g_list_next(children);
953 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
954 gtk_widget_intersect (child->widget, &event->area, &child_event.area))
955 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
963 gtk_packer_size_request (GtkWidget *widget,
964 GtkRequisition *requisition)
967 GtkContainer *container;
968 GtkPackerChild *child;
970 gint nvis_vert_children;
971 gint nvis_horz_children;
973 gint maxWidth, maxHeight;
974 GtkRequisition child_requisition;
976 g_return_if_fail (widget != NULL);
977 g_return_if_fail (GTK_IS_PACKER (widget));
978 g_return_if_fail (requisition != NULL);
980 packer = GTK_PACKER (widget);
981 container = GTK_CONTAINER (widget);
983 requisition->width = 0;
984 requisition->height = 0;
985 nvis_vert_children = 0;
986 nvis_horz_children = 0;
988 width = height = maxWidth = maxHeight = 0;
990 children = g_list_first(packer->children);
991 while (children != NULL)
993 child = children->data;
995 if (GTK_WIDGET_VISIBLE (child->widget))
997 GtkRequisition child_requisition;
999 gtk_widget_size_request (child->widget, &child_requisition);
1001 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1003 maxWidth = MAX (maxWidth,
1004 (child_requisition.width +
1005 2 * child->border_width +
1006 child->pad_x + child->i_pad_x +
1008 height += (child_requisition.height +
1009 2 * child->border_width +
1010 child->pad_y + child->i_pad_y);
1014 maxHeight = MAX (maxHeight,
1015 (child_requisition.height +
1016 2 * child->border_width +
1017 child->pad_y + child->i_pad_y +
1019 width += (child_requisition.width +
1020 2 * child->border_width +
1021 child->pad_x + child->i_pad_x);
1025 children = g_list_next(children);
1028 requisition->width = MAX (maxWidth, width) + 2 * container->border_width;
1029 requisition->height = MAX (maxHeight, height) + 2 * container->border_width;
1033 YExpansion (GList *children,
1037 GtkPackerChild *child;
1039 gint numExpand, minExpand, curExpand;
1042 minExpand = cavityHeight;
1046 while (list != NULL)
1048 GtkRequisition child_requisition;
1051 widget = child->widget;
1052 gtk_widget_get_child_requisition (widget, &child_requisition);
1054 childHeight = (child_requisition.height +
1055 2 * child->border_width +
1058 if ((child->side == GTK_SIDE_LEFT) || (child->side == GTK_SIDE_RIGHT))
1060 curExpand = (cavityHeight - childHeight)/numExpand;
1061 minExpand = MIN(minExpand, curExpand);
1065 cavityHeight -= childHeight;
1066 if (child->options & GTK_PACK_EXPAND)
1069 list = g_list_next(list);
1071 curExpand = cavityHeight/numExpand;
1072 if (curExpand < minExpand)
1073 minExpand = curExpand;
1074 return (minExpand < 0) ? 0 : minExpand;
1078 XExpansion (GList *children,
1082 GtkPackerChild *child;
1084 gint numExpand, minExpand, curExpand;
1087 minExpand = cavityWidth;
1091 while (list != NULL)
1093 GtkRequisition child_requisition;
1096 widget = child->widget;
1097 gtk_widget_get_child_requisition (widget, &child_requisition);
1099 childWidth = (child_requisition.width +
1100 2 * child->border_width +
1104 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1106 curExpand = (cavityWidth - childWidth)/numExpand;
1107 minExpand = MIN(minExpand, curExpand);
1111 cavityWidth -= childWidth;
1112 if (child->options & GTK_PACK_EXPAND)
1115 list = g_list_next(list);
1117 curExpand = cavityWidth/numExpand;
1118 if (curExpand < minExpand)
1119 minExpand = curExpand;
1120 return (minExpand < 0) ? 0 : minExpand;
1124 gtk_packer_size_allocate (GtkWidget *widget,
1125 GtkAllocation *allocation)
1128 GtkContainer *container;
1129 GtkAllocation child_allocation;
1131 GtkPackerChild *child;
1132 gint cavityX, cavityY;
1133 gint cavityWidth, cavityHeight;
1134 gint width, height, x, y;
1135 gint frameHeight, frameWidth, frameX, frameY;
1136 gint borderX, borderY;
1138 g_return_if_fail (widget != NULL);
1139 g_return_if_fail (GTK_IS_PACKER (widget));
1140 g_return_if_fail (allocation != NULL);
1142 packer = GTK_PACKER (widget);
1143 container = GTK_CONTAINER (widget);
1147 widget->allocation = *allocation;
1149 cavityX = widget->allocation.x + container->border_width;
1150 cavityY = widget->allocation.y + container->border_width;
1151 cavityWidth = widget->allocation.width - 2 * container->border_width;
1152 cavityHeight = widget->allocation.height - 2 * container->border_width;
1154 list = g_list_first (packer->children);
1155 while (list != NULL)
1157 GtkRequisition child_requisition;
1160 gtk_widget_get_child_requisition (child->widget, &child_requisition);
1162 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1164 frameWidth = cavityWidth;
1165 frameHeight = (child_requisition.height +
1166 2 * child->border_width +
1169 if (child->options & GTK_PACK_EXPAND)
1170 frameHeight += YExpansion(list, cavityHeight);
1171 cavityHeight -= frameHeight;
1172 if (cavityHeight < 0)
1174 frameHeight += cavityHeight;
1178 if (child->side == GTK_SIDE_TOP)
1181 cavityY += frameHeight;
1185 frameY = cavityY + cavityHeight;
1190 frameHeight = cavityHeight;
1191 frameWidth = (child_requisition.width +
1192 2 * child->border_width +
1195 if (child->options & GTK_PACK_EXPAND)
1196 frameWidth += XExpansion(list, cavityWidth);
1197 cavityWidth -= frameWidth;
1198 if (cavityWidth < 0) {
1199 frameWidth += cavityWidth;
1203 if (child->side == GTK_SIDE_LEFT)
1206 cavityX += frameWidth;
1210 frameX = cavityX + cavityWidth;
1214 borderX = child->pad_x + 2 * child->border_width;
1215 borderY = child->pad_y + 2 * child->border_width;
1217 width = (child_requisition.width +
1218 2 * child->border_width +
1220 if ((child->options & GTK_FILL_X) || (width > (frameWidth - borderX)))
1221 width = frameWidth - borderX;
1223 height = (child_requisition.height +
1224 2 * child->border_width +
1226 if ((child->options & GTK_FILL_Y) || (height > (frameHeight - borderY)))
1227 height = frameHeight - borderY;
1231 switch (child->anchor)
1234 x = frameX + (frameWidth - width)/2;
1235 y = frameY + borderY;
1238 x = frameX + frameWidth - width - borderX;
1239 y = frameY + borderY;
1242 x = frameX + frameWidth - width - borderX;
1243 y = frameY + (frameHeight - height)/2;
1246 x = frameX + frameWidth - width - borderX;
1247 y = frameY + frameHeight - height - borderY;
1250 x = frameX + (frameWidth - width)/2;
1251 y = frameY + frameHeight - height - borderY;
1254 x = frameX + borderX;
1255 y = frameY + frameHeight - height - borderY;
1258 x = frameX + borderX;
1259 y = frameY + (frameHeight - height)/2;
1262 x = frameX + borderX;
1263 y = frameY + borderY;
1265 case GTK_ANCHOR_CENTER:
1266 x = frameX + (frameWidth - width)/2;
1267 y = frameY + (frameHeight - height)/2;
1270 g_warning ("gtk_packer_size_allocate(): bad anchor type: %d", child->anchor);
1273 if (width <= 0 || height <= 0)
1275 gtk_widget_unmap(child->widget);
1279 child_allocation.x = x;
1280 child_allocation.y = y;
1281 child_allocation.width = width;
1282 child_allocation.height = height;
1283 gtk_widget_size_allocate (child->widget, &child_allocation);
1285 if (GTK_WIDGET_MAPPED (widget) &&
1286 !(GTK_WIDGET_MAPPED (child->widget)))
1287 gtk_widget_map(child->widget);
1290 list = g_list_next(list);
1295 gtk_packer_forall (GtkContainer *container,
1296 gboolean include_internals,
1297 GtkCallback callback,
1298 gpointer callback_data)
1301 GtkPackerChild *child;
1304 g_return_if_fail (container != NULL);
1305 g_return_if_fail (GTK_IS_PACKER (container));
1306 g_return_if_fail (callback != NULL);
1308 packer = GTK_PACKER (container);
1310 children = g_list_first (packer->children);
1311 while (children != NULL)
1313 child = children->data;
1314 children = g_list_next(children);
1316 (* callback) (child->widget, callback_data);