]> Pileus Git - ~andy/gtk/blob - gtk/gtkbbox.c
81b02d401e582ccfed855133fb857c0f0fc57c07
[~andy/gtk] / gtk / gtkbbox.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 "gtkbbox.h"
28 #include "gtkintl.h"
29
30 enum {
31   PROP_0,
32   PROP_LAYOUT_STYLE,
33   PROP_LAST
34 };
35
36 static void gtk_button_box_class_init    (GtkButtonBoxClass   *klass);
37 static void gtk_button_box_init          (GtkButtonBox        *box);
38 static void gtk_button_box_set_property  (GObject         *object,
39                                           guint            prop_id,
40                                           const GValue    *value,
41                                           GParamSpec      *pspec);
42 static void gtk_button_box_get_property  (GObject         *object,
43                                           guint            prop_id,
44                                           GValue          *value,
45                                           GParamSpec      *pspec);
46
47 #define DEFAULT_CHILD_MIN_WIDTH 85
48 #define DEFAULT_CHILD_MIN_HEIGHT 27
49 #define DEFAULT_CHILD_IPAD_X 4
50 #define DEFAULT_CHILD_IPAD_Y 0
51
52 GtkType
53 gtk_button_box_get_type (void)
54 {
55   static GtkType button_box_type = 0;
56
57   if (!button_box_type)
58     {
59       static const GtkTypeInfo button_box_info =
60       {
61         "GtkButtonBox",
62         sizeof (GtkButtonBox),
63         sizeof (GtkButtonBoxClass),
64         (GtkClassInitFunc) gtk_button_box_class_init,
65         (GtkObjectInitFunc) gtk_button_box_init,
66         /* reserved_1 */ NULL,
67         /* reserved_2 */ NULL,
68         (GtkClassInitFunc) NULL,
69       };
70
71       button_box_type = gtk_type_unique (gtk_box_get_type (), &button_box_info);
72     }
73
74   return button_box_type;
75 }
76
77 static void
78 gtk_button_box_class_init (GtkButtonBoxClass *class)
79 {
80   GtkWidgetClass *widget_class;
81   GObjectClass *gobject_class;
82
83   gobject_class = G_OBJECT_CLASS (class);
84   widget_class = (GtkWidgetClass*) class;
85
86   gobject_class->set_property = gtk_button_box_set_property;
87   gobject_class->get_property = gtk_button_box_get_property;
88   
89   /* FIXME we need to override the "spacing" property on GtkBox once
90    * libgobject allows that.
91    */
92
93   gtk_widget_class_install_style_property (widget_class,
94                                            g_param_spec_int ("child_min_width",
95                                                              _("Minimum child width"),
96                                                              _("Minimum width of buttons inside the box"),
97                                                              0,
98                                                              G_MAXINT,
99                                                              DEFAULT_CHILD_MIN_WIDTH,
100                                                              G_PARAM_READABLE));
101
102   gtk_widget_class_install_style_property (widget_class,
103                                            g_param_spec_int ("child_min_height",
104                                                              _("Minimum child height"),
105                                                              _("Minimum height of buttons inside the box"),
106                                                              0,
107                                                              G_MAXINT,
108                                                              DEFAULT_CHILD_MIN_HEIGHT,
109                                                              G_PARAM_READABLE));
110
111   gtk_widget_class_install_style_property (widget_class,
112                                            g_param_spec_int ("child_internal_pad_x",
113                                                              _("Child internal width padding"),
114                                                              _("Amount to increase child's size on either side"),
115                                                              0,
116                                                              G_MAXINT,
117                                                              DEFAULT_CHILD_IPAD_X,
118                                                              G_PARAM_READABLE));
119
120   gtk_widget_class_install_style_property (widget_class,
121                                            g_param_spec_int ("child_internal_pad_y",
122                                                              _("Child internal height padding"),
123                                                              _("Amount to increase child's size on the top and bottom"),
124                                                              0,
125                                                              G_MAXINT,
126                                                              DEFAULT_CHILD_IPAD_Y,
127                                                              G_PARAM_READABLE));
128   g_object_class_install_property (gobject_class,
129                                    PROP_LAYOUT_STYLE,
130                                    g_param_spec_enum ("layout_style",
131                                                       _("Layout style"),
132                                                       _("How to layout the buttons in the box. Possible values are default, spread, edge, start and end"),
133                                                       GTK_TYPE_BUTTON_BOX_STYLE,
134                                                       GTK_BUTTONBOX_DEFAULT_STYLE,
135                                                       G_PARAM_READWRITE));
136 }
137
138 static void
139 gtk_button_box_init (GtkButtonBox *button_box)
140 {
141   GTK_BOX (button_box)->spacing = 0;
142   button_box->child_min_width = GTK_BUTTONBOX_DEFAULT;
143   button_box->child_min_height = GTK_BUTTONBOX_DEFAULT;
144   button_box->child_ipad_x = GTK_BUTTONBOX_DEFAULT;
145   button_box->child_ipad_y = GTK_BUTTONBOX_DEFAULT;
146   button_box->layout_style = GTK_BUTTONBOX_DEFAULT_STYLE;
147 }
148
149 static void
150 gtk_button_box_set_property (GObject         *object,
151                              guint            prop_id,
152                              const GValue    *value,
153                              GParamSpec      *pspec)
154 {
155   switch (prop_id) 
156     {
157     case PROP_LAYOUT_STYLE:
158       gtk_button_box_set_layout (GTK_BUTTON_BOX (object),
159                                  g_value_get_enum (value));
160       break;
161     default:
162       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
163       break;
164     }
165 }
166
167 static void
168 gtk_button_box_get_property (GObject         *object,
169                              guint            prop_id,
170                              GValue          *value,
171                              GParamSpec      *pspec)
172 {
173   switch (prop_id)
174     {
175     case PROP_LAYOUT_STYLE:
176       g_value_set_enum (value, GTK_BUTTON_BOX (object)->layout_style);
177       break;
178     default:
179       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
180       break;
181     }
182 }
183
184
185
186 /* set per widget values for spacing, child size and child internal padding */
187
188 void gtk_button_box_set_child_size (GtkButtonBox *widget, gint width, gint height)
189 {
190   widget->child_min_width = width;
191   widget->child_min_height = height;
192 }
193
194 void gtk_button_box_set_child_ipadding (GtkButtonBox *widget,
195                                         gint ipad_x, gint ipad_y)
196 {
197   widget->child_ipad_x = ipad_x;
198   widget->child_ipad_y = ipad_y;
199 }
200
201 void gtk_button_box_set_layout (GtkButtonBox *widget, 
202                                 GtkButtonBoxStyle layout_style)
203 {
204   g_return_if_fail (layout_style >= GTK_BUTTONBOX_DEFAULT_STYLE &&
205                     layout_style <= GTK_BUTTONBOX_END);
206
207   if (widget->layout_style != layout_style)
208     {
209       widget->layout_style = layout_style;
210       g_object_notify (G_OBJECT (widget), "layout_style");
211       gtk_widget_queue_resize (GTK_WIDGET (widget));
212     }
213 }
214
215
216 /* get per widget values for spacing, child size and child internal padding */
217
218 void gtk_button_box_get_child_size (GtkButtonBox *widget,
219                                      gint *width, gint *height)
220 {
221   *width  = widget->child_min_width;
222   *height = widget->child_min_height;
223 }
224
225 void gtk_button_box_get_child_ipadding (GtkButtonBox *widget,
226                                          gint* ipad_x, gint *ipad_y)
227 {
228   *ipad_x = widget->child_ipad_x;
229   *ipad_y = widget->child_ipad_y;
230 }
231
232 GtkButtonBoxStyle gtk_button_box_get_layout (GtkButtonBox *widget)
233 {
234   return widget->layout_style;
235 }
236
237
238
239 /* Ask children how much space they require and round up 
240    to match minimum size and internal padding.
241    Returns the size each single child should have. */
242 void
243 _gtk_button_box_child_requisition (GtkWidget *widget,
244                                    int *nvis_children,
245                                    int *width,
246                                    int *height)
247 {
248   GtkButtonBox *bbox;
249   GtkBoxChild *child;
250   GList *children;
251   gint nchildren;
252   gint needed_width;
253   gint needed_height;
254   GtkRequisition child_requisition;
255   gint ipad_w;
256   gint ipad_h;
257   gint width_default;
258   gint height_default;
259   gint ipad_x_default;
260   gint ipad_y_default;
261   
262   gint child_min_width;
263   gint child_min_height;
264   gint ipad_x;
265   gint ipad_y;
266   
267   g_return_if_fail (widget != NULL);
268   g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
269
270   bbox = GTK_BUTTON_BOX (widget);
271
272   gtk_widget_style_get (widget,
273                         "child_min_width",
274                         &width_default,
275                         "child_min_height",
276                         &height_default,
277                         "child_internal_pad_x",
278                         &ipad_x_default,
279                         "child_internal_pad_y",
280                         &ipad_y_default, NULL);
281   
282   child_min_width = bbox->child_min_width   != GTK_BUTTONBOX_DEFAULT
283           ? bbox->child_min_width : width_default;
284   child_min_height = bbox->child_min_height !=GTK_BUTTONBOX_DEFAULT
285           ? bbox->child_min_height : height_default;
286   ipad_x = bbox->child_ipad_x != GTK_BUTTONBOX_DEFAULT
287           ? bbox->child_ipad_x : ipad_x_default;
288   ipad_y = bbox->child_ipad_y != GTK_BUTTONBOX_DEFAULT
289           ? bbox->child_ipad_y : ipad_y_default;
290
291   nchildren = 0;
292   children = GTK_BOX(bbox)->children;
293   needed_width = child_min_width;
294   needed_height = child_min_height;  
295   ipad_w = ipad_x * 2;
296   ipad_h = ipad_y * 2;
297   
298   while (children)
299     {
300       child = children->data;
301       children = children->next;
302
303       if (GTK_WIDGET_VISIBLE (child->widget))
304         {
305           nchildren += 1;
306           gtk_widget_size_request (child->widget, &child_requisition);
307           if (child_requisition.width + ipad_w > needed_width)
308                   needed_width = child_requisition.width + ipad_w;
309           if (child_requisition.height + ipad_h > needed_height)
310                   needed_height = child_requisition.height + ipad_h;
311         }
312     }
313   
314   *nvis_children = nchildren;
315   *width = needed_width;
316   *height = needed_height;
317 }