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_REALIZED (child->parent))
640 gtk_widget_realize (child);
642 if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child))
644 if (GTK_WIDGET_MAPPED (child->parent))
645 gtk_widget_map (child);
647 gtk_widget_queue_resize (child);
652 gtk_packer_add (GtkPacker *packer,
655 GtkAnchorType anchor,
656 GtkPackerOptions options,
663 GtkPackerChild *pchild;
665 g_return_if_fail (packer != NULL);
666 g_return_if_fail (GTK_IS_PACKER (packer));
667 g_return_if_fail (child != NULL);
668 g_return_if_fail (GTK_IS_WIDGET (child));
670 pchild = (GtkPackerChild*) g_malloc(sizeof(GtkPackerChild));
672 pchild->widget = child;
674 pchild->options = options;
675 pchild->anchor = anchor;
677 pchild->use_default = 0;
679 pchild->border_width = border_width;
680 pchild->pad_x = pad_x;
681 pchild->pad_y = pad_y;
682 pchild->i_pad_x = i_pad_x;
683 pchild->i_pad_y = i_pad_y;
685 packer->children = g_list_append(packer->children, (gpointer) pchild);
687 gtk_widget_set_parent (child, GTK_WIDGET (packer));
689 if (GTK_WIDGET_REALIZED (child->parent))
690 gtk_widget_realize (child);
692 if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child))
694 if (GTK_WIDGET_MAPPED (child->parent))
695 gtk_widget_map (child);
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;
975 g_return_if_fail (widget != NULL);
976 g_return_if_fail (GTK_IS_PACKER (widget));
977 g_return_if_fail (requisition != NULL);
979 packer = GTK_PACKER (widget);
980 container = GTK_CONTAINER (widget);
982 requisition->width = 0;
983 requisition->height = 0;
984 nvis_vert_children = 0;
985 nvis_horz_children = 0;
987 width = height = maxWidth = maxHeight = 0;
989 children = g_list_first(packer->children);
990 while (children != NULL)
992 child = children->data;
994 if (GTK_WIDGET_VISIBLE (child->widget))
996 GtkRequisition child_requisition;
998 gtk_widget_size_request (child->widget, &child_requisition);
1000 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1002 maxWidth = MAX (maxWidth,
1003 (child_requisition.width +
1004 2 * child->border_width +
1005 child->pad_x + child->i_pad_x +
1007 height += (child_requisition.height +
1008 2 * child->border_width +
1009 child->pad_y + child->i_pad_y);
1013 maxHeight = MAX (maxHeight,
1014 (child_requisition.height +
1015 2 * child->border_width +
1016 child->pad_y + child->i_pad_y +
1018 width += (child_requisition.width +
1019 2 * child->border_width +
1020 child->pad_x + child->i_pad_x);
1024 children = g_list_next(children);
1027 requisition->width = MAX (maxWidth, width) + 2 * container->border_width;
1028 requisition->height = MAX (maxHeight, height) + 2 * container->border_width;
1032 YExpansion (GList *children,
1036 GtkPackerChild *child;
1038 gint numExpand, minExpand, curExpand;
1041 minExpand = cavityHeight;
1045 while (list != NULL)
1047 GtkRequisition child_requisition;
1050 widget = child->widget;
1051 gtk_widget_get_child_requisition (widget, &child_requisition);
1053 childHeight = (child_requisition.height +
1054 2 * child->border_width +
1057 if ((child->side == GTK_SIDE_LEFT) || (child->side == GTK_SIDE_RIGHT))
1059 curExpand = (cavityHeight - childHeight)/numExpand;
1060 minExpand = MIN(minExpand, curExpand);
1064 cavityHeight -= childHeight;
1065 if (child->options & GTK_PACK_EXPAND)
1068 list = g_list_next(list);
1070 curExpand = cavityHeight/numExpand;
1071 if (curExpand < minExpand)
1072 minExpand = curExpand;
1073 return (minExpand < 0) ? 0 : minExpand;
1077 XExpansion (GList *children,
1081 GtkPackerChild *child;
1083 gint numExpand, minExpand, curExpand;
1086 minExpand = cavityWidth;
1090 while (list != NULL)
1092 GtkRequisition child_requisition;
1095 widget = child->widget;
1096 gtk_widget_get_child_requisition (widget, &child_requisition);
1098 childWidth = (child_requisition.width +
1099 2 * child->border_width +
1103 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1105 curExpand = (cavityWidth - childWidth)/numExpand;
1106 minExpand = MIN(minExpand, curExpand);
1110 cavityWidth -= childWidth;
1111 if (child->options & GTK_PACK_EXPAND)
1114 list = g_list_next(list);
1116 curExpand = cavityWidth/numExpand;
1117 if (curExpand < minExpand)
1118 minExpand = curExpand;
1119 return (minExpand < 0) ? 0 : minExpand;
1123 gtk_packer_size_allocate (GtkWidget *widget,
1124 GtkAllocation *allocation)
1127 GtkContainer *container;
1128 GtkAllocation child_allocation;
1130 GtkPackerChild *child;
1131 gint cavityX, cavityY;
1132 gint cavityWidth, cavityHeight;
1133 gint width, height, x, y;
1134 gint frameHeight, frameWidth, frameX, frameY;
1135 gint borderX, borderY;
1137 g_return_if_fail (widget != NULL);
1138 g_return_if_fail (GTK_IS_PACKER (widget));
1139 g_return_if_fail (allocation != NULL);
1141 packer = GTK_PACKER (widget);
1142 container = GTK_CONTAINER (widget);
1146 widget->allocation = *allocation;
1148 cavityX = widget->allocation.x + container->border_width;
1149 cavityY = widget->allocation.y + container->border_width;
1150 cavityWidth = widget->allocation.width - 2 * container->border_width;
1151 cavityHeight = widget->allocation.height - 2 * container->border_width;
1153 list = g_list_first (packer->children);
1154 while (list != NULL)
1156 GtkRequisition child_requisition;
1159 gtk_widget_get_child_requisition (child->widget, &child_requisition);
1161 if ((child->side == GTK_SIDE_TOP) || (child->side == GTK_SIDE_BOTTOM))
1163 frameWidth = cavityWidth;
1164 frameHeight = (child_requisition.height +
1165 2 * child->border_width +
1168 if (child->options & GTK_PACK_EXPAND)
1169 frameHeight += YExpansion(list, cavityHeight);
1170 cavityHeight -= frameHeight;
1171 if (cavityHeight < 0)
1173 frameHeight += cavityHeight;
1177 if (child->side == GTK_SIDE_TOP)
1180 cavityY += frameHeight;
1184 frameY = cavityY + cavityHeight;
1189 frameHeight = cavityHeight;
1190 frameWidth = (child_requisition.width +
1191 2 * child->border_width +
1194 if (child->options & GTK_PACK_EXPAND)
1195 frameWidth += XExpansion(list, cavityWidth);
1196 cavityWidth -= frameWidth;
1197 if (cavityWidth < 0) {
1198 frameWidth += cavityWidth;
1202 if (child->side == GTK_SIDE_LEFT)
1205 cavityX += frameWidth;
1209 frameX = cavityX + cavityWidth;
1213 borderX = child->pad_x + 2 * child->border_width;
1214 borderY = child->pad_y + 2 * child->border_width;
1216 width = (child_requisition.width +
1217 2 * child->border_width +
1219 if ((child->options & GTK_FILL_X) || (width > (frameWidth - borderX)))
1220 width = frameWidth - borderX;
1222 height = (child_requisition.height +
1223 2 * child->border_width +
1225 if ((child->options & GTK_FILL_Y) || (height > (frameHeight - borderY)))
1226 height = frameHeight - borderY;
1230 switch (child->anchor)
1233 x = frameX + (frameWidth - width)/2;
1234 y = frameY + borderY;
1237 x = frameX + frameWidth - width - borderX;
1238 y = frameY + borderY;
1241 x = frameX + frameWidth - width - borderX;
1242 y = frameY + (frameHeight - height)/2;
1245 x = frameX + frameWidth - width - borderX;
1246 y = frameY + frameHeight - height - borderY;
1249 x = frameX + (frameWidth - width)/2;
1250 y = frameY + frameHeight - height - borderY;
1253 x = frameX + borderX;
1254 y = frameY + frameHeight - height - borderY;
1257 x = frameX + borderX;
1258 y = frameY + (frameHeight - height)/2;
1261 x = frameX + borderX;
1262 y = frameY + borderY;
1264 case GTK_ANCHOR_CENTER:
1265 x = frameX + (frameWidth - width)/2;
1266 y = frameY + (frameHeight - height)/2;
1269 g_warning ("gtk_packer_size_allocate(): bad anchor type: %d", child->anchor);
1272 if (width <= 0 || height <= 0)
1274 gtk_widget_unmap(child->widget);
1278 child_allocation.x = x;
1279 child_allocation.y = y;
1280 child_allocation.width = width;
1281 child_allocation.height = height;
1282 gtk_widget_size_allocate (child->widget, &child_allocation);
1284 if (GTK_WIDGET_MAPPED (widget) &&
1285 !(GTK_WIDGET_MAPPED (child->widget)))
1286 gtk_widget_map(child->widget);
1289 list = g_list_next(list);
1294 gtk_packer_forall (GtkContainer *container,
1295 gboolean include_internals,
1296 GtkCallback callback,
1297 gpointer callback_data)
1300 GtkPackerChild *child;
1303 g_return_if_fail (container != NULL);
1304 g_return_if_fail (GTK_IS_PACKER (container));
1305 g_return_if_fail (callback != NULL);
1307 packer = GTK_PACKER (container);
1309 children = g_list_first (packer->children);
1310 while (children != NULL)
1312 child = children->data;
1313 children = g_list_next(children);
1315 (* callback) (child->widget, callback_data);