2 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
5 * This file is part of the Gnome Library.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * published by the Free Software Foundation; either the
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU Lesser General Public License
17 * License along with the Gnome Library; see the file COPYING.LIB. If not,
22 /* Widget item type for GnomeCanvas widget
24 * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas
25 * widget. Tk is copyrighted by the Regents of the University of California,
26 * Sun Microsystems, and other parties.
29 * Author: Federico Mena <federico@nuclecu.unam.mx>
32 #include "evolution-config.h"
35 #include "gnome-canvas-widget.h"
47 static void gnome_canvas_widget_dispose (GnomeCanvasItem
*object
);
48 static void gnome_canvas_widget_get_property (GObject
*object
,
52 static void gnome_canvas_widget_set_property (GObject
*object
,
57 static void gnome_canvas_widget_update (GnomeCanvasItem
*item
,
58 const cairo_matrix_t
*matrix
,
60 static GnomeCanvasItem
*gnome_canvas_widget_point (GnomeCanvasItem
*item
,
65 static void gnome_canvas_widget_bounds (GnomeCanvasItem
*item
,
71 static void gnome_canvas_widget_draw (GnomeCanvasItem
*item
,
81 GNOME_TYPE_CANVAS_ITEM
)
84 gnome_canvas_widget_class_init (GnomeCanvasWidgetClass
*class)
86 GObjectClass
*gobject_class
;
87 GnomeCanvasItemClass
*item_class
;
89 gobject_class
= (GObjectClass
*) class;
90 item_class
= (GnomeCanvasItemClass
*) class;
92 gobject_class
->set_property
= gnome_canvas_widget_set_property
;
93 gobject_class
->get_property
= gnome_canvas_widget_get_property
;
95 g_object_class_install_property
98 g_param_spec_object ("widget", NULL
, NULL
,
100 (G_PARAM_READABLE
| G_PARAM_WRITABLE
)));
101 g_object_class_install_property
104 g_param_spec_double ("x", NULL
, NULL
,
105 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
106 (G_PARAM_READABLE
| G_PARAM_WRITABLE
)));
107 g_object_class_install_property
110 g_param_spec_double ("y", NULL
, NULL
,
111 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
112 (G_PARAM_READABLE
| G_PARAM_WRITABLE
)));
113 g_object_class_install_property
116 g_param_spec_double ("width", NULL
, NULL
,
117 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
118 (G_PARAM_READABLE
| G_PARAM_WRITABLE
)));
119 g_object_class_install_property
122 g_param_spec_double ("height", NULL
, NULL
,
123 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
124 (G_PARAM_READABLE
| G_PARAM_WRITABLE
)));
125 g_object_class_install_property
128 g_param_spec_boolean ("size_pixels", NULL
, NULL
,
130 (G_PARAM_READABLE
| G_PARAM_WRITABLE
)));
132 item_class
->dispose
= gnome_canvas_widget_dispose
;
133 item_class
->update
= gnome_canvas_widget_update
;
134 item_class
->point
= gnome_canvas_widget_point
;
135 item_class
->bounds
= gnome_canvas_widget_bounds
;
136 item_class
->draw
= gnome_canvas_widget_draw
;
140 do_destroy (gpointer data
,
141 GObject
*gone_object
)
143 GnomeCanvasWidget
*witem
;
147 if (!witem
->in_destroy
) {
148 witem
->in_destroy
= TRUE
;
149 g_object_run_dispose (G_OBJECT (witem
));
154 gnome_canvas_widget_init (GnomeCanvasWidget
*witem
)
160 witem
->size_pixels
= FALSE
;
164 gnome_canvas_widget_dispose (GnomeCanvasItem
*object
)
166 GnomeCanvasWidget
*witem
;
168 g_return_if_fail (object
!= NULL
);
169 g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object
));
171 witem
= GNOME_CANVAS_WIDGET (object
);
173 if (witem
->widget
&& !witem
->in_destroy
) {
174 g_object_weak_unref (G_OBJECT (witem
->widget
), do_destroy
, witem
);
175 gtk_widget_destroy (witem
->widget
);
176 witem
->widget
= NULL
;
179 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_widget_parent_class
)->
184 reposition_widget_cb (gpointer user_data
)
186 GnomeCanvasWidget
*witem
= user_data
;
188 g_return_val_if_fail (GNOME_IS_CANVAS_WIDGET (witem
), FALSE
);
191 gtk_widget_queue_resize (witem
->widget
);
197 recalc_bounds (GnomeCanvasWidget
*witem
)
199 GnomeCanvasItem
*item
;
202 item
= GNOME_CANVAS_ITEM (witem
);
204 /* Get world coordinates */
208 gnome_canvas_item_i2w (item
, &wx
, &wy
);
210 /* Get canvas pixel coordinates */
212 gnome_canvas_w2c (item
->canvas
, wx
, wy
, &witem
->cx
, &witem
->cy
);
216 item
->x1
= witem
->cx
;
217 item
->y1
= witem
->cy
;
218 item
->x2
= witem
->cx
+ witem
->cwidth
;
219 item
->y2
= witem
->cy
+ witem
->cheight
;
222 gint current_x
= 0, current_y
= 0;
224 gtk_container_child_get (GTK_CONTAINER (item
->canvas
), witem
->widget
,
229 if (current_x
!= ((gint
) (witem
->cx
+ item
->canvas
->zoom_xofs
)) ||
230 current_y
!= ((gint
) (witem
->cy
+ item
->canvas
->zoom_yofs
))) {
232 GTK_LAYOUT (item
->canvas
), witem
->widget
,
233 witem
->cx
+ item
->canvas
->zoom_xofs
,
234 witem
->cy
+ item
->canvas
->zoom_yofs
);
236 /* This is needed, because the gtk_layout_move() calls gtk_widget_queue_resize(),
237 which can be silently ignored when called inside "size-allocate" handler, causing
238 misposition of the child widget. */
239 g_idle_add_full (G_PRIORITY_HIGH_IDLE
,
240 reposition_widget_cb
, g_object_ref (witem
), g_object_unref
);
246 gnome_canvas_widget_set_property (GObject
*object
,
251 GnomeCanvasItem
*item
;
252 GnomeCanvasWidget
*witem
;
257 g_return_if_fail (object
!= NULL
);
258 g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object
));
260 item
= GNOME_CANVAS_ITEM (object
);
261 witem
= GNOME_CANVAS_WIDGET (object
);
269 g_object_weak_unref (G_OBJECT (witem
->widget
), do_destroy
, witem
);
270 gtk_container_remove (GTK_CONTAINER (item
->canvas
), witem
->widget
);
273 obj
= g_value_get_object (value
);
275 witem
->widget
= GTK_WIDGET (obj
);
276 g_object_weak_ref (obj
, do_destroy
, witem
);
278 GTK_LAYOUT (item
->canvas
), witem
->widget
,
279 witem
->cx
+ item
->canvas
->zoom_xofs
,
280 witem
->cy
+ item
->canvas
->zoom_yofs
);
287 if (witem
->x
!= g_value_get_double (value
))
289 witem
->x
= g_value_get_double (value
);
295 if (witem
->y
!= g_value_get_double (value
))
297 witem
->y
= g_value_get_double (value
);
303 if (witem
->width
!= fabs (g_value_get_double (value
)))
305 witem
->width
= fabs (g_value_get_double (value
));
311 if (witem
->height
!= fabs (g_value_get_double (value
)))
313 witem
->height
= fabs (g_value_get_double (value
));
318 case PROP_SIZE_PIXELS
:
319 if (witem
->size_pixels
!= g_value_get_boolean (value
))
321 witem
->size_pixels
= g_value_get_boolean (value
);
327 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
332 (* GNOME_CANVAS_ITEM_GET_CLASS (item
)->update
) (item
, NULL
, 0);
335 recalc_bounds (witem
);
339 gnome_canvas_widget_get_property (GObject
*object
,
344 GnomeCanvasWidget
*witem
;
346 g_return_if_fail (object
!= NULL
);
347 g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object
));
349 witem
= GNOME_CANVAS_WIDGET (object
);
353 g_value_set_object (value
, (GObject
*) witem
->widget
);
357 g_value_set_double (value
, witem
->x
);
361 g_value_set_double (value
, witem
->y
);
365 g_value_set_double (value
, witem
->width
);
369 g_value_set_double (value
, witem
->height
);
372 case PROP_SIZE_PIXELS
:
373 g_value_set_boolean (value
, witem
->size_pixels
);
377 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
383 gnome_canvas_widget_update (GnomeCanvasItem
*item
,
384 const cairo_matrix_t
*matrix
,
387 GnomeCanvasWidget
*witem
;
389 witem
= GNOME_CANVAS_WIDGET (item
);
391 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_widget_parent_class
)->
392 update (item
, matrix
, flags
);
395 witem
->cwidth
= (gint
) (witem
->width
+ 0.5);
396 witem
->cheight
= (gint
) (witem
->height
+ 0.5);
398 gtk_widget_set_size_request (witem
->widget
, witem
->cwidth
, witem
->cheight
);
401 witem
->cheight
= 0.0;
404 recalc_bounds (witem
);
408 gnome_canvas_widget_draw (GnomeCanvasItem
*item
,
416 GnomeCanvasWidget
*witem
;
418 witem
= GNOME_CANVAS_WIDGET (item
);
421 gtk_widget_queue_draw (witem
->widget
);
425 static GnomeCanvasItem
*
426 gnome_canvas_widget_point (GnomeCanvasItem
*item
,
432 GnomeCanvasWidget
*witem
;
433 gdouble x1
, y1
, x2
, y2
;
435 witem
= GNOME_CANVAS_WIDGET (item
);
437 gnome_canvas_c2w (item
->canvas
, witem
->cx
, witem
->cy
, &x1
, &y1
);
439 x2
= x1
+ (witem
->cwidth
- 1);
440 y2
= y1
+ (witem
->cheight
- 1);
442 /* Is point inside widget bounds? */
444 if ((x
>= x1
) && (y
>= y1
) && (x
<= x2
) && (y
<= y2
))
447 /* Point is outside widget bounds */
452 gnome_canvas_widget_bounds (GnomeCanvasItem
*item
,
458 GnomeCanvasWidget
*witem
;
460 witem
= GNOME_CANVAS_WIDGET (item
);
465 *x2
= *x1
+ witem
->width
;
466 *y2
= *y1
+ witem
->height
;