Added the Compute dialog box.
[pspp-builds.git] / src / ui / gui / psppire-hbuttonbox.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-hbuttonbox.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_hbuttonbox_class_init          (PsppireHButtonBoxClass *);
38 static void psppire_hbuttonbox_init                (PsppireHButtonBox      *);
39
40 static void gtk_hbutton_box_size_request  (GtkWidget      *widget,
41                                            GtkRequisition *requisition);
42 static void gtk_hbutton_box_size_allocate (GtkWidget      *widget,
43                                            GtkAllocation  *allocation);
44
45
46 static GtkButtonBoxStyle default_layout_style = GTK_BUTTONBOX_EDGE;
47
48 GType
49 psppire_hbutton_box_get_type (void)
50 {
51   static GType hbuttonbox_type = 0;
52
53   if (!hbuttonbox_type)
54     {
55       static const GTypeInfo hbuttonbox_info =
56       {
57         sizeof (PsppireHButtonBoxClass),
58         NULL, /* base_init */
59         NULL, /* base_finalize */
60         (GClassInitFunc) psppire_hbuttonbox_class_init,
61         NULL, /* class_finalize */
62         NULL, /* class_data */
63         sizeof (PsppireHButtonBox),
64         0,
65         (GInstanceInitFunc) psppire_hbuttonbox_init,
66       };
67
68       hbuttonbox_type = g_type_register_static (PSPPIRE_BUTTONBOX_TYPE,
69                                             "PsppireHButtonBox", &hbuttonbox_info, 0);
70     }
71
72   return hbuttonbox_type;
73 }
74
75 static void
76 psppire_hbuttonbox_class_init (PsppireHButtonBoxClass *class)
77 {
78   GtkWidgetClass *widget_class;
79
80   widget_class = (GtkWidgetClass*) class;
81
82   widget_class->size_request = gtk_hbutton_box_size_request;
83   widget_class->size_allocate = gtk_hbutton_box_size_allocate;
84 }
85
86
87 static void
88 psppire_hbuttonbox_init (PsppireHButtonBox *hbuttonbox)
89 {
90 }
91
92
93 GtkWidget*
94 psppire_hbuttonbox_new (void)
95 {
96   PsppireHButtonBox *hbuttonbox ;
97
98   hbuttonbox = g_object_new (psppire_hbutton_box_get_type (), NULL);
99
100   return GTK_WIDGET (hbuttonbox) ;
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_hbutton_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->width =
144               nvis_children*child_width + ((nvis_children+1)*spacing);
145       break;
146     case GTK_BUTTONBOX_EDGE:
147     case GTK_BUTTONBOX_START:
148     case GTK_BUTTONBOX_END:
149       requisition->width = nvis_children*child_width + ((nvis_children-1)*spacing);
150       break;
151     default:
152       g_assert_not_reached();
153       break;
154     }
155
156     requisition->height = child_height;
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_hbutton_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 secondary_x = 0;
180   gint y = 0;
181   gint width;
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   width = allocation->width - GTK_CONTAINER (box)->border_width*2;
199   switch (layout)
200   {
201   case GTK_BUTTONBOX_SPREAD:
202     childspacing = (width - (nvis_children * child_width)) / (nvis_children + 1);
203     x = allocation->x + GTK_CONTAINER (box)->border_width + childspacing;
204     secondary_x = x + ((nvis_children - n_secondaries) * (child_width + childspacing));
205     break;
206   case GTK_BUTTONBOX_EDGE:
207     if (nvis_children >= 2)
208       {
209         childspacing = (width - (nvis_children * child_width)) / (nvis_children - 1);
210         x = allocation->x + GTK_CONTAINER (box)->border_width;
211         secondary_x = x + ((nvis_children - n_secondaries) * (child_width + childspacing));
212       }
213     else
214       {
215         /* one or zero children, just center */
216         childspacing = width;
217         x = secondary_x = allocation->x + (allocation->width - child_width) / 2;
218       }
219     break;
220   case GTK_BUTTONBOX_START:
221     childspacing = spacing;
222     x = allocation->x + GTK_CONTAINER (box)->border_width;
223     secondary_x = allocation->x + allocation->width
224       - child_width * n_secondaries
225       - spacing * (n_secondaries - 1)
226       - GTK_CONTAINER (box)->border_width;
227     break;
228   case GTK_BUTTONBOX_END:
229     childspacing = spacing;
230     x = allocation->x + allocation->width
231       - child_width * (nvis_children - n_secondaries)
232       - spacing * (nvis_children - n_secondaries - 1)
233       - GTK_CONTAINER (box)->border_width;
234     secondary_x = allocation->x + GTK_CONTAINER (box)->border_width;
235     break;
236   default:
237     g_assert_not_reached();
238     break;
239   }
240
241
242   y = allocation->y + (allocation->height - child_height) / 2;
243   childspace = child_width + childspacing;
244
245   children = GTK_BOX (box)->children;
246
247   while (children)
248     {
249       child = children->data;
250       children = children->next;
251
252       if (GTK_WIDGET_VISIBLE (child->widget))
253         {
254           child_allocation.width = child_width;
255           child_allocation.height = child_height;
256           child_allocation.y = y;
257
258           if (child->is_secondary)
259             {
260               child_allocation.x = secondary_x;
261               secondary_x += childspace;
262             }
263           else
264             {
265               child_allocation.x = x;
266               x += childspace;
267             }
268
269           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
270             child_allocation.x = (allocation->x + allocation->width) - (child_allocation.x + child_width - allocation->x);
271
272           gtk_widget_size_allocate (child->widget, &child_allocation);
273         }
274     }
275 }