Sets the caret position to the body of a callback.
[anjuta.git] / libfoocanvas / foo-canvas-widget.c
blob0ba8aba77ce356b1ece6267a6bee2603e96ca56a
1 /*
2 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
3 * All rights reserved.
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.
23 @NOTATION@
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>
34 #include <config.h>
35 #include <math.h>
36 #include <glib-object.h>
37 #include "foo-canvas-widget.h"
39 enum {
40 PROP_0,
41 PROP_WIDGET,
42 PROP_X,
43 PROP_Y,
44 PROP_WIDTH,
45 PROP_HEIGHT,
46 PROP_ANCHOR,
47 PROP_SIZE_PIXELS
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,
55 guint param_id,
56 GValue *value,
57 GParamSpec *pspec);
58 static void foo_canvas_widget_set_property (GObject *object,
59 guint param_id,
60 const GValue *value,
61 GParamSpec *pspec);
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)
79 static void
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
96 (gobject_class,
97 PROP_WIDGET,
98 g_param_spec_object ("widget", NULL, NULL,
99 GTK_TYPE_WIDGET,
100 G_PARAM_READWRITE));
101 g_object_class_install_property
102 (gobject_class,
103 PROP_X,
104 g_param_spec_double ("x", NULL, NULL,
105 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
106 G_PARAM_READWRITE));
107 g_object_class_install_property
108 (gobject_class,
109 PROP_Y,
110 g_param_spec_double ("y", NULL, NULL,
111 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
112 G_PARAM_READWRITE));
113 g_object_class_install_property
114 (gobject_class,
115 PROP_WIDTH,
116 g_param_spec_double ("width", NULL, NULL,
117 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
118 G_PARAM_READWRITE));
119 g_object_class_install_property
120 (gobject_class,
121 PROP_HEIGHT,
122 g_param_spec_double ("height", NULL, NULL,
123 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
124 G_PARAM_READWRITE));
125 g_object_class_install_property
126 (gobject_class,
127 PROP_ANCHOR,
128 g_param_spec_enum ("anchor", NULL, NULL,
129 GTK_TYPE_ANCHOR_TYPE,
130 GTK_ANCHOR_NW,
131 G_PARAM_READWRITE));
132 g_object_class_install_property
133 (gobject_class,
134 PROP_SIZE_PIXELS,
135 g_param_spec_boolean ("size-pixels", NULL, NULL,
136 FALSE,
137 G_PARAM_READWRITE));
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;
150 static void
151 foo_canvas_widget_init (FooCanvasWidget *witem)
153 witem->x = 0.0;
154 witem->y = 0.0;
155 witem->width = 0.0;
156 witem->height = 0.0;
157 witem->anchor = GTK_ANCHOR_NW;
158 witem->size_pixels = FALSE;
161 static void
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);
181 static void
182 recalc_bounds (FooCanvasWidget *witem)
184 FooCanvasItem *item;
185 double wx, wy;
187 item = FOO_CANVAS_ITEM (witem);
189 /* Get world coordinates */
191 wx = witem->x;
192 wy = witem->y;
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) {
202 case GTK_ANCHOR_NW:
203 case GTK_ANCHOR_W:
204 case GTK_ANCHOR_SW:
205 break;
207 case GTK_ANCHOR_N:
208 case GTK_ANCHOR_CENTER:
209 case GTK_ANCHOR_S:
210 witem->cx -= witem->cwidth / 2;
211 break;
213 case GTK_ANCHOR_NE:
214 case GTK_ANCHOR_E:
215 case GTK_ANCHOR_SE:
216 witem->cx -= witem->cwidth;
217 break;
219 default:
220 break;
223 switch (witem->anchor) {
224 case GTK_ANCHOR_NW:
225 case GTK_ANCHOR_N:
226 case GTK_ANCHOR_NE:
227 break;
229 case GTK_ANCHOR_W:
230 case GTK_ANCHOR_CENTER:
231 case GTK_ANCHOR_E:
232 witem->cy -= witem->cheight / 2;
233 break;
235 case GTK_ANCHOR_SW:
236 case GTK_ANCHOR_S:
237 case GTK_ANCHOR_SE:
238 witem->cy -= witem->cheight;
239 break;
241 default:
242 break;
245 /* Bounds */
247 item->x1 = witem->cx;
248 item->y1 = witem->cy;
249 item->x2 = witem->cx + witem->cwidth;
250 item->y2 = witem->cy + witem->cheight;
252 if (witem->widget)
253 gtk_layout_move (GTK_LAYOUT (item->canvas), witem->widget,
254 witem->cx,
255 witem->cy);
258 static void
259 do_destroy (GtkObject *object, gpointer data)
261 FooCanvasWidget *witem;
263 witem = data;
265 witem->in_destroy = TRUE;
267 gtk_object_destroy (data);
270 static void
271 foo_canvas_widget_set_property (GObject *object,
272 guint param_id,
273 const GValue *value,
274 GParamSpec *pspec)
276 FooCanvasItem *item;
277 FooCanvasWidget *witem;
278 GObject *obj;
279 int update;
280 int calc_bounds;
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);
288 update = FALSE;
289 calc_bounds = FALSE;
291 switch (param_id) {
292 case PROP_WIDGET:
293 if (witem->widget) {
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);
299 if (obj) {
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);
308 update = TRUE;
309 break;
311 case PROP_X:
312 if (witem->x != g_value_get_double (value))
314 witem->x = g_value_get_double (value);
315 calc_bounds = TRUE;
317 break;
319 case PROP_Y:
320 if (witem->y != g_value_get_double (value))
322 witem->y = g_value_get_double (value);
323 calc_bounds = TRUE;
325 break;
327 case PROP_WIDTH:
328 if (witem->width != fabs (g_value_get_double (value)))
330 witem->width = fabs (g_value_get_double (value));
331 update = TRUE;
333 break;
335 case PROP_HEIGHT:
336 if (witem->height != fabs (g_value_get_double (value)))
338 witem->height = fabs (g_value_get_double (value));
339 update = TRUE;
341 break;
343 case PROP_ANCHOR:
344 if (witem->anchor != (GtkAnchorType)g_value_get_enum (value))
346 witem->anchor = g_value_get_enum (value);
347 update = TRUE;
349 break;
351 case PROP_SIZE_PIXELS:
352 if (witem->size_pixels != g_value_get_boolean (value))
354 witem->size_pixels = g_value_get_boolean (value);
355 update = TRUE;
357 break;
359 default:
360 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
361 break;
364 if (update)
365 (* FOO_CANVAS_ITEM_GET_CLASS (item)->update) (item, 0, 0, 0);
367 if (calc_bounds)
368 recalc_bounds (witem);
371 static void
372 foo_canvas_widget_get_property (GObject *object,
373 guint param_id,
374 GValue *value,
375 GParamSpec *pspec)
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);
384 switch (param_id) {
385 case PROP_WIDGET:
386 g_value_set_object (value, (GObject *) witem->widget);
387 break;
389 case PROP_X:
390 g_value_set_double (value, witem->x);
391 break;
393 case PROP_Y:
394 g_value_set_double (value, witem->y);
395 break;
397 case PROP_WIDTH:
398 g_value_set_double (value, witem->width);
399 break;
401 case PROP_HEIGHT:
402 g_value_set_double (value, witem->height);
403 break;
405 case PROP_ANCHOR:
406 g_value_set_enum (value, witem->anchor);
407 break;
409 case PROP_SIZE_PIXELS:
410 g_value_set_boolean (value, witem->size_pixels);
411 break;
413 default:
414 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
415 break;
419 static void
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);
429 if (witem->widget) {
430 GtkRequisition req;
431 if (witem->size_pixels) {
432 witem->cwidth = (int) (witem->width + 0.5);
433 witem->cheight = (int) (witem->height + 0.5);
434 } else {
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);
441 } else {
442 witem->cwidth = 0.0;
443 witem->cheight = 0.0;
446 recalc_bounds (witem);
449 static void
450 foo_canvas_widget_draw (FooCanvasItem *item,
451 GdkDrawable *drawable,
452 GdkEventExpose *event)
454 #if 0
455 FooCanvasWidget *witem;
457 witem = FOO_CANVAS_WIDGET (item);
459 if (witem->widget)
460 gtk_widget_queue_draw (witem->widget);
461 #endif
463 static void
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);
473 static void
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);
482 static double
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;
488 double dx, dy;
490 witem = FOO_CANVAS_WIDGET (item);
492 *actual_item = 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))
502 return 0.0;
504 /* Point is outside widget bounds */
506 if (x < x1)
507 dx = x1 - x;
508 else if (x > x2)
509 dx = x - x2;
510 else
511 dx = 0.0;
513 if (y < y1)
514 dy = y1 - y;
515 else if (y > y2)
516 dy = y - y2;
517 else
518 dy = 0.0;
520 return sqrt (dx * dx + dy * dy);
523 static void
524 foo_canvas_widget_translate (FooCanvasItem *item, double dx, double dy)
526 FooCanvasWidget *witem;
528 witem = FOO_CANVAS_WIDGET (item);
530 witem->x += dx;
531 witem->y += dy;
535 static void
536 foo_canvas_widget_bounds (FooCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
538 FooCanvasWidget *witem;
540 witem = FOO_CANVAS_WIDGET (item);
542 *x1 = witem->x;
543 *y1 = witem->y;
545 switch (witem->anchor) {
546 case GTK_ANCHOR_NW:
547 case GTK_ANCHOR_W:
548 case GTK_ANCHOR_SW:
549 break;
551 case GTK_ANCHOR_N:
552 case GTK_ANCHOR_CENTER:
553 case GTK_ANCHOR_S:
554 *x1 -= witem->width / 2.0;
555 break;
557 case GTK_ANCHOR_NE:
558 case GTK_ANCHOR_E:
559 case GTK_ANCHOR_SE:
560 *x1 -= witem->width;
561 break;
563 default:
564 break;
567 switch (witem->anchor) {
568 case GTK_ANCHOR_NW:
569 case GTK_ANCHOR_N:
570 case GTK_ANCHOR_NE:
571 break;
573 case GTK_ANCHOR_W:
574 case GTK_ANCHOR_CENTER:
575 case GTK_ANCHOR_E:
576 *y1 -= witem->height / 2.0;
577 break;
579 case GTK_ANCHOR_SW:
580 case GTK_ANCHOR_S:
581 case GTK_ANCHOR_SE:
582 *y1 -= witem->height;
583 break;
585 default:
586 break;
589 *x2 = *x1 + witem->width;
590 *y2 = *y1 + witem->height;