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 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
90 * file for a list of people on the GTK+ Team. See the ChangeLog
91 * files for a list of changes. These files are distributed with
92 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
97 #include "gtkpacker.h"
117 CHILD_ARG_USE_DEFAULT,
118 CHILD_ARG_BORDER_WIDTH,
126 static void gtk_packer_class_init (GtkPackerClass *klass);
127 static void gtk_packer_init (GtkPacker *packer);
128 static void gtk_packer_map (GtkWidget *widget);
129 static void gtk_packer_unmap (GtkWidget *widget);
130 static void gtk_packer_draw (GtkWidget *widget,
132 static gint gtk_packer_expose (GtkWidget *widget,
133 GdkEventExpose *event);
134 static void gtk_packer_size_request (GtkWidget *widget,
135 GtkRequisition *requisition);
136 static void gtk_packer_size_allocate (GtkWidget *widget,
137 GtkAllocation *allocation);
138 static void gtk_packer_container_add (GtkContainer *container,
140 static void gtk_packer_remove (GtkContainer *container,
142 static void gtk_packer_forall (GtkContainer *container,
143 gboolean include_internals,
144 GtkCallback callback,
145 gpointer callback_data);
146 static void gtk_packer_set_arg (GtkObject *object,
149 static void gtk_packer_get_arg (GtkObject *object,
152 static void gtk_packer_get_child_arg (GtkContainer *container,
156 static void gtk_packer_set_child_arg (GtkContainer *container,
160 static GtkType gtk_packer_child_type (GtkContainer *container);
163 static GtkPackerClass *parent_class;
166 gtk_packer_get_type (void)
168 static GtkType packer_type = 0;
172 static const GtkTypeInfo packer_info =
176 sizeof (GtkPackerClass),
177 (GtkClassInitFunc) gtk_packer_class_init,
178 (GtkObjectInitFunc) gtk_packer_init,
179 /* reserved_1 */ NULL,
180 /* reserved_2 */ NULL,
181 (GtkClassInitFunc) NULL,
184 packer_type = gtk_type_unique (GTK_TYPE_CONTAINER, &packer_info);
191 gtk_packer_class_init (GtkPackerClass *klass)
193 GtkObjectClass *object_class;
194 GtkWidgetClass *widget_class;
195 GtkContainerClass *container_class;
197 object_class = (GtkObjectClass*) klass;
198 widget_class = (GtkWidgetClass*) klass;
199 container_class = (GtkContainerClass*) klass;
200 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
202 gtk_object_add_arg_type ("GtkPacker::spacing", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_SPACING);
203 gtk_object_add_arg_type ("GtkPacker::default_border_width", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_BORDER_WIDTH);
204 gtk_object_add_arg_type ("GtkPacker::default_pad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_PAD_X);
205 gtk_object_add_arg_type ("GtkPacker::default_pad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_PAD_Y);
206 gtk_object_add_arg_type ("GtkPacker::default_ipad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_IPAD_X);
207 gtk_object_add_arg_type ("GtkPacker::default_ipad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_D_IPAD_Y);
209 gtk_container_add_child_arg_type ("GtkPacker::side", GTK_TYPE_SIDE_TYPE, GTK_ARG_READWRITE, CHILD_ARG_SIDE);
210 gtk_container_add_child_arg_type ("GtkPacker::anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, CHILD_ARG_ANCHOR);
211 gtk_container_add_child_arg_type ("GtkPacker::expand", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_EXPAND);
212 gtk_container_add_child_arg_type ("GtkPacker::fill_x", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FILL_X);
213 gtk_container_add_child_arg_type ("GtkPacker::fill_y", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_FILL_Y);
214 gtk_container_add_child_arg_type ("GtkPacker::use_default", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_USE_DEFAULT);
215 gtk_container_add_child_arg_type ("GtkPacker::border_width", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_BORDER_WIDTH);
216 gtk_container_add_child_arg_type ("GtkPacker::pad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_PAD_X);
217 gtk_container_add_child_arg_type ("GtkPacker::pad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_PAD_Y);
218 gtk_container_add_child_arg_type ("GtkPacker::ipad_x", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_I_PAD_X);
219 gtk_container_add_child_arg_type ("GtkPacker::ipad_y", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_I_PAD_Y);
220 gtk_container_add_child_arg_type ("GtkPacker::position", GTK_TYPE_LONG, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
222 object_class->set_arg = gtk_packer_set_arg;
223 object_class->get_arg = gtk_packer_get_arg;
225 widget_class->map = gtk_packer_map;
226 widget_class->unmap = gtk_packer_unmap;
227 widget_class->draw = gtk_packer_draw;
228 widget_class->expose_event = gtk_packer_expose;
230 widget_class->size_request = gtk_packer_size_request;
231 widget_class->size_allocate = gtk_packer_size_allocate;
233 container_class->add = gtk_packer_container_add;
234 container_class->remove = gtk_packer_remove;
235 container_class->forall = gtk_packer_forall;
236 container_class->child_type = gtk_packer_child_type;
237 container_class->get_child_arg = gtk_packer_get_child_arg;
238 container_class->set_child_arg = gtk_packer_set_child_arg;
242 gtk_packer_set_arg (GtkObject *object,
248 packer = GTK_PACKER (object);
253 gtk_packer_set_spacing (packer, GTK_VALUE_UINT (*arg));
255 case ARG_D_BORDER_WIDTH:
256 gtk_packer_set_default_border_width (packer, GTK_VALUE_UINT (*arg));
259 gtk_packer_set_default_pad (packer,
260 GTK_VALUE_UINT (*arg),
261 packer->default_pad_y);
264 gtk_packer_set_default_pad (packer,
265 packer->default_pad_x,
266 GTK_VALUE_UINT (*arg));
269 gtk_packer_set_default_ipad (packer,
270 GTK_VALUE_UINT (*arg),
271 packer->default_i_pad_y);
274 gtk_packer_set_default_ipad (packer,
275 packer->default_i_pad_x,
276 GTK_VALUE_UINT (*arg));
284 gtk_packer_get_arg (GtkObject *object,
290 packer = GTK_PACKER (object);
295 GTK_VALUE_UINT (*arg) = packer->spacing;
297 case ARG_D_BORDER_WIDTH:
298 GTK_VALUE_UINT (*arg) = packer->default_border_width;
301 GTK_VALUE_UINT (*arg) = packer->default_pad_x;
304 GTK_VALUE_UINT (*arg) = packer->default_pad_y;
307 GTK_VALUE_UINT (*arg) = packer->default_i_pad_x;
310 GTK_VALUE_UINT (*arg) = packer->default_i_pad_y;
313 arg->type = GTK_TYPE_INVALID;
319 gtk_packer_child_type (GtkContainer *container)
321 return GTK_TYPE_WIDGET;
325 gtk_packer_set_child_arg (GtkContainer *container,
331 GtkPackerChild *child_info = NULL;
333 packer = GTK_PACKER (container);
335 if (arg_id != CHILD_ARG_POSITION)
339 list = packer->children;
342 child_info = list->data;
343 if (child_info->widget == child)
355 child_info->side = GTK_VALUE_ENUM (*arg);
357 case CHILD_ARG_ANCHOR:
358 child_info->anchor = GTK_VALUE_ENUM (*arg);
360 case CHILD_ARG_EXPAND:
361 if (GTK_VALUE_BOOL (*arg))
362 child_info->options |= GTK_PACK_EXPAND;
364 child_info->options &= ~GTK_PACK_EXPAND;
366 case CHILD_ARG_FILL_X:
367 if (GTK_VALUE_BOOL (*arg))
368 child_info->options |= GTK_FILL_X;
370 child_info->options &= ~GTK_FILL_X;
372 case CHILD_ARG_FILL_Y:
373 if (GTK_VALUE_BOOL (*arg))
374 child_info->options |= GTK_FILL_Y;
376 child_info->options &= ~GTK_FILL_Y;
378 case CHILD_ARG_USE_DEFAULT:
379 child_info->use_default = (GTK_VALUE_BOOL (*arg) != 0);
381 case CHILD_ARG_BORDER_WIDTH:
382 if (!child_info->use_default)
383 child_info->border_width = GTK_VALUE_UINT (*arg);
385 case CHILD_ARG_PAD_X:
386 if (!child_info->use_default)
387 child_info->pad_x = GTK_VALUE_UINT (*arg);
389 case CHILD_ARG_PAD_Y:
390 if (!child_info->use_default)
391 child_info->pad_y = GTK_VALUE_UINT (*arg);
393 case CHILD_ARG_I_PAD_X:
394 if (!child_info->use_default)
395 child_info->i_pad_x = GTK_VALUE_UINT (*arg);
397 case CHILD_ARG_I_PAD_Y:
398 if (!child_info->use_default)
399 child_info->i_pad_y = GTK_VALUE_UINT (*arg);
401 case CHILD_ARG_POSITION:
402 gtk_packer_reorder_child (packer,
404 GTK_VALUE_LONG (*arg));
410 if (arg_id != CHILD_ARG_POSITION &&
411 GTK_WIDGET_VISIBLE (packer) &&
412 GTK_WIDGET_VISIBLE (child))
413 gtk_widget_queue_resize (child);
417 gtk_packer_get_child_arg (GtkContainer *container,
423 GtkPackerChild *child_info = NULL;
426 packer = GTK_PACKER (container);
428 if (arg_id != CHILD_ARG_POSITION)
430 list = packer->children;
433 child_info = list->data;
434 if (child_info->widget == child)
441 arg->type = GTK_TYPE_INVALID;
449 GTK_VALUE_ENUM (*arg) = child_info->side;
451 case CHILD_ARG_ANCHOR:
452 GTK_VALUE_ENUM (*arg) = child_info->anchor;
454 case CHILD_ARG_EXPAND:
455 GTK_VALUE_BOOL (*arg) = (child_info->options & GTK_PACK_EXPAND) != 0;
457 case CHILD_ARG_FILL_X:
458 GTK_VALUE_BOOL (*arg) = (child_info->options & GTK_FILL_X) != 0;
460 case CHILD_ARG_FILL_Y:
461 GTK_VALUE_BOOL (*arg) = (child_info->options & GTK_FILL_Y) != 0;
463 case CHILD_ARG_USE_DEFAULT:
464 GTK_VALUE_BOOL (*arg) = child_info->use_default;
466 case CHILD_ARG_BORDER_WIDTH:
467 GTK_VALUE_UINT (*arg) = child_info->border_width;
469 case CHILD_ARG_PAD_X:
470 GTK_VALUE_UINT (*arg) = child_info->pad_x;
472 case CHILD_ARG_PAD_Y:
473 GTK_VALUE_UINT (*arg) = child_info->pad_y;
475 case CHILD_ARG_I_PAD_X:
476 GTK_VALUE_UINT (*arg) = child_info->i_pad_x;
478 case CHILD_ARG_I_PAD_Y:
479 GTK_VALUE_UINT (*arg) = child_info->i_pad_y;
481 case CHILD_ARG_POSITION:
482 GTK_VALUE_LONG (*arg) = 0;
483 for (list = packer->children; list; list = list->next)
485 child_info = list->data;
486 if (child_info->widget == child)
488 GTK_VALUE_LONG (*arg)++;
491 GTK_VALUE_LONG (*arg) = -1;
494 arg->type = GTK_TYPE_INVALID;
500 gtk_packer_init (GtkPacker *packer)
502 GTK_WIDGET_SET_FLAGS (packer, GTK_NO_WINDOW);
504 packer->children = NULL;
509 gtk_packer_set_spacing (GtkPacker *packer,
512 g_return_if_fail (packer != NULL);
513 g_return_if_fail (GTK_IS_PACKER (packer));
515 if (spacing != packer->spacing)
517 packer->spacing = spacing;
518 gtk_widget_queue_resize (GTK_WIDGET (packer));
523 gtk_packer_new (void)
525 return GTK_WIDGET (gtk_type_new (GTK_TYPE_PACKER));
529 redo_defaults_children (GtkPacker *packer)
532 GtkPackerChild *child;
534 list = g_list_first(packer->children);
539 if (child->use_default)
541 child->border_width = packer->default_border_width;
542 child->pad_x = packer->default_pad_x;
543 child->pad_y = packer->default_pad_y;
544 child->i_pad_x = packer->default_i_pad_x;
545 child->i_pad_y = packer->default_i_pad_y;
546 gtk_widget_queue_resize (GTK_WIDGET (child->widget));
548 list = g_list_next(list);
553 gtk_packer_set_default_border_width (GtkPacker *packer,
556 g_return_if_fail (packer != NULL);
557 g_return_if_fail (GTK_IS_PACKER (packer));
559 if (packer->default_border_width != border)
561 packer->default_border_width = border;;
562 redo_defaults_children (packer);
566 gtk_packer_set_default_pad (GtkPacker *packer,
570 g_return_if_fail (packer != NULL);
571 g_return_if_fail (GTK_IS_PACKER (packer));
573 if (packer->default_pad_x != pad_x ||
574 packer->default_pad_y != pad_y)
576 packer->default_pad_x = pad_x;
577 packer->default_pad_y = pad_y;
578 redo_defaults_children (packer);
583 gtk_packer_set_default_ipad (GtkPacker *packer,
587 g_return_if_fail (packer != NULL);
588 g_return_if_fail (GTK_IS_PACKER (packer));
590 if (packer->default_i_pad_x != i_pad_x ||
591 packer->default_i_pad_y != i_pad_y) {
593 packer->default_i_pad_x = i_pad_x;
594 packer->default_i_pad_y = i_pad_y;
595 redo_defaults_children (packer);
600 gtk_packer_container_add (GtkContainer *packer, GtkWidget *child)
602 gtk_packer_add_defaults(GTK_PACKER(packer), child,
603 GTK_SIDE_TOP, GTK_ANCHOR_CENTER, 0);
607 gtk_packer_add_defaults (GtkPacker *packer,
610 GtkAnchorType anchor,
611 GtkPackerOptions options)
613 GtkPackerChild *pchild;
615 g_return_if_fail (packer != NULL);
616 g_return_if_fail (GTK_IS_PACKER (packer));
617 g_return_if_fail (child != NULL);
618 g_return_if_fail (GTK_IS_WIDGET (child));
620 pchild = (GtkPackerChild*) g_malloc(sizeof(GtkPackerChild));
622 pchild->widget = child;
624 pchild->options = options;
625 pchild->anchor = anchor;
627 pchild->use_default = 1;
629 pchild->border_width = packer->default_border_width;
630 pchild->pad_x = packer->default_pad_x;
631 pchild->pad_y = packer->default_pad_y;
632 pchild->i_pad_x = packer->default_i_pad_x;
633 pchild->i_pad_y = packer->default_i_pad_y;
635 packer->children = g_list_append(packer->children, (gpointer) pchild);
637 gtk_widget_set_parent (child, GTK_WIDGET (packer));
639 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (packer)))
641 if (GTK_WIDGET_REALIZED (GTK_WIDGET (packer)) &&
642 !GTK_WIDGET_REALIZED (child))
643 gtk_widget_realize (child);
645 if (GTK_WIDGET_MAPPED (GTK_WIDGET (packer)) &&
646 !GTK_WIDGET_MAPPED (child))
647 gtk_widget_map (child);
650 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
651 gtk_widget_queue_resize (child);
656 gtk_packer_add (GtkPacker *packer,
659 GtkAnchorType anchor,
660 GtkPackerOptions options,
667 GtkPackerChild *pchild;
669 g_return_if_fail (packer != NULL);
670 g_return_if_fail (GTK_IS_PACKER (packer));
671 g_return_if_fail (child != NULL);
672 g_return_if_fail (GTK_IS_WIDGET (child));
674 pchild = (GtkPackerChild*) g_malloc(sizeof(GtkPackerChild));
676 pchild->widget = child;
678 pchild->options = options;
679 pchild->anchor = anchor;
681 pchild->use_default = 0;
683 pchild->border_width = border_width;
684 pchild->pad_x = pad_x;
685 pchild->pad_y = pad_y;
686 pchild->i_pad_x = i_pad_x;
687 pchild->i_pad_y = i_pad_y;
689 packer->children = g_list_append(packer->children, (gpointer) pchild);
691 gtk_widget_set_parent (child, GTK_WIDGET (packer));
693 if (GTK_WIDGET_VISIBLE (GTK_WIDGET (packer)))
695 if (GTK_WIDGET_REALIZED (GTK_WIDGET (packer)) &&
696 !GTK_WIDGET_REALIZED (child))
697 gtk_widget_realize (child);
699 if (GTK_WIDGET_MAPPED (GTK_WIDGET (packer)) &&
700 !GTK_WIDGET_MAPPED (child))
701 gtk_widget_map (child);
704 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
705 gtk_widget_queue_resize (child);
710 gtk_packer_set_child_packing (GtkPacker *packer,
713 GtkAnchorType anchor,
714 GtkPackerOptions options,
722 GtkPackerChild *pchild;
724 g_return_if_fail (packer != NULL);
725 g_return_if_fail (GTK_IS_PACKER (packer));
726 g_return_if_fail (child != NULL);
728 list = g_list_first(packer->children);
731 pchild = (GtkPackerChild*) list->data;
732 if (pchild->widget == child)
735 pchild->anchor = anchor;
736 pchild->options = options;
738 pchild->use_default = 0;
740 pchild->border_width = border_width;
741 pchild->pad_x = pad_x;
742 pchild->pad_y = pad_y;
743 pchild->i_pad_x = i_pad_x;
744 pchild->i_pad_y = i_pad_y;
746 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
747 gtk_widget_queue_resize (child);
750 list = g_list_next(list);
753 g_warning ("couldn't find child `%s' amongst the packer's children", gtk_type_name (GTK_OBJECT_TYPE (child)));
757 gtk_packer_reorder_child (GtkPacker *packer,
763 g_return_if_fail (packer != NULL);
764 g_return_if_fail (GTK_IS_PACKER (packer));
765 g_return_if_fail (child != NULL);
767 list = packer->children;
770 GtkPackerChild *child_info;
772 child_info = list->data;
773 if (child_info->widget == child)
779 if (list && packer->children->next)
784 list->next->prev = list->prev;
786 list->prev->next = list->next;
788 packer->children = list->next;
790 tmp_list = packer->children;
791 while (position && tmp_list->next)
794 tmp_list = tmp_list->next;
799 tmp_list->next = list;
800 list->prev = tmp_list;
806 tmp_list->prev->next = list;
808 packer->children = list;
809 list->prev = tmp_list->prev;
810 tmp_list->prev = list;
811 list->next = tmp_list;
814 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (packer))
815 gtk_widget_queue_resize (child);
820 gtk_packer_remove (GtkContainer *container,
824 GtkPackerChild *child;
828 g_return_if_fail (container != NULL);
829 g_return_if_fail (widget != NULL);
831 packer = GTK_PACKER (container);
833 children = g_list_first(packer->children);
836 child = children->data;
838 if (child->widget == widget)
840 visible = GTK_WIDGET_VISIBLE (widget);
841 gtk_widget_unparent (widget);
843 packer->children = g_list_remove_link (packer->children, children);
844 g_list_free (children);
847 if (visible && GTK_WIDGET_VISIBLE (container))
848 gtk_widget_queue_resize (GTK_WIDGET (container));
853 children = g_list_next(children);
858 gtk_packer_map (GtkWidget *widget)
861 GtkPackerChild *child;
864 g_return_if_fail (widget != NULL);
865 g_return_if_fail (GTK_IS_PACKER (widget));
867 packer = GTK_PACKER (widget);
868 GTK_WIDGET_SET_FLAGS (packer, GTK_MAPPED);
870 children = g_list_first(packer->children);
871 while (children != NULL)
873 child = children->data;
874 children = g_list_next(children);
876 if (GTK_WIDGET_VISIBLE (child->widget) &&
877 !GTK_WIDGET_MAPPED (child->widget))
878 gtk_widget_map (child->widget);
883 gtk_packer_unmap (GtkWidget *widget)
886 GtkPackerChild *child;
889 g_return_if_fail (widget != NULL);
890 g_return_if_fail (GTK_IS_PACKER (widget));
892 packer = GTK_PACKER (widget);
893 GTK_WIDGET_UNSET_FLAGS (packer, GTK_MAPPED);
895 children = g_list_first(packer->children);
898 child = children->data;
899 children = g_list_next(children);
901 if (GTK_WIDGET_VISIBLE (child->widget) &&
902 GTK_WIDGET_MAPPED (child->widget))
903 gtk_widget_unmap (child->widget);
908 gtk_packer_draw (GtkWidget *widget,
912 GtkPackerChild *child;
913 GdkRectangle child_area;
916 g_return_if_fail (widget != NULL);
917 g_return_if_fail (GTK_IS_PACKER (widget));
919 if (GTK_WIDGET_DRAWABLE (widget))
921 packer = GTK_PACKER (widget);
923 children = g_list_first(packer->children);
924 while (children != NULL)
926 child = children->data;
927 children = g_list_next(children);
929 if (gtk_widget_intersect (child->widget, area, &child_area))
930 gtk_widget_draw (child->widget, &child_area);
937 gtk_packer_expose (GtkWidget *widget,
938 GdkEventExpose *event)
941 GtkPackerChild *child;
942 GdkEventExpose child_event;
945 g_return_val_if_fail (widget != NULL, FALSE);
946 g_return_val_if_fail (GTK_IS_PACKER (widget), FALSE);
947 g_return_val_if_fail (event != NULL, FALSE);
949 if (GTK_WIDGET_DRAWABLE (widget))
951 packer = GTK_PACKER (widget);
953 child_event = *event;
955 children = g_list_first(packer->children);
958 child = children->data;
959 children = g_list_next(children);
961 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
962 gtk_widget_intersect (child->widget, &event->area, &child_event.area))
963 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
971 gtk_packer_size_request (GtkWidget *widget,
972 GtkRequisition *requisition)
975 GtkContainer *container;
976 GtkPackerChild *child;
978 gint nvis_vert_children;
979 gint nvis_horz_children;
981 gint maxWidth, maxHeight;
982 GtkRequisition child_requisition;
984 g_return_if_fail (widget != NULL);
985 g_return_if_fail (GTK_IS_PACKER (widget));
986 g_return_if_fail (requisition != NULL);
988 packer = GTK_PACKER (widget);
989 container = GTK_CONTAINER (widget);
991 requisition->width = 0;
992 requisition->height = 0;
993 nvis_vert_children = 0;
994 nvis_horz_children = 0;
996 width = height = maxWidth = maxHeight = 0;
998 children = g_list_first(packer->children);
999 while (children != NULL)
1001 child = children->data;
1003 if (GTK_WIDGET_VISIBLE (child->widget))
1005 GtkRequisition child_requisition;
1007 gtk_widget_size_request (child->widget, &child_requisition);
1009 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1011 maxWidth = MAX (maxWidth,
1012 (child_requisition.width +
1013 2 * child->border_width +
1014 child->pad_x + child->i_pad_x +
1016 height += (child_requisition.height +
1017 2 * child->border_width +
1018 child->pad_y + child->i_pad_y);
1022 maxHeight = MAX (maxHeight,
1023 (child_requisition.height +
1024 2 * child->border_width +
1025 child->pad_y + child->i_pad_y +
1027 width += (child_requisition.width +
1028 2 * child->border_width +
1029 child->pad_x + child->i_pad_x);
1033 children = g_list_next(children);
1036 requisition->width = MAX (maxWidth, width) + 2 * container->border_width;
1037 requisition->height = MAX (maxHeight, height) + 2 * container->border_width;
1041 YExpansion (GList *children,
1045 GtkPackerChild *child;
1047 gint numExpand, minExpand, curExpand;
1050 minExpand = cavityHeight;
1054 while (list != NULL)
1056 GtkRequisition child_requisition;
1059 widget = child->widget;
1060 gtk_widget_get_child_requisition (widget, &child_requisition);
1062 childHeight = (child_requisition.height +
1063 2 * child->border_width +
1066 if ((child->side == GTK_SIDE_LEFT) || (child->side == GTK_SIDE_RIGHT))
1068 curExpand = (cavityHeight - childHeight)/numExpand;
1069 minExpand = MIN(minExpand, curExpand);
1073 cavityHeight -= childHeight;
1074 if (child->options & GTK_PACK_EXPAND)
1077 list = g_list_next(list);
1079 curExpand = cavityHeight/numExpand;
1080 if (curExpand < minExpand)
1081 minExpand = curExpand;
1082 return (minExpand < 0) ? 0 : minExpand;
1086 XExpansion (GList *children,
1090 GtkPackerChild *child;
1092 gint numExpand, minExpand, curExpand;
1095 minExpand = cavityWidth;
1099 while (list != NULL)
1101 GtkRequisition child_requisition;
1104 widget = child->widget;
1105 gtk_widget_get_child_requisition (widget, &child_requisition);
1107 childWidth = (child_requisition.width +
1108 2 * child->border_width +
1112 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1114 curExpand = (cavityWidth - childWidth)/numExpand;
1115 minExpand = MIN(minExpand, curExpand);
1119 cavityWidth -= childWidth;
1120 if (child->options & GTK_PACK_EXPAND)
1123 list = g_list_next(list);
1125 curExpand = cavityWidth/numExpand;
1126 if (curExpand < minExpand)
1127 minExpand = curExpand;
1128 return (minExpand < 0) ? 0 : minExpand;
1132 gtk_packer_size_allocate (GtkWidget *widget,
1133 GtkAllocation *allocation)
1136 GtkContainer *container;
1137 GtkAllocation child_allocation;
1139 GtkPackerChild *child;
1140 gint cavityX, cavityY;
1141 gint cavityWidth, cavityHeight;
1142 gint width, height, x, y;
1143 gint frameHeight, frameWidth, frameX, frameY;
1144 gint borderX, borderY;
1146 g_return_if_fail (widget != NULL);
1147 g_return_if_fail (GTK_IS_PACKER (widget));
1148 g_return_if_fail (allocation != NULL);
1150 packer = GTK_PACKER (widget);
1151 container = GTK_CONTAINER (widget);
1155 widget->allocation = *allocation;
1157 cavityX = widget->allocation.x + container->border_width;
1158 cavityY = widget->allocation.y + container->border_width;
1159 cavityWidth = widget->allocation.width - 2 * container->border_width;
1160 cavityHeight = widget->allocation.height - 2 * container->border_width;
1162 list = g_list_first (packer->children);
1163 while (list != NULL)
1165 GtkRequisition child_requisition;
1168 gtk_widget_get_child_requisition (child->widget, &child_requisition);
1170 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1172 frameWidth = cavityWidth;
1173 frameHeight = (child_requisition.height +
1174 2 * child->border_width +
1177 if (child->options & GTK_PACK_EXPAND)
1178 frameHeight += YExpansion(list, cavityHeight);
1179 cavityHeight -= frameHeight;
1180 if (cavityHeight < 0)
1182 frameHeight += cavityHeight;
1186 if (child->side == GTK_SIDE_TOP)
1189 cavityY += frameHeight;
1193 frameY = cavityY + cavityHeight;
1198 frameHeight = cavityHeight;
1199 frameWidth = (child_requisition.width +
1200 2 * child->border_width +
1203 if (child->options & GTK_PACK_EXPAND)
1204 frameWidth += XExpansion(list, cavityWidth);
1205 cavityWidth -= frameWidth;
1206 if (cavityWidth < 0) {
1207 frameWidth += cavityWidth;
1211 if (child->side == GTK_SIDE_LEFT)
1214 cavityX += frameWidth;
1218 frameX = cavityX + cavityWidth;
1222 borderX = child->pad_x + 2 * child->border_width;
1223 borderY = child->pad_y + 2 * child->border_width;
1225 width = (child_requisition.width +
1226 2 * child->border_width +
1228 if ((child->options & GTK_FILL_X) || (width > (frameWidth - borderX)))
1229 width = frameWidth - borderX;
1231 height = (child_requisition.height +
1232 2 * child->border_width +
1234 if ((child->options & GTK_FILL_Y) || (height > (frameHeight - borderY)))
1235 height = frameHeight - borderY;
1239 switch (child->anchor)
1242 x = frameX + (frameWidth - width)/2;
1243 y = frameY + borderY;
1246 x = frameX + frameWidth - width - borderX;
1247 y = frameY + borderY;
1250 x = frameX + frameWidth - width - borderX;
1251 y = frameY + (frameHeight - height)/2;
1254 x = frameX + frameWidth - width - borderX;
1255 y = frameY + frameHeight - height - borderY;
1258 x = frameX + (frameWidth - width)/2;
1259 y = frameY + frameHeight - height - borderY;
1262 x = frameX + borderX;
1263 y = frameY + frameHeight - height - borderY;
1266 x = frameX + borderX;
1267 y = frameY + (frameHeight - height)/2;
1270 x = frameX + borderX;
1271 y = frameY + borderY;
1273 case GTK_ANCHOR_CENTER:
1274 x = frameX + (frameWidth - width)/2;
1275 y = frameY + (frameHeight - height)/2;
1278 g_warning ("gtk_packer_size_allocate(): bad anchor type: %d", child->anchor);
1281 if (width <= 0 || height <= 0)
1283 gtk_widget_unmap(child->widget);
1287 child_allocation.x = x;
1288 child_allocation.y = y;
1289 child_allocation.width = width;
1290 child_allocation.height = height;
1291 gtk_widget_size_allocate (child->widget, &child_allocation);
1293 if (GTK_WIDGET_MAPPED (widget) &&
1294 !(GTK_WIDGET_MAPPED (child->widget)))
1295 gtk_widget_map(child->widget);
1298 list = g_list_next(list);
1303 gtk_packer_forall (GtkContainer *container,
1304 gboolean include_internals,
1305 GtkCallback callback,
1306 gpointer callback_data)
1309 GtkPackerChild *child;
1312 g_return_if_fail (container != NULL);
1313 g_return_if_fail (GTK_IS_PACKER (container));
1314 g_return_if_fail (callback != NULL);
1316 packer = GTK_PACKER (container);
1318 children = g_list_first (packer->children);
1319 while (children != NULL)
1321 child = children->data;
1322 children = g_list_next(children);
1324 (* callback) (child->widget, callback_data);