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 }