]> Pileus Git - ~andy/gtk/blob - gtk/gtkvbox.c
Changed LGPL address for FSF in all .h and .c files
[~andy/gtk] / gtk / gtkvbox.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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 #include "gtkvbox.h"
20
21
22 static void gtk_vbox_class_init    (GtkVBoxClass   *klass);
23 static void gtk_vbox_init          (GtkVBox        *box);
24 static void gtk_vbox_size_request  (GtkWidget      *widget,
25                                     GtkRequisition *requisition);
26 static void gtk_vbox_size_allocate (GtkWidget      *widget,
27                                     GtkAllocation  *allocation);
28
29
30 guint
31 gtk_vbox_get_type ()
32 {
33   static guint vbox_type = 0;
34
35   if (!vbox_type)
36     {
37       GtkTypeInfo vbox_info =
38       {
39         "GtkVBox",
40         sizeof (GtkVBox),
41         sizeof (GtkVBoxClass),
42         (GtkClassInitFunc) gtk_vbox_class_init,
43         (GtkObjectInitFunc) gtk_vbox_init,
44         (GtkArgSetFunc) NULL,
45         (GtkArgGetFunc) NULL,
46       };
47
48       vbox_type = gtk_type_unique (gtk_box_get_type (), &vbox_info);
49     }
50
51   return vbox_type;
52 }
53
54 static void
55 gtk_vbox_class_init (GtkVBoxClass *class)
56 {
57   GtkWidgetClass *widget_class;
58
59   widget_class = (GtkWidgetClass*) class;
60
61   widget_class->size_request = gtk_vbox_size_request;
62   widget_class->size_allocate = gtk_vbox_size_allocate;
63 }
64
65 static void
66 gtk_vbox_init (GtkVBox *vbox)
67 {
68 }
69
70 GtkWidget*
71 gtk_vbox_new (gint homogeneous,
72               gint spacing)
73 {
74   GtkVBox *vbox;
75
76   vbox = gtk_type_new (gtk_vbox_get_type ());
77
78   GTK_BOX (vbox)->spacing = spacing;
79   GTK_BOX (vbox)->homogeneous = homogeneous ? TRUE : FALSE;
80
81   return GTK_WIDGET (vbox);
82 }
83
84
85 static void
86 gtk_vbox_size_request (GtkWidget      *widget,
87                        GtkRequisition *requisition)
88 {
89   GtkBox *box;
90   GtkBoxChild *child;
91   GList *children;
92   gint nvis_children;
93   gint height;
94
95   g_return_if_fail (widget != NULL);
96   g_return_if_fail (GTK_IS_VBOX (widget));
97   g_return_if_fail (requisition != NULL);
98
99   box = GTK_BOX (widget);
100   requisition->width = 0;
101   requisition->height = 0;
102   nvis_children = 0;
103
104   children = box->children;
105   while (children)
106     {
107       child = children->data;
108       children = children->next;
109
110       if (GTK_WIDGET_VISIBLE (child->widget))
111         {
112           gtk_widget_size_request (child->widget, &child->widget->requisition);
113
114           if (box->homogeneous)
115             {
116               height = child->widget->requisition.height + child->padding * 2;
117               requisition->height = MAX (requisition->height, height);
118             }
119           else
120             {
121               requisition->height += child->widget->requisition.height + child->padding * 2;
122             }
123
124           requisition->width = MAX (requisition->width, child->widget->requisition.width);
125
126           nvis_children += 1;
127         }
128     }
129
130   if (nvis_children > 0)
131     {
132       if (box->homogeneous)
133         requisition->height *= nvis_children;
134       requisition->height += (nvis_children - 1) * box->spacing;
135     }
136
137   requisition->width += GTK_CONTAINER (box)->border_width * 2;
138   requisition->height += GTK_CONTAINER (box)->border_width * 2;
139 }
140
141 static void
142 gtk_vbox_size_allocate (GtkWidget     *widget,
143                         GtkAllocation *allocation)
144 {
145   GtkBox *box;
146   GtkBoxChild *child;
147   GList *children;
148   GtkAllocation child_allocation;
149   gint nvis_children;
150   gint nexpand_children;
151   gint child_height;
152   gint height;
153   gint extra;
154   gint y;
155
156   g_return_if_fail (widget != NULL);
157   g_return_if_fail (GTK_IS_VBOX (widget));
158   g_return_if_fail (allocation != NULL);
159
160   box = GTK_BOX (widget);
161   widget->allocation = *allocation;
162
163   nvis_children = 0;
164   nexpand_children = 0;
165   children = box->children;
166
167   while (children)
168     {
169       child = children->data;
170       children = children->next;
171
172       if (GTK_WIDGET_VISIBLE (child->widget))
173         {
174           nvis_children += 1;
175           if (child->expand)
176             nexpand_children += 1;
177         }
178     }
179
180   if (nvis_children > 0)
181     {
182       if (box->homogeneous)
183         {
184           height = (allocation->height -
185                    GTK_CONTAINER (box)->border_width * 2 -
186                    (nvis_children - 1) * box->spacing);
187           extra = height / nvis_children;
188         }
189       else if (nexpand_children > 0)
190         {
191           height = (gint)allocation->height - (gint)widget->requisition.height;
192           extra = height / nexpand_children;
193         }
194       else
195         {
196           height = 0;
197           extra = 0;
198         }
199
200       y = allocation->y + GTK_CONTAINER (box)->border_width;
201       child_allocation.x = allocation->x + GTK_CONTAINER (box)->border_width;
202       child_allocation.width = MAX (1, allocation->width - GTK_CONTAINER (box)->border_width * 2);
203
204       children = box->children;
205       while (children)
206         {
207           child = children->data;
208           children = children->next;
209
210           if ((child->pack == GTK_PACK_START) && GTK_WIDGET_VISIBLE (child->widget))
211             {
212               if (box->homogeneous)
213                 {
214                   if (nvis_children == 1)
215                     child_height = height;
216                   else
217                     child_height = extra;
218
219                   nvis_children -= 1;
220                   height -= extra;
221                 }
222               else
223                 {
224                   child_height = child->widget->requisition.height + child->padding * 2;
225
226                   if (child->expand)
227                     {
228                       if (nexpand_children == 1)
229                         child_height += height;
230                       else
231                         child_height += extra;
232
233                       nexpand_children -= 1;
234                       height -= extra;
235                     }
236                 }
237
238               if (child->fill)
239                 {
240                   child_allocation.height = MAX (1, child_height - child->padding * 2);
241                   child_allocation.y = y + child->padding;
242                 }
243               else
244                 {
245                   child_allocation.height = child->widget->requisition.height;
246                   child_allocation.y = y + (child_height - child_allocation.height) / 2;
247                 }
248
249               gtk_widget_size_allocate (child->widget, &child_allocation);
250
251               y += child_height + box->spacing;
252             }
253         }
254
255       y = allocation->y + allocation->height - GTK_CONTAINER (box)->border_width;
256
257       children = box->children;
258       while (children)
259         {
260           child = children->data;
261           children = children->next;
262
263           if ((child->pack == GTK_PACK_END) && GTK_WIDGET_VISIBLE (child->widget))
264             {
265               if (box->homogeneous)
266                 {
267                   if (nvis_children == 1)
268                     child_height = height;
269                   else
270                     child_height = extra;
271
272                   nvis_children -= 1;
273                   height -= extra;
274                 }
275               else
276                 {
277                   child_height = child->widget->requisition.height + child->padding * 2;
278
279                   if (child->expand)
280                     {
281                       if (nexpand_children == 1)
282                         child_height += height;
283                       else
284                         child_height += extra;
285
286                       nexpand_children -= 1;
287                       height -= extra;
288                     }
289                 }
290
291               if (child->fill)
292                 {
293                   child_allocation.height = MAX (1, child_height - child->padding * 2);
294                   child_allocation.y = y + child->padding - child_height;
295                 }
296               else
297                 {
298                   child_allocation.height = child->widget->requisition.height;
299                   child_allocation.y = y + (child_height - child_allocation.height) / 2 - child_height;
300                 }
301
302               gtk_widget_size_allocate (child->widget, &child_allocation);
303
304               y -= (child_height + box->spacing);
305             }
306         }
307     }
308 }