]> Pileus Git - ~andy/gtk/blob - gtk/gtkvbbox.c
Fixes #136082 and #135265, patch by Morten Welinder.
[~andy/gtk] / gtk / gtkvbbox.c
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 "gtkvbbox.h"
29
30
31 static void gtk_vbutton_box_class_init    (GtkVButtonBoxClass   *klass);
32 static void gtk_vbutton_box_init          (GtkVButtonBox        *box);
33 static void gtk_vbutton_box_size_request  (GtkWidget      *widget,
34                                            GtkRequisition *requisition);
35 static void gtk_vbutton_box_size_allocate (GtkWidget      *widget,
36                                            GtkAllocation  *allocation);
37
38 static gint default_spacing = 10;
39 static GtkButtonBoxStyle default_layout_style = GTK_BUTTONBOX_EDGE;
40
41 GType
42 gtk_vbutton_box_get_type (void)
43 {
44   static GType vbutton_box_type = 0;
45
46   if (!vbutton_box_type)
47     {
48       static const GTypeInfo vbutton_box_info =
49       {
50         sizeof (GtkVButtonBoxClass),
51         NULL,           /* base_init */
52         NULL,           /* base_finalize */
53         (GClassInitFunc) gtk_vbutton_box_class_init,
54         NULL,           /* class_finalize */
55         NULL,           /* class_data */
56         sizeof (GtkVButtonBox),
57         0,              /* n_preallocs */
58         (GInstanceInitFunc) gtk_vbutton_box_init,
59       };
60
61       vbutton_box_type =
62         g_type_register_static (GTK_TYPE_BUTTON_BOX, "GtkVButtonBox",
63                                 &vbutton_box_info, 0);
64     }
65
66   return vbutton_box_type;
67 }
68
69 static void
70 gtk_vbutton_box_class_init (GtkVButtonBoxClass *class)
71 {
72   GtkWidgetClass *widget_class;
73
74   widget_class = (GtkWidgetClass*) class;
75
76   widget_class->size_request = gtk_vbutton_box_size_request;
77   widget_class->size_allocate = gtk_vbutton_box_size_allocate;
78 }
79
80 static void
81 gtk_vbutton_box_init (GtkVButtonBox *vbutton_box)
82 {
83   /* button_box_init has done everything allready */
84 }
85
86 GtkWidget*
87 gtk_vbutton_box_new (void)
88 {
89   GtkVButtonBox *vbutton_box;
90
91   vbutton_box = g_object_new (GTK_TYPE_VBUTTON_BOX, NULL);
92
93   return GTK_WIDGET (vbutton_box);
94 }
95
96
97
98 /* set default value for spacing */
99
100 void
101 gtk_vbutton_box_set_spacing_default (gint spacing)
102 {
103   default_spacing = spacing;
104 }
105
106
107 /* set default value for layout style */
108
109 void
110 gtk_vbutton_box_set_layout_default (GtkButtonBoxStyle layout)
111 {
112   g_return_if_fail (layout >= GTK_BUTTONBOX_DEFAULT_STYLE &&
113                     layout <= GTK_BUTTONBOX_END);
114
115   default_layout_style = layout;
116 }
117
118 /* get default value for spacing */
119
120 gint
121 gtk_vbutton_box_get_spacing_default (void)
122 {
123   return default_spacing;
124 }
125
126
127
128 /* get default value for layout style */
129
130 GtkButtonBoxStyle
131 gtk_vbutton_box_get_layout_default (void)
132 {
133   return default_layout_style;
134 }
135
136
137
138
139 static void
140 gtk_vbutton_box_size_request (GtkWidget      *widget,
141                               GtkRequisition *requisition)
142 {
143   GtkBox *box;
144   GtkButtonBox *bbox;
145   gint nvis_children;
146   gint child_width;
147   gint child_height;
148   gint spacing;
149   GtkButtonBoxStyle layout;
150   
151   box = GTK_BOX (widget);
152   bbox = GTK_BUTTON_BOX (widget);
153
154   spacing = box->spacing;
155   layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE
156           ? bbox->layout_style : default_layout_style;
157   
158   _gtk_button_box_child_requisition (widget,
159                                      &nvis_children,
160                                      NULL,
161                                      &child_width,
162                                      &child_height);
163
164   if (nvis_children == 0)
165     {
166       requisition->width = 0; 
167       requisition->height = 0;
168     }
169   else
170     {
171       switch (layout)
172       {
173       case GTK_BUTTONBOX_SPREAD:
174         requisition->height =
175                 nvis_children*child_height + ((nvis_children+1)*spacing);
176         break;
177       case GTK_BUTTONBOX_EDGE:
178       case GTK_BUTTONBOX_START:
179       case GTK_BUTTONBOX_END:
180         requisition->height =
181                 nvis_children*child_height + ((nvis_children-1)*spacing);
182         break;
183       default:
184             g_assert_not_reached();
185             break;
186       }
187           
188       requisition->width = child_width;
189     }
190           
191   requisition->width += GTK_CONTAINER (box)->border_width * 2;
192   requisition->height += GTK_CONTAINER (box)->border_width * 2;
193 }
194
195
196
197 static void
198 gtk_vbutton_box_size_allocate (GtkWidget     *widget,
199                                GtkAllocation *allocation)
200 {
201   GtkBox *base_box;
202   GtkButtonBox *box;
203   GtkVButtonBox *hbox;
204   GtkBoxChild *child;
205   GList *children;
206   GtkAllocation child_allocation;
207   gint nvis_children;
208   gint n_secondaries;
209   gint child_width;
210   gint child_height;
211   gint x = 0;
212   gint y = 0;
213   gint secondary_y = 0;
214   gint height;
215   gint childspace;
216   gint childspacing = 0;
217   GtkButtonBoxStyle layout;
218   gint spacing;
219   
220   base_box = GTK_BOX (widget);
221   box = GTK_BUTTON_BOX (widget);
222   hbox = GTK_VBUTTON_BOX (widget);
223   spacing = base_box->spacing;
224   layout = box->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE
225           ? box->layout_style : default_layout_style;
226   _gtk_button_box_child_requisition (widget,
227                                      &nvis_children,
228                                      &n_secondaries,
229                                      &child_width,
230                                      &child_height);
231   widget->allocation = *allocation;
232   height = allocation->height - GTK_CONTAINER (box)->border_width*2;
233   switch (layout)
234   {
235   case GTK_BUTTONBOX_SPREAD:
236     childspacing = (height - (nvis_children * child_height)) / (nvis_children + 1);
237     y = allocation->y + GTK_CONTAINER (box)->border_width + childspacing;
238     secondary_y = y + ((nvis_children - n_secondaries) * (child_height + childspacing));
239     break;
240   case GTK_BUTTONBOX_EDGE:
241     if (nvis_children >= 2)
242       {
243         childspacing = (height - (nvis_children*child_height)) / (nvis_children-1);
244         y = allocation->y + GTK_CONTAINER (box)->border_width;
245         secondary_y = y + ((nvis_children - n_secondaries) * (child_height + childspacing));
246       }
247     else
248       {
249         /* one or zero children, just center */
250         childspacing = height;
251         y = secondary_y = allocation->y + (allocation->height - child_height) / 2;
252       }
253     break;
254   case GTK_BUTTONBOX_START:
255     childspacing = spacing;
256     y = allocation->y + GTK_CONTAINER (box)->border_width;
257     secondary_y = allocation->y + allocation->height
258       - child_height * n_secondaries
259       - spacing * (n_secondaries - 1)
260       - GTK_CONTAINER (box)->border_width;
261     break;
262   case GTK_BUTTONBOX_END:
263     childspacing = spacing;
264     y = allocation->y + allocation->height 
265       - child_height * (nvis_children - n_secondaries)
266       - spacing * (nvis_children - n_secondaries - 1)
267       - GTK_CONTAINER (box)->border_width;
268     secondary_y = allocation->y + GTK_CONTAINER (box)->border_width;
269     break;
270   default:
271     g_assert_not_reached();
272     break;
273   }
274                   
275   
276   x = allocation->x + (allocation->width - child_width) / 2;
277   childspace = child_height + childspacing;
278
279   children = GTK_BOX (box)->children;
280           
281   while (children)
282     {
283       child = children->data;
284       children = children->next;
285
286       if (GTK_WIDGET_VISIBLE (child->widget))
287         {
288           child_allocation.width = child_width;
289           child_allocation.height = child_height;
290           child_allocation.x = x;
291           
292           if (child->is_secondary)
293             {
294               child_allocation.y = secondary_y;
295               secondary_y += childspace;
296             }
297           else
298             {
299               child_allocation.y = y;
300               y += childspace;
301             }
302           
303           gtk_widget_size_allocate (child->widget, &child_allocation);
304         }
305     }
306 }
307   
308