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