No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Chris Lahey <clahey@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <math.h>
28
29 #include <gdk/gdkkeysyms.h>
30 #include <gtk/gtk.h>
31
32 #include <glib/gi18n.h>
33 #include "e-util/e-util.h"
34
35 #include "e-canvas.h"
36 #include "e-canvas-utils.h"
37 #include "e-canvas-vbox.h"
38
39 static void e_canvas_vbox_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
40 static void e_canvas_vbox_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
41 static void e_canvas_vbox_dispose (GObject *object);
42
43 static gint e_canvas_vbox_event (GnomeCanvasItem *item, GdkEvent *event);
44 static void e_canvas_vbox_realize (GnomeCanvasItem *item);
45
46 static void e_canvas_vbox_reflow (GnomeCanvasItem *item, gint flags);
47
48 static void e_canvas_vbox_real_add_item (ECanvasVbox *e_canvas_vbox, GnomeCanvasItem *item);
49 static void e_canvas_vbox_real_add_item_start (ECanvasVbox *e_canvas_vbox, GnomeCanvasItem *item);
50 static void e_canvas_vbox_resize_children (GnomeCanvasItem *item);
51
52 enum {
53 PROP_0,
54 PROP_WIDTH,
55 PROP_MINIMUM_WIDTH,
56 PROP_HEIGHT,
57 PROP_SPACING
58 };
59
60 G_DEFINE_TYPE (
61 ECanvasVbox,
62 e_canvas_vbox,
63 GNOME_TYPE_CANVAS_GROUP)
64
65 static void
66 e_canvas_vbox_class_init (ECanvasVboxClass *class)
67 {
68 GObjectClass *object_class;
69 GnomeCanvasItemClass *item_class;
70
71 object_class = (GObjectClass *) class;
72 item_class = (GnomeCanvasItemClass *) class;
73
74 class->add_item = e_canvas_vbox_real_add_item;
75 class->add_item_start = e_canvas_vbox_real_add_item_start;
76
77 object_class->set_property = e_canvas_vbox_set_property;
78 object_class->get_property = e_canvas_vbox_get_property;
79 object_class->dispose = e_canvas_vbox_dispose;
80
81 /* GnomeCanvasItem method overrides */
82 item_class->event = e_canvas_vbox_event;
83 item_class->realize = e_canvas_vbox_realize;
84
85 g_object_class_install_property (
86 object_class,
87 PROP_WIDTH,
88 g_param_spec_double (
89 "width",
90 "Width",
91 "Width",
92 0.0, G_MAXDOUBLE, 0.0,
93 G_PARAM_READWRITE));
94 g_object_class_install_property (
95 object_class,
96 PROP_MINIMUM_WIDTH,
97 g_param_spec_double (
98 "minimum_width",
99 "Minimum width",
100 "Minimum Width",
101 0.0, G_MAXDOUBLE, 0.0,
102 G_PARAM_READWRITE));
103 g_object_class_install_property (
104 object_class,
105 PROP_HEIGHT,
106 g_param_spec_double (
107 "height",
108 "Height",
109 "Height",
110 0.0, G_MAXDOUBLE, 0.0,
111 G_PARAM_READABLE));
112 g_object_class_install_property (
113 object_class,
114 PROP_SPACING,
115 g_param_spec_double (
116 "spacing",
117 "Spacing",
118 "Spacing",
119 0.0, G_MAXDOUBLE, 0.0,
120 G_PARAM_READWRITE));
121 }
122
123 static void
124 e_canvas_vbox_init (ECanvasVbox *vbox)
125 {
126 vbox->items = NULL;
127
128 vbox->width = 10;
129 vbox->minimum_width = 10;
130 vbox->height = 10;
131 vbox->spacing = 0;
132
133 e_canvas_item_set_reflow_callback (GNOME_CANVAS_ITEM (vbox), e_canvas_vbox_reflow);
134 }
135
136 static void
137 e_canvas_vbox_set_property (GObject *object,
138 guint property_id,
139 const GValue *value,
140 GParamSpec *pspec)
141 {
142 GnomeCanvasItem *item;
143 ECanvasVbox *e_canvas_vbox;
144
145 item = GNOME_CANVAS_ITEM (object);
146 e_canvas_vbox = E_CANVAS_VBOX (object);
147
148 switch (property_id) {
149 case PROP_WIDTH:
150 case PROP_MINIMUM_WIDTH:
151 e_canvas_vbox->minimum_width = g_value_get_double (value);
152 e_canvas_vbox_resize_children (item);
153 e_canvas_item_request_reflow (item);
154 break;
155 case PROP_SPACING:
156 e_canvas_vbox->spacing = g_value_get_double (value);
157 e_canvas_item_request_reflow (item);
158 break;
159 }
160 }
161
162 static void
163 e_canvas_vbox_get_property (GObject *object,
164 guint property_id,
165 GValue *value,
166 GParamSpec *pspec)
167 {
168 ECanvasVbox *e_canvas_vbox;
169
170 e_canvas_vbox = E_CANVAS_VBOX (object);
171
172 switch (property_id) {
173 case PROP_WIDTH:
174 g_value_set_double (value, e_canvas_vbox->width);
175 break;
176 case PROP_MINIMUM_WIDTH:
177 g_value_set_double (value, e_canvas_vbox->minimum_width);
178 break;
179 case PROP_HEIGHT:
180 g_value_set_double (value, e_canvas_vbox->height);
181 break;
182 case PROP_SPACING:
183 g_value_set_double (value, e_canvas_vbox->spacing);
184 break;
185 default:
186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
187 break;
188 }
189 }
190
191 /* Used from g_list_foreach(); disconnects from an item's signals */
192 static void
193 disconnect_item_cb (gpointer data,
194 gpointer user_data)
195 {
196 ECanvasVbox *vbox;
197 GnomeCanvasItem *item;
198
199 vbox = E_CANVAS_VBOX (user_data);
200
201 item = GNOME_CANVAS_ITEM (data);
202 g_signal_handlers_disconnect_matched (
203 item,
204 G_SIGNAL_MATCH_DATA,
205 0, 0, NULL, NULL,
206 vbox);
207 }
208
209 static void
210 e_canvas_vbox_dispose (GObject *object)
211 {
212 ECanvasVbox *vbox = E_CANVAS_VBOX (object);
213
214 if (vbox->items) {
215 g_list_foreach (vbox->items, disconnect_item_cb, vbox);
216 g_list_free (vbox->items);
217 vbox->items = NULL;
218 }
219
220 G_OBJECT_CLASS (e_canvas_vbox_parent_class)->dispose (object);
221 }
222
223 static gint
224 e_canvas_vbox_event (GnomeCanvasItem *item,
225 GdkEvent *event)
226 {
227 gint return_val = TRUE;
228
229 switch (event->type) {
230 case GDK_KEY_PRESS:
231 switch (event->key.keyval) {
232 case GDK_KEY_Left:
233 case GDK_KEY_KP_Left:
234 case GDK_KEY_Right:
235 case GDK_KEY_KP_Right:
236 case GDK_KEY_Down:
237 case GDK_KEY_KP_Down:
238 case GDK_KEY_Up:
239 case GDK_KEY_KP_Up:
240 case GDK_KEY_Return:
241 case GDK_KEY_KP_Enter:
242 return_val = TRUE;
243 break;
244 default:
245 return_val = FALSE;
246 break;
247 }
248 break;
249 default:
250 return_val = FALSE;
251 break;
252 }
253 if (!return_val) {
254 if (GNOME_CANVAS_ITEM_CLASS (e_canvas_vbox_parent_class)->event)
255 return GNOME_CANVAS_ITEM_CLASS (e_canvas_vbox_parent_class)->event (item, event);
256 }
257 return return_val;
258
259 }
260
261 static void
262 e_canvas_vbox_realize (GnomeCanvasItem *item)
263 {
264 if (GNOME_CANVAS_ITEM_CLASS (e_canvas_vbox_parent_class)->realize)
265 (* GNOME_CANVAS_ITEM_CLASS (e_canvas_vbox_parent_class)->realize) (item);
266
267 e_canvas_vbox_resize_children (item);
268 e_canvas_item_request_reflow (item);
269 }
270
271 static void
272 e_canvas_vbox_remove_item (gpointer data,
273 GObject *where_object_was)
274 {
275 ECanvasVbox *vbox = data;
276 vbox->items = g_list_remove (vbox->items, where_object_was);
277 }
278
279 static void
280 e_canvas_vbox_real_add_item (ECanvasVbox *e_canvas_vbox,
281 GnomeCanvasItem *item)
282 {
283 e_canvas_vbox->items = g_list_append (e_canvas_vbox->items, item);
284 g_object_weak_ref (
285 G_OBJECT (item),
286 e_canvas_vbox_remove_item, e_canvas_vbox);
287 if (GNOME_CANVAS_ITEM (e_canvas_vbox)->flags & GNOME_CANVAS_ITEM_REALIZED) {
288 gnome_canvas_item_set (
289 item,
290 "width", (gdouble) e_canvas_vbox->minimum_width,
291 NULL);
292 e_canvas_item_request_reflow (item);
293 }
294 }
295
296 static void
297 e_canvas_vbox_real_add_item_start (ECanvasVbox *e_canvas_vbox,
298 GnomeCanvasItem *item)
299 {
300 e_canvas_vbox->items = g_list_prepend (e_canvas_vbox->items, item);
301 g_object_weak_ref (
302 G_OBJECT (item),
303 e_canvas_vbox_remove_item, e_canvas_vbox);
304 if (GNOME_CANVAS_ITEM (e_canvas_vbox)->flags & GNOME_CANVAS_ITEM_REALIZED) {
305 gnome_canvas_item_set (
306 item,
307 "width", (gdouble) e_canvas_vbox->minimum_width,
308 NULL);
309 e_canvas_item_request_reflow (item);
310 }
311 }
312
313 static void
314 e_canvas_vbox_resize_children (GnomeCanvasItem *item)
315 {
316 GList *list;
317 ECanvasVbox *e_canvas_vbox;
318
319 e_canvas_vbox = E_CANVAS_VBOX (item);
320 for (list = e_canvas_vbox->items; list; list = list->next) {
321 GnomeCanvasItem *child = GNOME_CANVAS_ITEM (list->data);
322 gnome_canvas_item_set (
323 child,
324 "width", (gdouble) e_canvas_vbox->minimum_width,
325 NULL);
326 }
327 }
328
329 static void
330 e_canvas_vbox_reflow (GnomeCanvasItem *item,
331 gint flags)
332 {
333 ECanvasVbox *e_canvas_vbox = E_CANVAS_VBOX (item);
334 if (item->flags & GNOME_CANVAS_ITEM_REALIZED) {
335
336 gdouble old_height;
337 gdouble running_height;
338 gdouble old_width;
339 gdouble max_width;
340
341 old_width = e_canvas_vbox->width;
342 max_width = e_canvas_vbox->minimum_width;
343
344 old_height = e_canvas_vbox->height;
345 running_height = 0;
346
347 if (e_canvas_vbox->items == NULL) {
348 } else {
349 GList *list;
350 gdouble item_height;
351 gdouble item_width;
352
353 list = e_canvas_vbox->items;
354 g_object_get (
355 list->data,
356 "height", &item_height,
357 "width", &item_width,
358 NULL);
359 e_canvas_item_move_absolute (
360 GNOME_CANVAS_ITEM (list->data),
361 (gdouble) 0,
362 (gdouble) running_height);
363 running_height += item_height;
364 if (max_width < item_width)
365 max_width = item_width;
366 list = g_list_next (list);
367
368 for (; list; list = g_list_next (list)) {
369 running_height += e_canvas_vbox->spacing;
370
371 g_object_get (
372 list->data,
373 "height", &item_height,
374 "width", &item_width,
375 NULL);
376
377 e_canvas_item_move_absolute (
378 GNOME_CANVAS_ITEM (list->data),
379 (gdouble) 0,
380 (gdouble) running_height);
381
382 running_height += item_height;
383 if (max_width < item_width)
384 max_width = item_width;
385 }
386
387 }
388 e_canvas_vbox->height = running_height;
389 e_canvas_vbox->width = max_width;
390 if (old_height != e_canvas_vbox->height ||
391 old_width != e_canvas_vbox->width)
392 e_canvas_item_request_parent_reflow (item);
393 }
394 }
395
396 void
397 e_canvas_vbox_add_item (ECanvasVbox *e_canvas_vbox,
398 GnomeCanvasItem *item)
399 {
400 if (E_CANVAS_VBOX_CLASS (G_OBJECT_GET_CLASS (e_canvas_vbox))->add_item)
401 (E_CANVAS_VBOX_CLASS (G_OBJECT_GET_CLASS (e_canvas_vbox))->add_item) (e_canvas_vbox, item);
402 }
403
404 void
405 e_canvas_vbox_add_item_start (ECanvasVbox *e_canvas_vbox,
406 GnomeCanvasItem *item)
407 {
408 if (E_CANVAS_VBOX_CLASS (G_OBJECT_GET_CLASS (e_canvas_vbox))->add_item_start)
409 (E_CANVAS_VBOX_CLASS (G_OBJECT_GET_CLASS (e_canvas_vbox))->add_item_start) (e_canvas_vbox, item);
410 }