1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27 #include "config.h"
28 #include "gtkbbox.h"
29 #include "gtkhbbox.h"
30 #include "gtkvbbox.h"
31 #include "gtkorientable.h"
32 #include "gtkprivate.h"
33 #include "gtkintl.h"
34 #include "gtkalias.h"
35
36 enum {
37 PROP_0,
38 PROP_LAYOUT_STYLE
39 };
40
41 enum {
42 CHILD_PROP_0,
43 CHILD_PROP_SECONDARY
44 };
45
46 static void gtk_button_box_set_property (GObject *object,
47 guint prop_id,
48 const GValue *value,
49 GParamSpec *pspec);
50 static void gtk_button_box_get_property (GObject *object,
51 guint prop_id,
52 GValue *value,
53 GParamSpec *pspec);
54 static void gtk_button_box_size_request (GtkWidget *widget,
55 GtkRequisition *requisition);
56 static void gtk_button_box_size_allocate (GtkWidget *widget,
57 GtkAllocation *allocation);
58 static void gtk_button_box_set_child_property (GtkContainer *container,
59 GtkWidget *child,
60 guint property_id,
61 const GValue *value,
62 GParamSpec *pspec);
63 static void gtk_button_box_get_child_property (GtkContainer *container,
64 GtkWidget *child,
65 guint property_id,
66 GValue *value,
67 GParamSpec *pspec);
68
69 #define DEFAULT_CHILD_MIN_WIDTH 85
70 #define DEFAULT_CHILD_MIN_HEIGHT 27
71 #define DEFAULT_CHILD_IPAD_X 4
72 #define DEFAULT_CHILD_IPAD_Y 0
73
G_DEFINE_ABSTRACT_TYPE(GtkButtonBox,gtk_button_box,GTK_TYPE_BOX)74 G_DEFINE_ABSTRACT_TYPE (GtkButtonBox, gtk_button_box, GTK_TYPE_BOX)
75
76 static void
77 gtk_button_box_class_init (GtkButtonBoxClass *class)
78 {
79 GtkWidgetClass *widget_class;
80 GObjectClass *gobject_class;
81 GtkContainerClass *container_class;
82
83 gobject_class = G_OBJECT_CLASS (class);
84 widget_class = (GtkWidgetClass*) class;
85 container_class = (GtkContainerClass*) class;
86
87 gobject_class->set_property = gtk_button_box_set_property;
88 gobject_class->get_property = gtk_button_box_get_property;
89
90 widget_class->size_request = gtk_button_box_size_request;
91 widget_class->size_allocate = gtk_button_box_size_allocate;
92
93 container_class->set_child_property = gtk_button_box_set_child_property;
94 container_class->get_child_property = gtk_button_box_get_child_property;
95
96 /* FIXME we need to override the "spacing" property on GtkBox once
97 * libgobject allows that.
98 */
99 gtk_widget_class_install_style_property (widget_class,
100 g_param_spec_int ("child-min-width",
101 P_("Minimum child width"),
102 P_("Minimum width of buttons inside the box"),
103 0,
104 G_MAXINT,
105 DEFAULT_CHILD_MIN_WIDTH,
106 GTK_PARAM_READABLE));
107
108 gtk_widget_class_install_style_property (widget_class,
109 g_param_spec_int ("child-min-height",
110 P_("Minimum child height"),
111 P_("Minimum height of buttons inside the box"),
112 0,
113 G_MAXINT,
114 DEFAULT_CHILD_MIN_HEIGHT,
115 GTK_PARAM_READABLE));
116
117 gtk_widget_class_install_style_property (widget_class,
118 g_param_spec_int ("child-internal-pad-x",
119 P_("Child internal width padding"),
120 P_("Amount to increase child's size on either side"),
121 0,
122 G_MAXINT,
123 DEFAULT_CHILD_IPAD_X,
124 GTK_PARAM_READABLE));
125
126 gtk_widget_class_install_style_property (widget_class,
127 g_param_spec_int ("child-internal-pad-y",
128 P_("Child internal height padding"),
129 P_("Amount to increase child's size on the top and bottom"),
130 0,
131 G_MAXINT,
132 DEFAULT_CHILD_IPAD_Y,
133 GTK_PARAM_READABLE));
134 g_object_class_install_property (gobject_class,
135 PROP_LAYOUT_STYLE,
136 g_param_spec_enum ("layout-style",
137 P_("Layout style"),
138 P_("How to lay out the buttons in the box. Possible values are: default, spread, edge, start and end"),
139 GTK_TYPE_BUTTON_BOX_STYLE,
140 GTK_BUTTONBOX_DEFAULT_STYLE,
141 GTK_PARAM_READWRITE));
142
143 gtk_container_class_install_child_property (container_class,
144 CHILD_PROP_SECONDARY,
145 g_param_spec_boolean ("secondary",
146 P_("Secondary"),
147 P_("If TRUE, the child appears in a secondary group of children, suitable for, e.g., help buttons"),
148 FALSE,
149 GTK_PARAM_READWRITE));
150 }
151
152 static void
gtk_button_box_init(GtkButtonBox * button_box)153 gtk_button_box_init (GtkButtonBox *button_box)
154 {
155 GTK_BOX (button_box)->spacing = 0;
156 button_box->child_min_width = GTK_BUTTONBOX_DEFAULT;
157 button_box->child_min_height = GTK_BUTTONBOX_DEFAULT;
158 button_box->child_ipad_x = GTK_BUTTONBOX_DEFAULT;
159 button_box->child_ipad_y = GTK_BUTTONBOX_DEFAULT;
160 button_box->layout_style = GTK_BUTTONBOX_DEFAULT_STYLE;
161 }
162
163 static void
gtk_button_box_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)164 gtk_button_box_set_property (GObject *object,
165 guint prop_id,
166 const GValue *value,
167 GParamSpec *pspec)
168 {
169 switch (prop_id)
170 {
171 case PROP_LAYOUT_STYLE:
172 gtk_button_box_set_layout (GTK_BUTTON_BOX (object),
173 g_value_get_enum (value));
174 break;
175 default:
176 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
177 break;
178 }
179 }
180
181 static void
gtk_button_box_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)182 gtk_button_box_get_property (GObject *object,
183 guint prop_id,
184 GValue *value,
185 GParamSpec *pspec)
186 {
187 switch (prop_id)
188 {
189 case PROP_LAYOUT_STYLE:
190 g_value_set_enum (value, GTK_BUTTON_BOX (object)->layout_style);
191 break;
192 default:
193 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
194 break;
195 }
196 }
197
198 static void
gtk_button_box_set_child_property(GtkContainer * container,GtkWidget * child,guint property_id,const GValue * value,GParamSpec * pspec)199 gtk_button_box_set_child_property (GtkContainer *container,
200 GtkWidget *child,
201 guint property_id,
202 const GValue *value,
203 GParamSpec *pspec)
204 {
205 switch (property_id)
206 {
207 case CHILD_PROP_SECONDARY:
208 gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (container), child,
209 g_value_get_boolean (value));
210 break;
211 default:
212 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
213 break;
214 }
215 }
216
217 static void
gtk_button_box_get_child_property(GtkContainer * container,GtkWidget * child,guint property_id,GValue * value,GParamSpec * pspec)218 gtk_button_box_get_child_property (GtkContainer *container,
219 GtkWidget *child,
220 guint property_id,
221 GValue *value,
222 GParamSpec *pspec)
223 {
224 switch (property_id)
225 {
226 case CHILD_PROP_SECONDARY:
227 g_value_set_boolean (value,
228 gtk_button_box_get_child_secondary (GTK_BUTTON_BOX (container),
229 child));
230 break;
231 default:
232 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
233 break;
234 }
235 }
236
237 /* set per widget values for spacing, child size and child internal padding */
238
239 void
gtk_button_box_set_child_size(GtkButtonBox * widget,gint width,gint height)240 gtk_button_box_set_child_size (GtkButtonBox *widget,
241 gint width, gint height)
242 {
243 g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
244
245 widget->child_min_width = width;
246 widget->child_min_height = height;
247 }
248
249 void
gtk_button_box_set_child_ipadding(GtkButtonBox * widget,gint ipad_x,gint ipad_y)250 gtk_button_box_set_child_ipadding (GtkButtonBox *widget,
251 gint ipad_x, gint ipad_y)
252 {
253 g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
254
255 widget->child_ipad_x = ipad_x;
256 widget->child_ipad_y = ipad_y;
257 }
258
259 void
gtk_button_box_set_layout(GtkButtonBox * widget,GtkButtonBoxStyle layout_style)260 gtk_button_box_set_layout (GtkButtonBox *widget,
261 GtkButtonBoxStyle layout_style)
262 {
263 g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
264 g_return_if_fail (layout_style >= GTK_BUTTONBOX_DEFAULT_STYLE &&
265 layout_style <= GTK_BUTTONBOX_CENTER);
266
267 if (widget->layout_style != layout_style)
268 {
269 widget->layout_style = layout_style;
270 g_object_notify (G_OBJECT (widget), "layout-style");
271 gtk_widget_queue_resize (GTK_WIDGET (widget));
272 }
273 }
274
275
276 /* get per widget values for spacing, child size and child internal padding */
277
278 void
gtk_button_box_get_child_size(GtkButtonBox * widget,gint * width,gint * height)279 gtk_button_box_get_child_size (GtkButtonBox *widget,
280 gint *width, gint *height)
281 {
282 g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
283 g_return_if_fail (width != NULL);
284 g_return_if_fail (height != NULL);
285
286 *width = widget->child_min_width;
287 *height = widget->child_min_height;
288 }
289
290 void
gtk_button_box_get_child_ipadding(GtkButtonBox * widget,gint * ipad_x,gint * ipad_y)291 gtk_button_box_get_child_ipadding (GtkButtonBox *widget,
292 gint* ipad_x, gint *ipad_y)
293 {
294 g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
295 g_return_if_fail (ipad_x != NULL);
296 g_return_if_fail (ipad_y != NULL);
297
298 *ipad_x = widget->child_ipad_x;
299 *ipad_y = widget->child_ipad_y;
300 }
301
302 GtkButtonBoxStyle
gtk_button_box_get_layout(GtkButtonBox * widget)303 gtk_button_box_get_layout (GtkButtonBox *widget)
304 {
305 g_return_val_if_fail (GTK_IS_BUTTON_BOX (widget), GTK_BUTTONBOX_SPREAD);
306
307 return widget->layout_style;
308 }
309
310 /**
311 * gtk_button_box_get_child_secondary:
312 * @widget: a #GtkButtonBox
313 * @child: a child of @widget
314 *
315 * Returns whether @child should appear in a secondary group of children.
316 *
317 * Return value: whether @child should appear in a secondary group of children.
318 *
319 * Since: 2.4
320 **/
321 gboolean
gtk_button_box_get_child_secondary(GtkButtonBox * widget,GtkWidget * child)322 gtk_button_box_get_child_secondary (GtkButtonBox *widget,
323 GtkWidget *child)
324 {
325 GList *list;
326 GtkBoxChild *child_info;
327
328 g_return_val_if_fail (GTK_IS_BUTTON_BOX (widget), FALSE);
329 g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
330
331 child_info = NULL;
332 list = GTK_BOX (widget)->children;
333 while (list)
334 {
335 child_info = list->data;
336 if (child_info->widget == child)
337 break;
338
339 list = list->next;
340 }
341
342 g_return_val_if_fail (list != NULL, FALSE);
343
344 return child_info->is_secondary;
345 }
346
347 /**
348 * gtk_button_box_set_child_secondary
349 * @widget: a #GtkButtonBox
350 * @child: a child of @widget
351 * @is_secondary: if %TRUE, the @child appears in a secondary group of the
352 * button box.
353 *
354 * Sets whether @child should appear in a secondary group of children.
355 * A typical use of a secondary child is the help button in a dialog.
356 *
357 * This group appears after the other children if the style
358 * is %GTK_BUTTONBOX_START, %GTK_BUTTONBOX_SPREAD or
359 * %GTK_BUTTONBOX_EDGE, and before the other children if the style
360 * is %GTK_BUTTONBOX_END. For horizontal button boxes, the definition
361 * of before/after depends on direction of the widget (see
362 * gtk_widget_set_direction()). If the style is %GTK_BUTTONBOX_START
363 * or %GTK_BUTTONBOX_END, then the secondary children are aligned at
364 * the other end of the button box from the main children. For the
365 * other styles, they appear immediately next to the main children.
366 **/
367 void
gtk_button_box_set_child_secondary(GtkButtonBox * widget,GtkWidget * child,gboolean is_secondary)368 gtk_button_box_set_child_secondary (GtkButtonBox *widget,
369 GtkWidget *child,
370 gboolean is_secondary)
371 {
372 GList *list;
373
374 g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
375 g_return_if_fail (GTK_IS_WIDGET (child));
376 g_return_if_fail (child->parent == GTK_WIDGET (widget));
377
378 list = GTK_BOX (widget)->children;
379 while (list)
380 {
381 GtkBoxChild *child_info = list->data;
382 if (child_info->widget == child)
383 {
384 child_info->is_secondary = is_secondary;
385 break;
386 }
387
388 list = list->next;
389 }
390
391 gtk_widget_child_notify (child, "secondary");
392
393 if (gtk_widget_get_visible (GTK_WIDGET (widget))
394 && gtk_widget_get_visible (child))
395 gtk_widget_queue_resize (child);
396 }
397
398 /* Ask children how much space they require and round up
399 to match minimum size and internal padding.
400 Returns the size each single child should have. */
401 void
_gtk_button_box_child_requisition(GtkWidget * widget,int * nvis_children,int * nvis_secondaries,int * width,int * height)402 _gtk_button_box_child_requisition (GtkWidget *widget,
403 int *nvis_children,
404 int *nvis_secondaries,
405 int *width,
406 int *height)
407 {
408 GtkButtonBox *bbox;
409 GtkBoxChild *child;
410 GList *children;
411 gint nchildren;
412 gint nsecondaries;
413 gint needed_width;
414 gint needed_height;
415 GtkRequisition child_requisition;
416 gint ipad_w;
417 gint ipad_h;
418 gint width_default;
419 gint height_default;
420 gint ipad_x_default;
421 gint ipad_y_default;
422
423 gint child_min_width;
424 gint child_min_height;
425 gint ipad_x;
426 gint ipad_y;
427
428 g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
429
430 bbox = GTK_BUTTON_BOX (widget);
431
432 gtk_widget_style_get (widget,
433 "child-min-width", &width_default,
434 "child-min-height", &height_default,
435 "child-internal-pad-x", &ipad_x_default,
436 "child-internal-pad-y", &ipad_y_default,
437 NULL);
438
439 child_min_width = bbox->child_min_width != GTK_BUTTONBOX_DEFAULT
440 ? bbox->child_min_width : width_default;
441 child_min_height = bbox->child_min_height !=GTK_BUTTONBOX_DEFAULT
442 ? bbox->child_min_height : height_default;
443 ipad_x = bbox->child_ipad_x != GTK_BUTTONBOX_DEFAULT
444 ? bbox->child_ipad_x : ipad_x_default;
445 ipad_y = bbox->child_ipad_y != GTK_BUTTONBOX_DEFAULT
446 ? bbox->child_ipad_y : ipad_y_default;
447
448 nchildren = 0;
449 nsecondaries = 0;
450 children = GTK_BOX(bbox)->children;
451 needed_width = child_min_width;
452 needed_height = child_min_height;
453 ipad_w = ipad_x * 2;
454 ipad_h = ipad_y * 2;
455
456 while (children)
457 {
458 child = children->data;
459 children = children->next;
460
461 if (gtk_widget_get_visible (child->widget))
462 {
463 nchildren += 1;
464 gtk_widget_size_request (child->widget, &child_requisition);
465
466 if (child_requisition.width + ipad_w > needed_width)
467 needed_width = child_requisition.width + ipad_w;
468 if (child_requisition.height + ipad_h > needed_height)
469 needed_height = child_requisition.height + ipad_h;
470 if (child->is_secondary)
471 nsecondaries++;
472 }
473 }
474
475 if (nvis_children)
476 *nvis_children = nchildren;
477 if (nvis_secondaries)
478 *nvis_secondaries = nsecondaries;
479 if (width)
480 *width = needed_width;
481 if (height)
482 *height = needed_height;
483 }
484
485 /* this is a kludge function to support the deprecated
486 * gtk_[vh]button_box_set_layout_default() just in case anyone is still
487 * using it (why?)
488 */
489 static GtkButtonBoxStyle
gtk_button_box_kludge_get_layout_default(GtkButtonBox * widget)490 gtk_button_box_kludge_get_layout_default (GtkButtonBox *widget)
491 {
492 GtkOrientation orientation;
493
494 orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
495
496 if (orientation == GTK_ORIENTATION_HORIZONTAL)
497 return _gtk_hbutton_box_get_layout_default ();
498 else
499 return _gtk_vbutton_box_get_layout_default ();
500 }
501
502 static void
gtk_button_box_size_request(GtkWidget * widget,GtkRequisition * requisition)503 gtk_button_box_size_request (GtkWidget *widget,
504 GtkRequisition *requisition)
505 {
506 GtkBox *box;
507 GtkButtonBox *bbox;
508 gint nvis_children;
509 gint child_width;
510 gint child_height;
511 gint spacing;
512 GtkButtonBoxStyle layout;
513 GtkOrientation orientation;
514
515 box = GTK_BOX (widget);
516 bbox = GTK_BUTTON_BOX (widget);
517
518 orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
519 spacing = box->spacing;
520 layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE
521 ? bbox->layout_style : gtk_button_box_kludge_get_layout_default (GTK_BUTTON_BOX (widget));
522
523 _gtk_button_box_child_requisition (widget,
524 &nvis_children,
525 NULL,
526 &child_width,
527 &child_height);
528
529 if (nvis_children == 0)
530 {
531 requisition->width = 0;
532 requisition->height = 0;
533 }
534 else
535 {
536 switch (layout)
537 {
538 case GTK_BUTTONBOX_SPREAD:
539 if (orientation == GTK_ORIENTATION_HORIZONTAL)
540 requisition->width =
541 nvis_children*child_width + ((nvis_children+1)*spacing);
542 else
543 requisition->height =
544 nvis_children*child_height + ((nvis_children+1)*spacing);
545
546 break;
547 case GTK_BUTTONBOX_EDGE:
548 case GTK_BUTTONBOX_START:
549 case GTK_BUTTONBOX_END:
550 case GTK_BUTTONBOX_CENTER:
551 if (orientation == GTK_ORIENTATION_HORIZONTAL)
552 requisition->width =
553 nvis_children*child_width + ((nvis_children-1)*spacing);
554 else
555 requisition->height =
556 nvis_children*child_height + ((nvis_children-1)*spacing);
557
558 break;
559 default:
560 g_assert_not_reached ();
561 break;
562 }
563
564 if (orientation == GTK_ORIENTATION_HORIZONTAL)
565 requisition->height = child_height;
566 else
567 requisition->width = child_width;
568 }
569
570 requisition->width += GTK_CONTAINER (box)->border_width * 2;
571 requisition->height += GTK_CONTAINER (box)->border_width * 2;
572 }
573
574 static void
gtk_button_box_size_allocate(GtkWidget * widget,GtkAllocation * allocation)575 gtk_button_box_size_allocate (GtkWidget *widget,
576 GtkAllocation *allocation)
577 {
578 GtkBox *base_box;
579 GtkButtonBox *box;
580 GtkBoxChild *child;
581 GList *children;
582 GtkAllocation child_allocation;
583 gint nvis_children;
584 gint n_secondaries;
585 gint child_width;
586 gint child_height;
587 gint x = 0;
588 gint y = 0;
589 gint secondary_x = 0;
590 gint secondary_y = 0;
591 gint width = 0;
592 gint height = 0;
593 gint childspace;
594 gint childspacing = 0;
595 GtkButtonBoxStyle layout;
596 gint spacing;
597 GtkOrientation orientation;
598
599 orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
600 base_box = GTK_BOX (widget);
601 box = GTK_BUTTON_BOX (widget);
602 spacing = base_box->spacing;
603 layout = box->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE
604 ? box->layout_style : gtk_button_box_kludge_get_layout_default (GTK_BUTTON_BOX (widget));
605 _gtk_button_box_child_requisition (widget,
606 &nvis_children,
607 &n_secondaries,
608 &child_width,
609 &child_height);
610 widget->allocation = *allocation;
611
612 if (orientation == GTK_ORIENTATION_HORIZONTAL)
613 width = allocation->width - GTK_CONTAINER (box)->border_width*2;
614 else
615 height = allocation->height - GTK_CONTAINER (box)->border_width*2;
616
617 switch (layout)
618 {
619 case GTK_BUTTONBOX_SPREAD:
620
621 if (orientation == GTK_ORIENTATION_HORIZONTAL)
622 {
623 childspacing = (width - (nvis_children * child_width))
624 / (nvis_children + 1);
625 x = allocation->x + GTK_CONTAINER (box)->border_width
626 + childspacing;
627 secondary_x = x + ((nvis_children - n_secondaries)
628 * (child_width + childspacing));
629 }
630 else
631 {
632 childspacing = (height - (nvis_children * child_height))
633 / (nvis_children + 1);
634 y = allocation->y + GTK_CONTAINER (box)->border_width
635 + childspacing;
636 secondary_y = y + ((nvis_children - n_secondaries)
637 * (child_height + childspacing));
638 }
639
640 break;
641
642 case GTK_BUTTONBOX_EDGE:
643
644 if (orientation == GTK_ORIENTATION_HORIZONTAL)
645 {
646 if (nvis_children >= 2)
647 {
648 childspacing = (width - (nvis_children * child_width))
649 / (nvis_children - 1);
650 x = allocation->x + GTK_CONTAINER (box)->border_width;
651 secondary_x = x + ((nvis_children - n_secondaries)
652 * (child_width + childspacing));
653 }
654 else
655 {
656 /* one or zero children, just center */
657 childspacing = width;
658 x = secondary_x = allocation->x
659 + (allocation->width - child_width) / 2;
660 }
661 }
662 else
663 {
664 if (nvis_children >= 2)
665 {
666 childspacing = (height - (nvis_children*child_height))
667 / (nvis_children-1);
668 y = allocation->y + GTK_CONTAINER (box)->border_width;
669 secondary_y = y + ((nvis_children - n_secondaries)
670 * (child_height + childspacing));
671 }
672 else
673 {
674 /* one or zero children, just center */
675 childspacing = height;
676 y = secondary_y = allocation->y
677 + (allocation->height - child_height) / 2;
678 }
679 }
680
681 break;
682
683 case GTK_BUTTONBOX_START:
684
685 if (orientation == GTK_ORIENTATION_HORIZONTAL)
686 {
687 childspacing = spacing;
688 x = allocation->x + GTK_CONTAINER (box)->border_width;
689 secondary_x = allocation->x + allocation->width
690 - child_width * n_secondaries
691 - spacing * (n_secondaries - 1)
692 - GTK_CONTAINER (box)->border_width;
693 }
694 else
695 {
696 childspacing = spacing;
697 y = allocation->y + GTK_CONTAINER (box)->border_width;
698 secondary_y = allocation->y + allocation->height
699 - child_height * n_secondaries
700 - spacing * (n_secondaries - 1)
701 - GTK_CONTAINER (box)->border_width;
702 }
703
704 break;
705
706 case GTK_BUTTONBOX_END:
707
708 if (orientation == GTK_ORIENTATION_HORIZONTAL)
709 {
710 childspacing = spacing;
711 x = allocation->x + allocation->width
712 - child_width * (nvis_children - n_secondaries)
713 - spacing * (nvis_children - n_secondaries - 1)
714 - GTK_CONTAINER (box)->border_width;
715 secondary_x = allocation->x + GTK_CONTAINER (box)->border_width;
716 }
717 else
718 {
719 childspacing = spacing;
720 y = allocation->y + allocation->height
721 - child_height * (nvis_children - n_secondaries)
722 - spacing * (nvis_children - n_secondaries - 1)
723 - GTK_CONTAINER (box)->border_width;
724 secondary_y = allocation->y + GTK_CONTAINER (box)->border_width;
725 }
726
727 break;
728
729 case GTK_BUTTONBOX_CENTER:
730
731 if (orientation == GTK_ORIENTATION_HORIZONTAL)
732 {
733 childspacing = spacing;
734 x = allocation->x +
735 (allocation->width
736 - (child_width * (nvis_children - n_secondaries)
737 + spacing * (nvis_children - n_secondaries - 1))) / 2
738 + (n_secondaries * child_width + n_secondaries * spacing) / 2;
739 secondary_x = allocation->x + GTK_CONTAINER (box)->border_width;
740 }
741 else
742 {
743 childspacing = spacing;
744 y = allocation->y +
745 (allocation->height
746 - (child_height * (nvis_children - n_secondaries)
747 + spacing * (nvis_children - n_secondaries - 1))) / 2
748 + (n_secondaries * child_height + n_secondaries * spacing) / 2;
749 secondary_y = allocation->y + GTK_CONTAINER (box)->border_width;
750 }
751
752 break;
753
754 default:
755 g_assert_not_reached ();
756 break;
757 }
758
759 if (orientation == GTK_ORIENTATION_HORIZONTAL)
760 {
761 y = allocation->y + (allocation->height - child_height) / 2;
762 childspace = child_width + childspacing;
763 }
764 else
765 {
766 x = allocation->x + (allocation->width - child_width) / 2;
767 childspace = child_height + childspacing;
768 }
769
770 children = GTK_BOX (box)->children;
771
772 while (children)
773 {
774 child = children->data;
775 children = children->next;
776
777 if (gtk_widget_get_visible (child->widget))
778 {
779 child_allocation.width = child_width;
780 child_allocation.height = child_height;
781
782 if (orientation == GTK_ORIENTATION_HORIZONTAL)
783 {
784 child_allocation.y = y;
785
786 if (child->is_secondary)
787 {
788 child_allocation.x = secondary_x;
789 secondary_x += childspace;
790 }
791 else
792 {
793 child_allocation.x = x;
794 x += childspace;
795 }
796
797 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
798 child_allocation.x = (allocation->x + allocation->width)
799 - (child_allocation.x + child_width - allocation->x);
800 }
801 else
802 {
803 child_allocation.x = x;
804
805 if (child->is_secondary)
806 {
807 child_allocation.y = secondary_y;
808 secondary_y += childspace;
809 }
810 else
811 {
812 child_allocation.y = y;
813 y += childspace;
814 }
815 }
816
817 gtk_widget_size_allocate (child->widget, &child_allocation);
818 }
819 }
820 }
821
822 #define __GTK_BUTTON_BOX_C__
823 #include "gtkaliasdef.c"
824