Added the Compute dialog box.
[pspp-builds.git] / src / ui / gui / psppire-vbuttonbox.c
1 /*
2     PSPPIRE --- A Graphical User Interface for PSPP
3     Copyright (C) 2007  Free Software Foundation
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18     02110-1301, USA. */
19
20
21 #include <config.h>
22
23 #include <glib.h>
24 #include <gtk/gtk.h>
25 #include <gtk/gtksignal.h>
26 #include "psppire-vbuttonbox.h"
27 #include "psppire-dialog.h"
28
29 #include <gtk/gtkbbox.h>
30
31 #include <gettext.h>
32
33 #define _(msgid) gettext (msgid)
34 #define N_(msgid) msgid
35
36
37 static void psppire_vbuttonbox_class_init          (PsppireVButtonBoxClass *);
38 static void psppire_vbuttonbox_init                (PsppireVButtonBox      *);
39
40 static void gtk_vbutton_box_size_request  (GtkWidget      *widget,
41                                            GtkRequisition *requisition);
42 static void gtk_vbutton_box_size_allocate (GtkWidget      *widget,
43                                            GtkAllocation  *allocation);
44
45
46 static GtkButtonBoxStyle default_layout_style = GTK_BUTTONBOX_EDGE;
47
48 GType
49 psppire_vbutton_box_get_type (void)
50 {
51   static GType vbuttonbox_type = 0;
52
53   if (!vbuttonbox_type)
54     {
55       static const GTypeInfo vbuttonbox_info =
56       {
57         sizeof (PsppireVButtonBoxClass),
58         NULL, /* base_init */
59         NULL, /* base_finalize */
60         (GClassInitFunc) psppire_vbuttonbox_class_init,
61         NULL, /* class_finalize */
62         NULL, /* class_data */
63         sizeof (PsppireVButtonBox),
64         0,
65         (GInstanceInitFunc) psppire_vbuttonbox_init,
66       };
67
68       vbuttonbox_type = g_type_register_static (PSPPIRE_BUTTONBOX_TYPE,
69                                             "PsppireVButtonBox", &vbuttonbox_info, 0);
70     }
71
72   return vbuttonbox_type;
73 }
74
75 static void
76 psppire_vbuttonbox_class_init (PsppireVButtonBoxClass *class)
77 {
78   GtkWidgetClass *widget_class;
79
80   widget_class = (GtkWidgetClass*) class;
81
82   widget_class->size_request = gtk_vbutton_box_size_request;
83   widget_class->size_allocate = gtk_vbutton_box_size_allocate;
84 }
85
86
87 static void
88 psppire_vbuttonbox_init (PsppireVButtonBox *vbuttonbox)
89 {
90 }
91
92
93 GtkWidget*
94 psppire_vbuttonbox_new (void)
95 {
96   PsppireVButtonBox *vbuttonbox ;
97
98   vbuttonbox = g_object_new (psppire_vbutton_box_get_type (), NULL);
99
100   return GTK_WIDGET (vbuttonbox) ;
101 }
102
103
104
105 /* The following two functions are lifted verbatim from
106    the Gtk2.10.6 library */
107
108 static void
109 gtk_vbutton_box_size_request (GtkWidget      *widget,
110                               GtkRequisition *requisition)
111 {
112   GtkBox *box;
113   GtkButtonBox *bbox;
114   gint nvis_children;
115   gint child_width;
116   gint child_height;
117   gint spacing;
118   GtkButtonBoxStyle layout;
119
120   box = GTK_BOX (widget);
121   bbox = GTK_BUTTON_BOX (widget);
122
123   spacing = box->spacing;
124   layout = bbox->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE
125           ? bbox->layout_style : default_layout_style;
126
127   _psppire_button_box_child_requisition (widget,
128                                          &nvis_children,
129                                          NULL,
130                                          &child_width,
131                                          &child_height);
132
133   if (nvis_children == 0)
134     {
135       requisition->width = 0;
136       requisition->height = 0;
137     }
138   else
139     {
140       switch (layout)
141       {
142       case GTK_BUTTONBOX_SPREAD:
143         requisition->height =
144                 nvis_children*child_height + ((nvis_children+1)*spacing);
145         break;
146       case GTK_BUTTONBOX_EDGE:
147       case GTK_BUTTONBOX_START:
148       case GTK_BUTTONBOX_END:
149         requisition->height =
150                 nvis_children*child_height + ((nvis_children-1)*spacing);
151         break;
152       default:
153             g_assert_not_reached();
154             break;
155       }
156       requisition->width = child_width;
157     }
158
159   requisition->width += GTK_CONTAINER (box)->border_width * 2;
160   requisition->height += GTK_CONTAINER (box)->border_width * 2;
161 }
162
163
164
165 static void
166 gtk_vbutton_box_size_allocate (GtkWidget     *widget,
167                                GtkAllocation *allocation)
168 {
169   GtkBox *base_box;
170   GtkButtonBox *box;
171   GtkBoxChild *child;
172   GList *children;
173   GtkAllocation child_allocation;
174   gint nvis_children;
175   gint n_secondaries;
176   gint child_width;
177   gint child_height;
178   gint x = 0;
179   gint y = 0;
180   gint secondary_y = 0;
181   gint height;
182   gint childspace;
183   gint childspacing = 0;
184   GtkButtonBoxStyle layout;
185   gint spacing;
186
187   base_box = GTK_BOX (widget);
188   box = GTK_BUTTON_BOX (widget);
189   spacing = base_box->spacing;
190   layout = box->layout_style != GTK_BUTTONBOX_DEFAULT_STYLE
191           ? box->layout_style : default_layout_style;
192   _psppire_button_box_child_requisition (widget,
193                                      &nvis_children,
194                                      &n_secondaries,
195                                      &child_width,
196                                      &child_height);
197   widget->allocation = *allocation;
198   height = allocation->height - GTK_CONTAINER (box)->border_width*2;
199   switch (layout)
200   {
201   case GTK_BUTTONBOX_SPREAD:
202     childspacing = (height - (nvis_children * child_height)) / (nvis_children + 1);
203     y = allocation->y + GTK_CONTAINER (box)->border_width + childspacing;
204     secondary_y = y + ((nvis_children - n_secondaries) * (child_height + childspacing));
205     break;
206   case GTK_BUTTONBOX_EDGE:
207     if (nvis_children >= 2)
208       {
209         childspacing = (height - (nvis_children*child_height)) / (nvis_children-1);
210         y = allocation->y + GTK_CONTAINER (box)->border_width;
211         secondary_y = y + ((nvis_children - n_secondaries) * (child_height + childspacing));
212       }
213     else
214       {
215         /* one or zero children, just center */
216         childspacing = height;
217         y = secondary_y = allocation->y + (allocation->height - child_height) / 2;
218       }
219     break;
220   case GTK_BUTTONBOX_START:
221     childspacing = spacing;
222     y = allocation->y + GTK_CONTAINER (box)->border_width;
223     secondary_y = allocation->y + allocation->height
224       - child_height * n_secondaries
225       - spacing * (n_secondaries - 1)
226       - GTK_CONTAINER (box)->border_width;
227     break;
228   case GTK_BUTTONBOX_END:
229     childspacing = spacing;
230     y = allocation->y + allocation->height
231       - child_height * (nvis_children - n_secondaries)
232       - spacing * (nvis_children - n_secondaries - 1)
233       - GTK_CONTAINER (box)->border_width;
234     secondary_y = allocation->y + GTK_CONTAINER (box)->border_width;
235     break;
236   default:
237     g_assert_not_reached();
238     break;
239   }
240
241   x = allocation->x + (allocation->width - child_width) / 2;
242   childspace = child_height + childspacing;
243
244   children = GTK_BOX (box)->children;
245
246   while (children)
247     {
248       child = children->data;
249       children = children->next;
250
251       if (GTK_WIDGET_VISIBLE (child->widget))
252         {
253           child_allocation.width = child_width;
254           child_allocation.height = child_height;
255           child_allocation.x = x;
256
257           if (child->is_secondary)
258             {
259               child_allocation.y = secondary_y;
260               secondary_y += childspace;
261             }
262           else
263             {
264               child_allocation.y = y;
265               y += childspace;
266             }
267
268           gtk_widget_size_allocate (child->widget, &child_allocation);
269         }
270     }
271 }
272