evolution-3.6.4/widgets/misc/e-canvas-vbox.c

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 }