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, GdkRectangle *area)
903 GtkPackerChild *child;
904 GdkRectangle child_area;
907 g_return_if_fail (widget != NULL);
908 g_return_if_fail (GTK_IS_PACKER (widget));
910 if (GTK_WIDGET_DRAWABLE (widget))
912 packer = GTK_PACKER (widget);
914 children = g_list_first(packer->children);
915 while (children != NULL)
917 child = children->data;
918 children = g_list_next(children);
920 if (gtk_widget_intersect (child->widget, area, &child_area))
921 gtk_widget_draw (child->widget, &child_area);
928 gtk_packer_expose (GtkWidget *widget, GdkEventExpose *event)
931 GtkPackerChild *child;
932 GdkEventExpose child_event;
935 g_return_val_if_fail (widget != NULL, FALSE);
936 g_return_val_if_fail (GTK_IS_PACKER (widget), FALSE);
937 g_return_val_if_fail (event != NULL, FALSE);
939 if (GTK_WIDGET_DRAWABLE (widget))
941 packer = GTK_PACKER (widget);
943 child_event = *event;
945 children = g_list_first(packer->children);
948 child = children->data;
949 children = g_list_next(children);
951 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
952 gtk_widget_intersect (child->widget, &event->area, &child_event.area))
953 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
961 gtk_packer_size_request (GtkWidget *widget, GtkRequisition *requisition)
964 GtkContainer *container;
965 GtkPackerChild *child;
967 gint nvis_vert_children;
968 gint nvis_horz_children;
970 gint maxWidth, maxHeight;
972 g_return_if_fail (widget != NULL);
973 g_return_if_fail (GTK_IS_PACKER (widget));
974 g_return_if_fail (requisition != NULL);
976 packer = GTK_PACKER (widget);
977 container = GTK_CONTAINER (widget);
979 requisition->width = 0;
980 requisition->height = 0;
981 nvis_vert_children = 0;
982 nvis_horz_children = 0;
984 width = height = maxWidth = maxHeight = 0;
986 children = g_list_first(packer->children);
987 while (children != NULL)
989 child = children->data;
991 if (GTK_WIDGET_VISIBLE (child->widget))
993 gtk_widget_size_request (child->widget, &child->widget->requisition);
995 if((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
997 maxWidth = MAX (maxWidth,
998 (child->widget->requisition.width +
999 2 * child->border_width +
1000 child->pad_x + child->i_pad_x +
1002 height += (child->widget->requisition.height +
1003 2 * child->border_width +
1004 child->pad_y + child->i_pad_y);
1008 maxHeight = MAX (maxHeight,
1009 (child->widget->requisition.height +
1010 2 * child->border_width +
1011 child->pad_y + child->i_pad_y +
1013 width += (child->widget->requisition.width +
1014 2 * child->border_width +
1015 child->pad_x + child->i_pad_x);
1019 children = g_list_next(children);
1022 requisition->width = MAX (maxWidth, width) + 2 * container->border_width;
1023 requisition->height = MAX (maxHeight, height) + 2 * container->border_width;
1027 YExpansion (GList *children, gint cavityHeight)
1030 GtkPackerChild *child;
1032 gint numExpand, minExpand, curExpand;
1035 minExpand = cavityHeight;
1039 while (list != NULL)
1042 widget = child->widget;
1043 childHeight = (widget->requisition.height +
1044 2 * child->border_width +
1047 if ((child->side == GTK_SIDE_LEFT) || (child->side == GTK_SIDE_RIGHT))
1049 curExpand = (cavityHeight - childHeight)/numExpand;
1050 minExpand = MIN(minExpand, curExpand);
1054 cavityHeight -= childHeight;
1055 if (child->options & GTK_PACK_EXPAND)
1058 list = g_list_next(list);
1060 curExpand = cavityHeight/numExpand;
1061 if (curExpand < minExpand)
1062 minExpand = curExpand;
1063 return (minExpand < 0) ? 0 : minExpand;
1067 XExpansion (GList *children, gint cavityWidth)
1070 GtkPackerChild *child;
1072 gint numExpand, minExpand, curExpand;
1075 minExpand = cavityWidth;
1079 while (list != NULL)
1082 widget = child->widget;
1083 childWidth = (widget->requisition.width +
1084 2 * child->border_width +
1088 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1090 curExpand = (cavityWidth - childWidth)/numExpand;
1091 minExpand = MIN(minExpand, curExpand);
1095 cavityWidth -= childWidth;
1096 if (child->options & GTK_PACK_EXPAND)
1099 list = g_list_next(list);
1101 curExpand = cavityWidth/numExpand;
1102 if (curExpand < minExpand)
1103 minExpand = curExpand;
1104 return (minExpand < 0) ? 0 : minExpand;
1108 gtk_packer_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
1111 GtkContainer *container;
1112 GtkAllocation child_allocation;
1114 GtkPackerChild *child;
1115 gint cavityX, cavityY;
1116 gint cavityWidth, cavityHeight;
1117 gint width, height, x, y;
1118 gint frameHeight, frameWidth, frameX, frameY;
1119 gint borderX, borderY;
1121 g_return_if_fail (widget != NULL);
1122 g_return_if_fail (GTK_IS_PACKER (widget));
1123 g_return_if_fail (allocation != NULL);
1125 packer = GTK_PACKER (widget);
1126 container = GTK_CONTAINER (widget);
1130 widget->allocation = *allocation;
1132 cavityX = widget->allocation.x + container->border_width;
1133 cavityY = widget->allocation.y + container->border_width;
1134 cavityWidth = widget->allocation.width - 2 * container->border_width;
1135 cavityHeight = widget->allocation.height - 2 * container->border_width;
1137 list = g_list_first (packer->children);
1138 while (list != NULL)
1142 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1144 frameWidth = cavityWidth;
1145 frameHeight = (child->widget->requisition.height +
1146 2 * child->border_width +
1149 if (child->options & GTK_PACK_EXPAND)
1150 frameHeight += YExpansion(list, cavityHeight);
1151 cavityHeight -= frameHeight;
1152 if (cavityHeight < 0)
1154 frameHeight += cavityHeight;
1158 if (child->side == GTK_SIDE_TOP)
1161 cavityY += frameHeight;
1165 frameY = cavityY + cavityHeight;
1170 frameHeight = cavityHeight;
1171 frameWidth = (child->widget->requisition.width +
1172 2 * child->border_width +
1175 if (child->options & GTK_PACK_EXPAND)
1176 frameWidth += XExpansion(list, cavityWidth);
1177 cavityWidth -= frameWidth;
1178 if (cavityWidth < 0) {
1179 frameWidth += cavityWidth;
1183 if (child->side == GTK_SIDE_LEFT)
1186 cavityX += frameWidth;
1190 frameX = cavityX + cavityWidth;
1194 borderX = child->pad_x + 2 * child->border_width;
1195 borderY = child->pad_y + 2 * child->border_width;
1197 width = (child->widget->requisition.width +
1198 2 * child->border_width +
1200 if ((child->options & GTK_FILL_X) || (width > (frameWidth - borderX)))
1201 width = frameWidth - borderX;
1203 height = (child->widget->requisition.height +
1204 2 * child->border_width +
1206 if ((child->options & GTK_FILL_Y) || (height > (frameHeight - borderY)))
1207 height = frameHeight - borderY;
1211 switch (child->anchor)
1214 x = frameX + (frameWidth - width)/2;
1215 y = frameY + borderY;
1218 x = frameX + frameWidth - width - borderX;
1219 y = frameY + borderY;
1222 x = frameX + frameWidth - width - borderX;
1223 y = frameY + (frameHeight - height)/2;
1226 x = frameX + frameWidth - width - borderX;
1227 y = frameY + frameHeight - height - borderY;
1230 x = frameX + (frameWidth - width)/2;
1231 y = frameY + frameHeight - height - borderY;
1234 x = frameX + borderX;
1235 y = frameY + frameHeight - height - borderY;
1238 x = frameX + borderX;
1239 y = frameY + (frameHeight - height)/2;
1242 x = frameX + borderX;
1243 y = frameY + borderY;
1245 case GTK_ANCHOR_CENTER:
1246 x = frameX + (frameWidth - width)/2;
1247 y = frameY + (frameHeight - height)/2;
1250 g_warning ("gtk_packer_size_allocate(): bad anchor type: %d", child->anchor);
1253 if (width <= 0 || height <= 0)
1255 gtk_widget_unmap(child->widget);
1259 child_allocation.x = x;
1260 child_allocation.y = y;
1261 child_allocation.width = width;
1262 child_allocation.height = height;
1263 gtk_widget_size_allocate (child->widget, &child_allocation);
1265 if (GTK_WIDGET_MAPPED (widget) &&
1266 !(GTK_WIDGET_MAPPED (child->widget)))
1267 gtk_widget_map(child->widget);
1270 list = g_list_next(list);
1275 gtk_packer_forall (GtkContainer *container,
1276 gboolean include_internals,
1277 GtkCallback callback,
1278 gpointer callback_data)
1281 GtkPackerChild *child;
1284 g_return_if_fail (container != NULL);
1285 g_return_if_fail (GTK_IS_PACKER (container));
1286 g_return_if_fail (callback != NULL);
1288 packer = GTK_PACKER (container);
1290 children = g_list_first (packer->children);
1291 while (children != NULL)
1293 child = children->data;
1294 children = g_list_next(children);
1296 (* callback) (child->widget, callback_data);