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