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