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