evolution-3.6.4/libgnomecanvas/gnome-canvas-widget.c

No issues found

  1 /*
  2  * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
  3  * All rights reserved.
  4  *
  5  * This file is part of the Gnome Library.
  6  *
  7  * The Gnome Library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Library General Public License as
  9  * published by the Free Software Foundation; either version 2 of the
 10  * License, or (at your option) any later version.
 11  *
 12  * The Gnome Library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Library General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Library General Public
 18  * License along with the Gnome Library; see the file COPYING.LIB.  If not,
 19  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 20  * Boston, MA 02111-1307, USA.
 21  */
 22 /*
 23   @NOTATION@
 24  */
 25 /* Widget item type for GnomeCanvas widget
 26  *
 27  * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas
 28  * widget.  Tk is copyrighted by the Regents of the University of California,
 29  * Sun Microsystems, and other parties.
 30  *
 31  *
 32  * Author: Federico Mena <federico@nuclecu.unam.mx>
 33  */
 34 
 35 #ifdef HAVE_CONFIG_H
 36 #include <config.h>
 37 #endif
 38 
 39 #include <math.h>
 40 #include "gnome-canvas-widget.h"
 41 
 42 enum {
 43 	PROP_0,
 44 	PROP_WIDGET,
 45 	PROP_X,
 46 	PROP_Y,
 47 	PROP_WIDTH,
 48 	PROP_HEIGHT,
 49 	PROP_SIZE_PIXELS
 50 };
 51 
 52 static void gnome_canvas_widget_dispose    (GnomeCanvasItem      *object);
 53 static void gnome_canvas_widget_get_property (GObject            *object,
 54 					      guint               param_id,
 55 					      GValue             *value,
 56 					      GParamSpec         *pspec);
 57 static void gnome_canvas_widget_set_property (GObject            *object,
 58 					      guint               param_id,
 59 					      const GValue       *value,
 60 					      GParamSpec         *pspec);
 61 
 62 static void	gnome_canvas_widget_update	(GnomeCanvasItem *item,
 63 						 const cairo_matrix_t *matrix,
 64 						 gint flags);
 65 static GnomeCanvasItem *gnome_canvas_widget_point (GnomeCanvasItem *item,
 66 						 gdouble x,
 67 						 gdouble y,
 68 						 gint cx,
 69 						 gint cy);
 70 static void	gnome_canvas_widget_bounds	(GnomeCanvasItem *item,
 71 						 gdouble *x1,
 72 						 gdouble *y1,
 73 						 gdouble *x2,
 74 						 gdouble *y2);
 75 
 76 static void	gnome_canvas_widget_draw	(GnomeCanvasItem *item,
 77 						 cairo_t *cr,
 78 						 gint x,
 79 						 gint y,
 80 						 gint width,
 81 						 gint height);
 82 
 83 G_DEFINE_TYPE (
 84 	GnomeCanvasWidget,
 85 	gnome_canvas_widget,
 86 	GNOME_TYPE_CANVAS_ITEM)
 87 
 88 static void
 89 gnome_canvas_widget_class_init (GnomeCanvasWidgetClass *class)
 90 {
 91 	GObjectClass *gobject_class;
 92 	GnomeCanvasItemClass *item_class;
 93 
 94 	gobject_class = (GObjectClass *) class;
 95 	item_class = (GnomeCanvasItemClass *) class;
 96 
 97 	gobject_class->set_property = gnome_canvas_widget_set_property;
 98 	gobject_class->get_property = gnome_canvas_widget_get_property;
 99 
100 	g_object_class_install_property
101 		(gobject_class,
102 		 PROP_WIDGET,
103 		 g_param_spec_object ("widget", NULL, NULL,
104 				      GTK_TYPE_WIDGET,
105 				      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
106 	g_object_class_install_property
107 		(gobject_class,
108 		 PROP_X,
109 		 g_param_spec_double ("x", NULL, NULL,
110 				      -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
111 				      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
112 	g_object_class_install_property
113 		(gobject_class,
114 		 PROP_Y,
115 		 g_param_spec_double ("y", NULL, NULL,
116 				      -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
117 				      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
118 	g_object_class_install_property
119 		(gobject_class,
120 		 PROP_WIDTH,
121 		 g_param_spec_double ("width", NULL, NULL,
122 				      -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
123 				      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
124 	g_object_class_install_property
125 		(gobject_class,
126 		 PROP_HEIGHT,
127 		 g_param_spec_double ("height", NULL, NULL,
128 				      -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
129 				      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
130 	g_object_class_install_property
131 		(gobject_class,
132 		 PROP_SIZE_PIXELS,
133 		 g_param_spec_boolean ("size_pixels", NULL, NULL,
134 				       FALSE,
135 				       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
136 
137 	item_class->dispose = gnome_canvas_widget_dispose;
138 	item_class->update = gnome_canvas_widget_update;
139 	item_class->point = gnome_canvas_widget_point;
140 	item_class->bounds = gnome_canvas_widget_bounds;
141 	item_class->draw = gnome_canvas_widget_draw;
142 }
143 
144 static void
145 do_destroy (gpointer data,
146             GObject *gone_object)
147 {
148 	GnomeCanvasWidget *witem;
149 
150 	witem = data;
151 
152 	if (!witem->in_destroy) {
153 		witem->in_destroy = TRUE;
154 		g_object_run_dispose (G_OBJECT (witem));
155 	}
156 }
157 
158 static void
159 gnome_canvas_widget_init (GnomeCanvasWidget *witem)
160 {
161 	witem->x = 0.0;
162 	witem->y = 0.0;
163 	witem->width = 0.0;
164 	witem->height = 0.0;
165 	witem->size_pixels = FALSE;
166 }
167 
168 static void
169 gnome_canvas_widget_dispose (GnomeCanvasItem *object)
170 {
171 	GnomeCanvasWidget *witem;
172 
173 	g_return_if_fail (object != NULL);
174 	g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
175 
176 	witem = GNOME_CANVAS_WIDGET (object);
177 
178 	if (witem->widget && !witem->in_destroy) {
179 		g_object_weak_unref (G_OBJECT (witem->widget), do_destroy, witem);
180 		gtk_widget_destroy (witem->widget);
181 		witem->widget = NULL;
182 	}
183 
184 	GNOME_CANVAS_ITEM_CLASS (gnome_canvas_widget_parent_class)->
185 		dispose (object);
186 }
187 
188 static void
189 recalc_bounds (GnomeCanvasWidget *witem)
190 {
191 	GnomeCanvasItem *item;
192 	gdouble wx, wy;
193 
194 	item = GNOME_CANVAS_ITEM (witem);
195 
196 	/* Get world coordinates */
197 
198 	wx = witem->x;
199 	wy = witem->y;
200 	gnome_canvas_item_i2w (item, &wx, &wy);
201 
202 	/* Get canvas pixel coordinates */
203 
204 	gnome_canvas_w2c (item->canvas, wx, wy, &witem->cx, &witem->cy);
205 
206 	/* Bounds */
207 
208 	item->x1 = witem->cx;
209 	item->y1 = witem->cy;
210 	item->x2 = witem->cx + witem->cwidth;
211 	item->y2 = witem->cy + witem->cheight;
212 
213 	if (witem->widget)
214 		gtk_layout_move (
215 			GTK_LAYOUT (item->canvas), witem->widget,
216 			witem->cx + item->canvas->zoom_xofs,
217 			witem->cy + item->canvas->zoom_yofs);
218 }
219 
220 static void
221 gnome_canvas_widget_set_property (GObject *object,
222                                   guint param_id,
223                                   const GValue *value,
224                                   GParamSpec *pspec)
225 {
226 	GnomeCanvasItem *item;
227 	GnomeCanvasWidget *witem;
228 	GObject *obj;
229 	gint update;
230 	gint calc_bounds;
231 
232 	g_return_if_fail (object != NULL);
233 	g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
234 
235 	item = GNOME_CANVAS_ITEM (object);
236 	witem = GNOME_CANVAS_WIDGET (object);
237 
238 	update = FALSE;
239 	calc_bounds = FALSE;
240 
241 	switch (param_id) {
242 	case PROP_WIDGET:
243 		if (witem->widget) {
244 			g_object_weak_unref (G_OBJECT (witem->widget), do_destroy, witem);
245 			gtk_container_remove (GTK_CONTAINER (item->canvas), witem->widget);
246 		}
247 
248 		obj = g_value_get_object (value);
249 		if (obj) {
250 			witem->widget = GTK_WIDGET (obj);
251 			g_object_weak_ref (obj, do_destroy, witem);
252 			gtk_layout_put (
253 				GTK_LAYOUT (item->canvas), witem->widget,
254 				witem->cx + item->canvas->zoom_xofs,
255 				witem->cy + item->canvas->zoom_yofs);
256 		}
257 
258 		update = TRUE;
259 		break;
260 
261 	case PROP_X:
262 		if (witem->x != g_value_get_double (value))
263 		{
264 			witem->x = g_value_get_double (value);
265 			calc_bounds = TRUE;
266 		}
267 		break;
268 
269 	case PROP_Y:
270 		if (witem->y != g_value_get_double (value))
271 		{
272 			witem->y = g_value_get_double (value);
273 			calc_bounds = TRUE;
274 		}
275 		break;
276 
277 	case PROP_WIDTH:
278 		if (witem->width != fabs (g_value_get_double (value)))
279 		{
280 			witem->width = fabs (g_value_get_double (value));
281 			update = TRUE;
282 		}
283 		break;
284 
285 	case PROP_HEIGHT:
286 		if (witem->height != fabs (g_value_get_double (value)))
287 		{
288 			witem->height = fabs (g_value_get_double (value));
289 			update = TRUE;
290 		}
291 		break;
292 
293 	case PROP_SIZE_PIXELS:
294 		if (witem->size_pixels != g_value_get_boolean (value))
295 		{
296 			witem->size_pixels = g_value_get_boolean (value);
297 			update = TRUE;
298 		}
299 		break;
300 
301 	default:
302 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
303 		break;
304 	}
305 
306 	if (update)
307 		(* GNOME_CANVAS_ITEM_GET_CLASS (item)->update) (item, NULL, 0);
308 
309 	if (calc_bounds)
310 		recalc_bounds (witem);
311 }
312 
313 static void
314 gnome_canvas_widget_get_property (GObject *object,
315                                   guint param_id,
316                                   GValue *value,
317                                   GParamSpec *pspec)
318 {
319 	GnomeCanvasWidget *witem;
320 
321 	g_return_if_fail (object != NULL);
322 	g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
323 
324 	witem = GNOME_CANVAS_WIDGET (object);
325 
326 	switch (param_id) {
327 	case PROP_WIDGET:
328 		g_value_set_object (value, (GObject *) witem->widget);
329 		break;
330 
331 	case PROP_X:
332 		g_value_set_double (value, witem->x);
333 		break;
334 
335 	case PROP_Y:
336 		g_value_set_double (value, witem->y);
337 		break;
338 
339 	case PROP_WIDTH:
340 		g_value_set_double (value, witem->width);
341 		break;
342 
343 	case PROP_HEIGHT:
344 		g_value_set_double (value, witem->height);
345 		break;
346 
347 	case PROP_SIZE_PIXELS:
348 		g_value_set_boolean (value, witem->size_pixels);
349 		break;
350 
351 	default:
352 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
353 		break;
354 	}
355 }
356 
357 static void
358 gnome_canvas_widget_update (GnomeCanvasItem *item,
359                             const cairo_matrix_t *matrix,
360                             gint flags)
361 {
362 	GnomeCanvasWidget *witem;
363 
364 	witem = GNOME_CANVAS_WIDGET (item);
365 
366 	GNOME_CANVAS_ITEM_CLASS (gnome_canvas_widget_parent_class)->
367 		update (item, matrix, flags);
368 
369 	if (witem->widget) {
370 		witem->cwidth = (gint) (witem->width + 0.5);
371 		witem->cheight = (gint) (witem->height + 0.5);
372 
373 		gtk_widget_set_size_request (witem->widget, witem->cwidth, witem->cheight);
374 	} else {
375 		witem->cwidth = 0.0;
376 		witem->cheight = 0.0;
377 	}
378 
379 	recalc_bounds (witem);
380 }
381 
382 static void
383 gnome_canvas_widget_draw (GnomeCanvasItem *item,
384                           cairo_t *cr,
385                           gint x,
386                           gint y,
387                           gint width,
388                           gint height)
389 {
390 #if 0
391 	GnomeCanvasWidget *witem;
392 
393 	witem = GNOME_CANVAS_WIDGET (item);
394 
395 	if (witem->widget)
396 		gtk_widget_queue_draw (witem->widget);
397 #endif
398 }
399 
400 static GnomeCanvasItem *
401 gnome_canvas_widget_point (GnomeCanvasItem *item,
402                            gdouble x,
403                            gdouble y,
404                            gint cx,
405                            gint cy)
406 {
407 	GnomeCanvasWidget *witem;
408 	gdouble x1, y1, x2, y2;
409 
410 	witem = GNOME_CANVAS_WIDGET (item);
411 
412 	gnome_canvas_c2w (item->canvas, witem->cx, witem->cy, &x1, &y1);
413 
414 	x2 = x1 + (witem->cwidth - 1);
415 	y2 = y1 + (witem->cheight - 1);
416 
417 	/* Is point inside widget bounds? */
418 
419 	if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2))
420 		return item;
421 
422 	/* Point is outside widget bounds */
423 	return NULL;
424 }
425 
426 static void
427 gnome_canvas_widget_bounds (GnomeCanvasItem *item,
428                             gdouble *x1,
429                             gdouble *y1,
430                             gdouble *x2,
431                             gdouble *y2)
432 {
433 	GnomeCanvasWidget *witem;
434 
435 	witem = GNOME_CANVAS_WIDGET (item);
436 
437 	*x1 = witem->x;
438 	*y1 = witem->y;
439 
440 	*x2 = *x1 + witem->width;
441 	*y2 = *y1 + witem->height;
442 }