2 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
5 * This file is part of the Gnome Library.
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.
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.
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.
25 /* Widget item type for GnomeCanvas widget
27 * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
28 * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
31 * Author: Federico Mena <federico@nuclecu.unam.mx>
36 #include <gtk/gtksignal.h>
37 #include "gnome-canvas-widget.h"
51 static void gnome_canvas_widget_class_init (GnomeCanvasWidgetClass *class);
52 static void gnome_canvas_widget_init (GnomeCanvasWidget *witem);
53 static void gnome_canvas_widget_destroy (GtkObject *object);
54 static void gnome_canvas_widget_get_property (GObject *object,
58 static void gnome_canvas_widget_set_property (GObject *object,
63 static void gnome_canvas_widget_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
64 static double gnome_canvas_widget_point (GnomeCanvasItem *item, double x, double y,
65 int cx, int cy, GnomeCanvasItem **actual_item);
66 static void gnome_canvas_widget_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
68 static void gnome_canvas_widget_render (GnomeCanvasItem *item,
70 static void gnome_canvas_widget_draw (GnomeCanvasItem *item,
71 GdkDrawable *drawable,
73 int width, int height);
75 static GnomeCanvasItemClass *parent_class;
79 gnome_canvas_widget_get_type (void)
81 static GType widget_type;
84 const GTypeInfo object_info = {
85 sizeof (GnomeCanvasWidgetClass),
87 (GBaseFinalizeFunc) NULL,
88 (GClassInitFunc) gnome_canvas_widget_class_init,
89 (GClassFinalizeFunc) NULL,
90 NULL, /* class_data */
91 sizeof (GnomeCanvasWidget),
93 (GInstanceInitFunc) gnome_canvas_widget_init,
94 NULL /* value_table */
97 widget_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasWidget",
105 gnome_canvas_widget_class_init (GnomeCanvasWidgetClass *class)
107 GObjectClass *gobject_class;
108 GtkObjectClass *object_class;
109 GnomeCanvasItemClass *item_class;
111 gobject_class = (GObjectClass *) class;
112 object_class = (GtkObjectClass *) class;
113 item_class = (GnomeCanvasItemClass *) class;
115 parent_class = g_type_class_peek_parent (class);
117 gobject_class->set_property = gnome_canvas_widget_set_property;
118 gobject_class->get_property = gnome_canvas_widget_get_property;
120 g_object_class_install_property
123 g_param_spec_object ("widget", NULL, NULL,
125 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
126 g_object_class_install_property
129 g_param_spec_double ("x", NULL, NULL,
130 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
131 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
132 g_object_class_install_property
135 g_param_spec_double ("y", NULL, NULL,
136 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
137 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
138 g_object_class_install_property
141 g_param_spec_double ("width", NULL, NULL,
142 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
143 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
144 g_object_class_install_property
147 g_param_spec_double ("height", NULL, NULL,
148 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
149 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
150 g_object_class_install_property
153 g_param_spec_enum ("anchor", NULL, NULL,
154 GTK_TYPE_ANCHOR_TYPE,
156 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
157 g_object_class_install_property
160 g_param_spec_boolean ("size_pixels", NULL, NULL,
162 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
164 object_class->destroy = gnome_canvas_widget_destroy;
166 item_class->update = gnome_canvas_widget_update;
167 item_class->point = gnome_canvas_widget_point;
168 item_class->bounds = gnome_canvas_widget_bounds;
169 item_class->render = gnome_canvas_widget_render;
170 item_class->draw = gnome_canvas_widget_draw;
174 gnome_canvas_widget_init (GnomeCanvasWidget *witem)
180 witem->anchor = GTK_ANCHOR_NW;
181 witem->size_pixels = FALSE;
185 gnome_canvas_widget_destroy (GtkObject *object)
187 GnomeCanvasWidget *witem;
189 g_return_if_fail (object != NULL);
190 g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
192 witem = GNOME_CANVAS_WIDGET (object);
194 if (witem->widget && !witem->in_destroy) {
195 g_signal_handler_disconnect (witem->widget, witem->destroy_id);
196 gtk_widget_destroy (witem->widget);
197 witem->widget = NULL;
200 if (GTK_OBJECT_CLASS (parent_class)->destroy)
201 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
205 recalc_bounds (GnomeCanvasWidget *witem)
207 GnomeCanvasItem *item;
210 item = GNOME_CANVAS_ITEM (witem);
212 /* Get world coordinates */
216 gnome_canvas_item_i2w (item, &wx, &wy);
218 /* Get canvas pixel coordinates */
220 gnome_canvas_w2c (item->canvas, wx, wy, &witem->cx, &witem->cy);
222 /* Anchor widget item */
224 switch (witem->anchor) {
231 case GTK_ANCHOR_CENTER:
233 witem->cx -= witem->cwidth / 2;
239 witem->cx -= witem->cwidth;
246 switch (witem->anchor) {
253 case GTK_ANCHOR_CENTER:
255 witem->cy -= witem->cheight / 2;
261 witem->cy -= witem->cheight;
270 item->x1 = witem->cx;
271 item->y1 = witem->cy;
272 item->x2 = witem->cx + witem->cwidth;
273 item->y2 = witem->cy + witem->cheight;
276 gtk_layout_move (GTK_LAYOUT (item->canvas), witem->widget,
277 witem->cx + item->canvas->zoom_xofs,
278 witem->cy + item->canvas->zoom_yofs);
282 do_destroy (GtkObject *object, gpointer data)
284 GnomeCanvasWidget *witem;
288 witem->in_destroy = TRUE;
290 gtk_object_destroy (data);
294 gnome_canvas_widget_set_property (GObject *object,
299 GnomeCanvasItem *item;
300 GnomeCanvasWidget *witem;
305 g_return_if_fail (object != NULL);
306 g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
308 item = GNOME_CANVAS_ITEM (object);
309 witem = GNOME_CANVAS_WIDGET (object);
317 g_signal_handler_disconnect (witem->widget, witem->destroy_id);
318 gtk_container_remove (GTK_CONTAINER (item->canvas), witem->widget);
321 obj = g_value_get_object (value);
323 witem->widget = GTK_WIDGET (obj);
324 witem->destroy_id = g_signal_connect (obj, "destroy",
325 G_CALLBACK (do_destroy),
327 gtk_layout_put (GTK_LAYOUT (item->canvas), witem->widget,
328 witem->cx + item->canvas->zoom_xofs,
329 witem->cy + item->canvas->zoom_yofs);
336 if (witem->x != g_value_get_double (value))
338 witem->x = g_value_get_double (value);
344 if (witem->y != g_value_get_double (value))
346 witem->y = g_value_get_double (value);
352 if (witem->width != fabs (g_value_get_double (value)))
354 witem->width = fabs (g_value_get_double (value));
360 if (witem->height != fabs (g_value_get_double (value)))
362 witem->height = fabs (g_value_get_double (value));
368 if (witem->anchor != g_value_get_enum (value))
370 witem->anchor = g_value_get_enum (value);
375 case PROP_SIZE_PIXELS:
376 if (witem->size_pixels != g_value_get_boolean (value))
378 witem->size_pixels = g_value_get_boolean (value);
384 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
389 (* GNOME_CANVAS_ITEM_GET_CLASS (item)->update) (item, NULL, NULL, 0);
392 recalc_bounds (witem);
396 gnome_canvas_widget_get_property (GObject *object,
401 GnomeCanvasWidget *witem;
403 g_return_if_fail (object != NULL);
404 g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
406 witem = GNOME_CANVAS_WIDGET (object);
410 g_value_set_object (value, (GObject *) witem->widget);
414 g_value_set_double (value, witem->x);
418 g_value_set_double (value, witem->y);
422 g_value_set_double (value, witem->width);
426 g_value_set_double (value, witem->height);
430 g_value_set_enum (value, witem->anchor);
433 case PROP_SIZE_PIXELS:
434 g_value_set_boolean (value, witem->size_pixels);
438 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
444 gnome_canvas_widget_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
446 GnomeCanvasWidget *witem;
448 witem = GNOME_CANVAS_WIDGET (item);
450 if (parent_class->update)
451 (* parent_class->update) (item, affine, clip_path, flags);
454 if (witem->size_pixels) {
455 witem->cwidth = (int) (witem->width + 0.5);
456 witem->cheight = (int) (witem->height + 0.5);
458 witem->cwidth = (int) (witem->width * item->canvas->pixels_per_unit + 0.5);
459 witem->cheight = (int) (witem->height * item->canvas->pixels_per_unit + 0.5);
462 gtk_widget_set_size_request (witem->widget, witem->cwidth, witem->cheight);
465 witem->cheight = 0.0;
468 recalc_bounds (witem);
472 gnome_canvas_widget_render (GnomeCanvasItem *item,
476 GnomeCanvasWidget *witem;
478 witem = GNOME_CANVAS_WIDGET (item);
481 gtk_widget_queue_draw (witem->widget);
487 gnome_canvas_widget_draw (GnomeCanvasItem *item,
488 GdkDrawable *drawable,
490 int width, int height)
493 GnomeCanvasWidget *witem;
495 witem = GNOME_CANVAS_WIDGET (item);
498 gtk_widget_queue_draw (witem->widget);
503 gnome_canvas_widget_point (GnomeCanvasItem *item, double x, double y,
504 int cx, int cy, GnomeCanvasItem **actual_item)
506 GnomeCanvasWidget *witem;
507 double x1, y1, x2, y2;
510 witem = GNOME_CANVAS_WIDGET (item);
514 gnome_canvas_c2w (item->canvas, witem->cx, witem->cy, &x1, &y1);
516 x2 = x1 + (witem->cwidth - 1) / item->canvas->pixels_per_unit;
517 y2 = y1 + (witem->cheight - 1) / item->canvas->pixels_per_unit;
519 /* Is point inside widget bounds? */
521 if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2))
524 /* Point is outside widget bounds */
540 return sqrt (dx * dx + dy * dy);
544 gnome_canvas_widget_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
546 GnomeCanvasWidget *witem;
548 witem = GNOME_CANVAS_WIDGET (item);
553 switch (witem->anchor) {
560 case GTK_ANCHOR_CENTER:
562 *x1 -= witem->width / 2.0;
575 switch (witem->anchor) {
582 case GTK_ANCHOR_CENTER:
584 *y1 -= witem->height / 2.0;
590 *y1 -= witem->height;
597 *x2 = *x1 + witem->width;
598 *y2 = *y1 + witem->height;