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 FooCanvas widget
27 * FooCanvas 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 <glib-object.h>
37 #include "foo-canvas-widget.h"
51 static void foo_canvas_widget_class_init (FooCanvasWidgetClass
*klass
);
52 static void foo_canvas_widget_init (FooCanvasWidget
*witem
);
53 static void foo_canvas_widget_destroy (GtkObject
*object
);
54 static void foo_canvas_widget_get_property (GObject
*object
,
58 static void foo_canvas_widget_set_property (GObject
*object
,
63 static void foo_canvas_widget_update (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, int flags
);
64 static double foo_canvas_widget_point (FooCanvasItem
*item
, double x
, double y
,
65 int cx
, int cy
, FooCanvasItem
**actual_item
);
66 static void foo_canvas_widget_translate (FooCanvasItem
*item
, double dx
, double dy
);
67 static void foo_canvas_widget_bounds (FooCanvasItem
*item
, double *x1
, double *y1
, double *x2
, double *y2
);
69 static void foo_canvas_widget_draw (FooCanvasItem
*item
,
70 GdkDrawable
*drawable
,
71 GdkEventExpose
*event
);
72 static void foo_canvas_widget_map (FooCanvasItem
*item
);
73 static void foo_canvas_widget_unmap (FooCanvasItem
*item
);
75 static FooCanvasItemClass
*parent_class
;
77 G_DEFINE_TYPE (FooCanvasWidget
, foo_canvas_widget
, FOO_TYPE_CANVAS_ITEM
)
80 foo_canvas_widget_class_init (FooCanvasWidgetClass
*klass
)
82 GObjectClass
*gobject_class
;
83 GtkObjectClass
*object_class
;
84 FooCanvasItemClass
*item_class
;
86 gobject_class
= (GObjectClass
*) klass
;
87 object_class
= (GtkObjectClass
*) klass
;
88 item_class
= (FooCanvasItemClass
*) klass
;
90 parent_class
= g_type_class_peek_parent (klass
);
92 gobject_class
->set_property
= foo_canvas_widget_set_property
;
93 gobject_class
->get_property
= foo_canvas_widget_get_property
;
95 g_object_class_install_property
98 g_param_spec_object ("widget", NULL
, NULL
,
101 g_object_class_install_property
104 g_param_spec_double ("x", NULL
, NULL
,
105 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
107 g_object_class_install_property
110 g_param_spec_double ("y", NULL
, NULL
,
111 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
113 g_object_class_install_property
116 g_param_spec_double ("width", NULL
, NULL
,
117 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
119 g_object_class_install_property
122 g_param_spec_double ("height", NULL
, NULL
,
123 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0.0,
125 g_object_class_install_property
128 g_param_spec_enum ("anchor", NULL
, NULL
,
129 GTK_TYPE_ANCHOR_TYPE
,
132 g_object_class_install_property
135 g_param_spec_boolean ("size-pixels", NULL
, NULL
,
139 object_class
->destroy
= foo_canvas_widget_destroy
;
141 item_class
->update
= foo_canvas_widget_update
;
142 item_class
->point
= foo_canvas_widget_point
;
143 item_class
->translate
= foo_canvas_widget_translate
;
144 item_class
->bounds
= foo_canvas_widget_bounds
;
145 item_class
->draw
= foo_canvas_widget_draw
;
146 item_class
->map
= foo_canvas_widget_map
;
147 item_class
->unmap
= foo_canvas_widget_unmap
;
151 foo_canvas_widget_init (FooCanvasWidget
*witem
)
157 witem
->anchor
= GTK_ANCHOR_NW
;
158 witem
->size_pixels
= FALSE
;
162 foo_canvas_widget_destroy (GtkObject
*object
)
164 FooCanvasWidget
*witem
;
166 g_return_if_fail (object
!= NULL
);
167 g_return_if_fail (FOO_IS_CANVAS_WIDGET (object
));
169 witem
= FOO_CANVAS_WIDGET (object
);
171 if (witem
->widget
&& !witem
->in_destroy
) {
172 g_signal_handler_disconnect (G_OBJECT (witem
->widget
), witem
->destroy_id
);
173 gtk_widget_destroy (witem
->widget
);
174 witem
->widget
= NULL
;
177 if (GTK_OBJECT_CLASS (parent_class
)->destroy
)
178 (* GTK_OBJECT_CLASS (parent_class
)->destroy
) (object
);
182 recalc_bounds (FooCanvasWidget
*witem
)
187 item
= FOO_CANVAS_ITEM (witem
);
189 /* Get world coordinates */
193 foo_canvas_item_i2w (item
, &wx
, &wy
);
195 /* Get canvas pixel coordinates */
197 foo_canvas_w2c (item
->canvas
, wx
, wy
, &witem
->cx
, &witem
->cy
);
199 /* Anchor widget item */
201 switch (witem
->anchor
) {
208 case GTK_ANCHOR_CENTER
:
210 witem
->cx
-= witem
->cwidth
/ 2;
216 witem
->cx
-= witem
->cwidth
;
223 switch (witem
->anchor
) {
230 case GTK_ANCHOR_CENTER
:
232 witem
->cy
-= witem
->cheight
/ 2;
238 witem
->cy
-= witem
->cheight
;
247 item
->x1
= witem
->cx
;
248 item
->y1
= witem
->cy
;
249 item
->x2
= witem
->cx
+ witem
->cwidth
;
250 item
->y2
= witem
->cy
+ witem
->cheight
;
253 gtk_layout_move (GTK_LAYOUT (item
->canvas
), witem
->widget
,
259 do_destroy (GtkObject
*object
, gpointer data
)
261 FooCanvasWidget
*witem
;
265 witem
->in_destroy
= TRUE
;
267 gtk_object_destroy (data
);
271 foo_canvas_widget_set_property (GObject
*object
,
277 FooCanvasWidget
*witem
;
282 g_return_if_fail (object
!= NULL
);
283 g_return_if_fail (FOO_IS_CANVAS_WIDGET (object
));
285 item
= FOO_CANVAS_ITEM (object
);
286 witem
= FOO_CANVAS_WIDGET (object
);
294 g_signal_handler_disconnect (G_OBJECT (witem
->widget
), witem
->destroy_id
);
295 gtk_container_remove (GTK_CONTAINER (item
->canvas
), witem
->widget
);
298 obj
= g_value_get_object (value
);
300 witem
->widget
= GTK_WIDGET (obj
);
301 witem
->destroy_id
= g_signal_connect (G_OBJECT (obj
),
302 "destroy", G_CALLBACK (do_destroy
), witem
);
303 gtk_layout_put (GTK_LAYOUT (item
->canvas
), witem
->widget
,
304 witem
->cx
+ item
->canvas
->zoom_xofs
,
305 witem
->cy
+ item
->canvas
->zoom_yofs
);
312 if (witem
->x
!= g_value_get_double (value
))
314 witem
->x
= g_value_get_double (value
);
320 if (witem
->y
!= g_value_get_double (value
))
322 witem
->y
= g_value_get_double (value
);
328 if (witem
->width
!= fabs (g_value_get_double (value
)))
330 witem
->width
= fabs (g_value_get_double (value
));
336 if (witem
->height
!= fabs (g_value_get_double (value
)))
338 witem
->height
= fabs (g_value_get_double (value
));
344 if (witem
->anchor
!= (GtkAnchorType
)g_value_get_enum (value
))
346 witem
->anchor
= g_value_get_enum (value
);
351 case PROP_SIZE_PIXELS
:
352 if (witem
->size_pixels
!= g_value_get_boolean (value
))
354 witem
->size_pixels
= g_value_get_boolean (value
);
360 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
365 (* FOO_CANVAS_ITEM_GET_CLASS (item
)->update
) (item
, 0, 0, 0);
368 recalc_bounds (witem
);
372 foo_canvas_widget_get_property (GObject
*object
,
377 FooCanvasWidget
*witem
;
379 g_return_if_fail (object
!= NULL
);
380 g_return_if_fail (FOO_IS_CANVAS_WIDGET (object
));
382 witem
= FOO_CANVAS_WIDGET (object
);
386 g_value_set_object (value
, (GObject
*) witem
->widget
);
390 g_value_set_double (value
, witem
->x
);
394 g_value_set_double (value
, witem
->y
);
398 g_value_set_double (value
, witem
->width
);
402 g_value_set_double (value
, witem
->height
);
406 g_value_set_enum (value
, witem
->anchor
);
409 case PROP_SIZE_PIXELS
:
410 g_value_set_boolean (value
, witem
->size_pixels
);
414 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
420 foo_canvas_widget_update (FooCanvasItem
*item
, double i2w_dx
, double i2w_dy
, int flags
)
422 FooCanvasWidget
*witem
;
424 witem
= FOO_CANVAS_WIDGET (item
);
426 if (parent_class
->update
)
427 (* parent_class
->update
) (item
, i2w_dx
, i2w_dy
, flags
);
431 if (witem
->size_pixels
) {
432 witem
->cwidth
= (int) (witem
->width
+ 0.5);
433 witem
->cheight
= (int) (witem
->height
+ 0.5);
435 witem
->cwidth
= (int) (witem
->width
* item
->canvas
->pixels_per_unit
+ 0.5);
436 witem
->cheight
= (int) (witem
->height
* item
->canvas
->pixels_per_unit
+ 0.5);
438 req
.width
= witem
->cwidth
;
439 req
.height
= witem
->cheight
;
440 gtk_widget_size_request (witem
->widget
, &req
);
443 witem
->cheight
= 0.0;
446 recalc_bounds (witem
);
450 foo_canvas_widget_draw (FooCanvasItem
*item
,
451 GdkDrawable
*drawable
,
452 GdkEventExpose
*event
)
455 FooCanvasWidget
*witem
;
457 witem
= FOO_CANVAS_WIDGET (item
);
460 gtk_widget_queue_draw (witem
->widget
);
464 foo_canvas_widget_map (FooCanvasItem
*item
)
466 FooCanvasWidget
*witem
= FOO_CANVAS_WIDGET (item
);
467 if (parent_class
->map
)
468 (* parent_class
->map
) (item
);
469 if (witem
->widget
&& gtk_widget_get_visible (witem
->widget
))
470 gtk_widget_map (witem
->widget
);
474 foo_canvas_widget_unmap (FooCanvasItem
*item
)
476 FooCanvasWidget
*witem
= FOO_CANVAS_WIDGET (item
);
477 if (parent_class
->unmap
)
478 (* parent_class
->unmap
) (item
);
479 gtk_widget_unmap (witem
->widget
);
483 foo_canvas_widget_point (FooCanvasItem
*item
, double x
, double y
,
484 int cx
, int cy
, FooCanvasItem
**actual_item
)
486 FooCanvasWidget
*witem
;
487 double x1
, y1
, x2
, y2
;
490 witem
= FOO_CANVAS_WIDGET (item
);
494 foo_canvas_c2w (item
->canvas
, witem
->cx
, witem
->cy
, &x1
, &y1
);
496 x2
= x1
+ (witem
->cwidth
- 1) / item
->canvas
->pixels_per_unit
;
497 y2
= y1
+ (witem
->cheight
- 1) / item
->canvas
->pixels_per_unit
;
499 /* Is point inside widget bounds? */
501 if ((x
>= x1
) && (y
>= y1
) && (x
<= x2
) && (y
<= y2
))
504 /* Point is outside widget bounds */
520 return sqrt (dx
* dx
+ dy
* dy
);
524 foo_canvas_widget_translate (FooCanvasItem
*item
, double dx
, double dy
)
526 FooCanvasWidget
*witem
;
528 witem
= FOO_CANVAS_WIDGET (item
);
536 foo_canvas_widget_bounds (FooCanvasItem
*item
, double *x1
, double *y1
, double *x2
, double *y2
)
538 FooCanvasWidget
*witem
;
540 witem
= FOO_CANVAS_WIDGET (item
);
545 switch (witem
->anchor
) {
552 case GTK_ANCHOR_CENTER
:
554 *x1
-= witem
->width
/ 2.0;
567 switch (witem
->anchor
) {
574 case GTK_ANCHOR_CENTER
:
576 *y1
-= witem
->height
/ 2.0;
582 *y1
-= witem
->height
;
589 *x2
= *x1
+ witem
->width
;
590 *y2
= *y1
+ witem
->height
;