source: trunk/third/libgnomecanvas/libgnomecanvas/gnome-canvas-widget.c @ 18323

Revision 18323, 14.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18322, which included commits to RCS files with non-trunk default branches.
Line 
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 widget.  Tk is
28 * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
29 *
30 *
31 * Author: Federico Mena <federico@nuclecu.unam.mx>
32 */
33
34#include <config.h>
35#include <math.h>
36#include <gtk/gtksignal.h>
37#include "gnome-canvas-widget.h"
38
39enum {
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
48};
49
50
51static void gnome_canvas_widget_class_init (GnomeCanvasWidgetClass *class);
52static void gnome_canvas_widget_init       (GnomeCanvasWidget      *witem);
53static void gnome_canvas_widget_destroy    (GtkObject              *object);
54static void gnome_canvas_widget_get_property (GObject            *object,
55                                              guint               param_id,
56                                              GValue             *value,
57                                              GParamSpec         *pspec);
58static void gnome_canvas_widget_set_property (GObject            *object,
59                                              guint               param_id,
60                                              const GValue       *value,
61                                              GParamSpec         *pspec);
62
63static void   gnome_canvas_widget_update      (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
64static double gnome_canvas_widget_point       (GnomeCanvasItem *item, double x, double y,
65                                               int cx, int cy, GnomeCanvasItem **actual_item);
66static void   gnome_canvas_widget_bounds      (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
67
68static void gnome_canvas_widget_render (GnomeCanvasItem *item,
69                                        GnomeCanvasBuf *buf);
70static void gnome_canvas_widget_draw (GnomeCanvasItem *item,
71                                      GdkDrawable *drawable,
72                                      int x, int y,
73                                      int width, int height);
74
75static GnomeCanvasItemClass *parent_class;
76
77
78GType
79gnome_canvas_widget_get_type (void)
80{
81        static GType widget_type;
82
83        if (!widget_type) {
84                static const GTypeInfo object_info = {
85                        sizeof (GnomeCanvasWidgetClass),
86                        (GBaseInitFunc) NULL,
87                        (GBaseFinalizeFunc) NULL,
88                        (GClassInitFunc) gnome_canvas_widget_class_init,
89                        (GClassFinalizeFunc) NULL,
90                        NULL,                   /* class_data */
91                        sizeof (GnomeCanvasWidget),
92                        0,                      /* n_preallocs */
93                        (GInstanceInitFunc) gnome_canvas_widget_init,
94                        NULL                    /* value_table */
95                };
96
97                widget_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasWidget",
98                                                      &object_info, 0);
99        }
100
101        return widget_type;
102}
103
104static void
105gnome_canvas_widget_class_init (GnomeCanvasWidgetClass *class)
106{
107        GObjectClass *gobject_class;
108        GtkObjectClass *object_class;
109        GnomeCanvasItemClass *item_class;
110
111        gobject_class = (GObjectClass *) class;
112        object_class = (GtkObjectClass *) class;
113        item_class = (GnomeCanvasItemClass *) class;
114
115        parent_class = g_type_class_peek_parent (class);
116
117        gobject_class->set_property = gnome_canvas_widget_set_property;
118        gobject_class->get_property = gnome_canvas_widget_get_property;
119
120        g_object_class_install_property
121                (gobject_class,
122                 PROP_WIDGET,
123                 g_param_spec_object ("widget", NULL, NULL,
124                                      GTK_TYPE_WIDGET,
125                                      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
126        g_object_class_install_property
127                (gobject_class,
128                 PROP_X,
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
133                (gobject_class,
134                 PROP_Y,
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
139                (gobject_class,
140                 PROP_WIDTH,
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
145                (gobject_class,
146                 PROP_HEIGHT,
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
151                (gobject_class,
152                 PROP_ANCHOR,
153                 g_param_spec_enum ("anchor", NULL, NULL,
154                                    GTK_TYPE_ANCHOR_TYPE,
155                                    GTK_ANCHOR_NW,
156                                    (G_PARAM_READABLE | G_PARAM_WRITABLE)));
157        g_object_class_install_property
158                (gobject_class,
159                 PROP_SIZE_PIXELS,
160                 g_param_spec_boolean ("size_pixels", NULL, NULL,
161                                       FALSE,
162                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
163
164        object_class->destroy = gnome_canvas_widget_destroy;
165
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;
171}
172
173static void
174gnome_canvas_widget_init (GnomeCanvasWidget *witem)
175{
176        witem->x = 0.0;
177        witem->y = 0.0;
178        witem->width = 0.0;
179        witem->height = 0.0;
180        witem->anchor = GTK_ANCHOR_NW;
181        witem->size_pixels = FALSE;
182}
183
184static void
185gnome_canvas_widget_destroy (GtkObject *object)
186{
187        GnomeCanvasWidget *witem;
188
189        g_return_if_fail (object != NULL);
190        g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
191
192        witem = GNOME_CANVAS_WIDGET (object);
193
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;
198        }
199
200        if (GTK_OBJECT_CLASS (parent_class)->destroy)
201                (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
202}
203
204static void
205recalc_bounds (GnomeCanvasWidget *witem)
206{
207        GnomeCanvasItem *item;
208        double wx, wy;
209
210        item = GNOME_CANVAS_ITEM (witem);
211
212        /* Get world coordinates */
213
214        wx = witem->x;
215        wy = witem->y;
216        gnome_canvas_item_i2w (item, &wx, &wy);
217
218        /* Get canvas pixel coordinates */
219
220        gnome_canvas_w2c (item->canvas, wx, wy, &witem->cx, &witem->cy);
221
222        /* Anchor widget item */
223
224        switch (witem->anchor) {
225        case GTK_ANCHOR_NW:
226        case GTK_ANCHOR_W:
227        case GTK_ANCHOR_SW:
228                break;
229
230        case GTK_ANCHOR_N:
231        case GTK_ANCHOR_CENTER:
232        case GTK_ANCHOR_S:
233                witem->cx -= witem->cwidth / 2;
234                break;
235
236        case GTK_ANCHOR_NE:
237        case GTK_ANCHOR_E:
238        case GTK_ANCHOR_SE:
239                witem->cx -= witem->cwidth;
240                break;
241
242        default:
243                break;
244        }
245
246        switch (witem->anchor) {
247        case GTK_ANCHOR_NW:
248        case GTK_ANCHOR_N:
249        case GTK_ANCHOR_NE:
250                break;
251
252        case GTK_ANCHOR_W:
253        case GTK_ANCHOR_CENTER:
254        case GTK_ANCHOR_E:
255                witem->cy -= witem->cheight / 2;
256                break;
257
258        case GTK_ANCHOR_SW:
259        case GTK_ANCHOR_S:
260        case GTK_ANCHOR_SE:
261                witem->cy -= witem->cheight;
262                break;
263
264        default:
265                break;
266        }
267
268        /* Bounds */
269
270        item->x1 = witem->cx;
271        item->y1 = witem->cy;
272        item->x2 = witem->cx + witem->cwidth;
273        item->y2 = witem->cy + witem->cheight;
274
275        if (witem->widget)
276                gtk_layout_move (GTK_LAYOUT (item->canvas), witem->widget,
277                                 witem->cx + item->canvas->zoom_xofs,
278                                 witem->cy + item->canvas->zoom_yofs);
279}
280
281static void
282do_destroy (GtkObject *object, gpointer data)
283{
284        GnomeCanvasWidget *witem;
285
286        witem = data;
287
288        witem->in_destroy = TRUE;
289
290        gtk_object_destroy (data);
291}
292
293static void
294gnome_canvas_widget_set_property (GObject            *object,
295                                  guint               param_id,
296                                  const GValue       *value,
297                                  GParamSpec         *pspec)
298{
299        GnomeCanvasItem *item;
300        GnomeCanvasWidget *witem;
301        GObject *obj;
302        int update;
303        int calc_bounds;
304
305        g_return_if_fail (object != NULL);
306        g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
307
308        item = GNOME_CANVAS_ITEM (object);
309        witem = GNOME_CANVAS_WIDGET (object);
310
311        update = FALSE;
312        calc_bounds = FALSE;
313
314        switch (param_id) {
315        case PROP_WIDGET:
316                if (witem->widget) {
317                        g_signal_handler_disconnect (witem->widget, witem->destroy_id);
318                        gtk_container_remove (GTK_CONTAINER (item->canvas), witem->widget);
319                }
320
321                obj = g_value_get_object (value);
322                if (obj) {
323                        witem->widget = GTK_WIDGET (obj);
324                        witem->destroy_id = g_signal_connect (obj, "destroy",
325                                                              G_CALLBACK (do_destroy),
326                                                              witem);
327                        gtk_layout_put (GTK_LAYOUT (item->canvas), witem->widget,
328                                        witem->cx + item->canvas->zoom_xofs,
329                                        witem->cy + item->canvas->zoom_yofs);
330                }
331
332                update = TRUE;
333                break;
334
335        case PROP_X:
336                if (witem->x != g_value_get_double (value))
337                {
338                        witem->x = g_value_get_double (value);
339                        calc_bounds = TRUE;
340                }
341                break;
342
343        case PROP_Y:
344                if (witem->y != g_value_get_double (value))
345                {
346                        witem->y = g_value_get_double (value);
347                        calc_bounds = TRUE;
348                }
349                break;
350
351        case PROP_WIDTH:
352                if (witem->width != fabs (g_value_get_double (value)))
353                {
354                        witem->width = fabs (g_value_get_double (value));
355                        update = TRUE;
356                }
357                break;
358
359        case PROP_HEIGHT:
360                if (witem->height != fabs (g_value_get_double (value)))
361                {
362                        witem->height = fabs (g_value_get_double (value));
363                        update = TRUE;
364                }
365                break;
366
367        case PROP_ANCHOR:
368                if (witem->anchor != g_value_get_enum (value))
369                {
370                        witem->anchor = g_value_get_enum (value);
371                        update = TRUE;
372                }
373                break;
374
375        case PROP_SIZE_PIXELS:
376                if (witem->size_pixels != g_value_get_boolean (value))
377                {
378                        witem->size_pixels = g_value_get_boolean (value);
379                        update = TRUE;
380                }
381                break;
382
383        default:
384                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
385                break;
386        }
387
388        if (update)
389                (* GNOME_CANVAS_ITEM_GET_CLASS (item)->update) (item, NULL, NULL, 0);
390
391        if (calc_bounds)
392                recalc_bounds (witem);
393}
394
395static void
396gnome_canvas_widget_get_property (GObject            *object,
397                                  guint               param_id,
398                                  GValue             *value,
399                                  GParamSpec         *pspec)
400{
401        GnomeCanvasWidget *witem;
402
403        g_return_if_fail (object != NULL);
404        g_return_if_fail (GNOME_IS_CANVAS_WIDGET (object));
405
406        witem = GNOME_CANVAS_WIDGET (object);
407
408        switch (param_id) {
409        case PROP_WIDGET:
410                g_value_set_object (value, (GObject *) witem->widget);
411                break;
412
413        case PROP_X:
414                g_value_set_double (value, witem->x);
415                break;
416
417        case PROP_Y:
418                g_value_set_double (value, witem->y);
419                break;
420
421        case PROP_WIDTH:
422                g_value_set_double (value, witem->width);
423                break;
424
425        case PROP_HEIGHT:
426                g_value_set_double (value, witem->height);
427                break;
428
429        case PROP_ANCHOR:
430                g_value_set_enum (value, witem->anchor);
431                break;
432
433        case PROP_SIZE_PIXELS:
434                g_value_set_boolean (value, witem->size_pixels);
435                break;
436
437        default:
438                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
439                break;
440        }
441}
442
443static void
444gnome_canvas_widget_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
445{
446        GnomeCanvasWidget *witem;
447
448        witem = GNOME_CANVAS_WIDGET (item);
449
450        if (parent_class->update)
451                (* parent_class->update) (item, affine, clip_path, flags);
452
453        if (witem->widget) {
454                if (witem->size_pixels) {
455                        witem->cwidth = (int) (witem->width + 0.5);
456                        witem->cheight = (int) (witem->height + 0.5);
457                } else {
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);
460                }
461
462                gtk_widget_set_size_request (witem->widget, witem->cwidth, witem->cheight);
463        } else {
464                witem->cwidth = 0.0;
465                witem->cheight = 0.0;
466        }
467
468        recalc_bounds (witem);
469}
470
471static void
472gnome_canvas_widget_render (GnomeCanvasItem *item,
473                            GnomeCanvasBuf *buf)
474{
475#if 0
476        GnomeCanvasWidget *witem;
477
478        witem = GNOME_CANVAS_WIDGET (item);
479
480        if (witem->widget)
481                gtk_widget_queue_draw (witem->widget);
482#endif
483
484}
485
486static void
487gnome_canvas_widget_draw (GnomeCanvasItem *item,
488                          GdkDrawable *drawable,
489                          int x, int y,
490                          int width, int height)
491{
492#if 0
493        GnomeCanvasWidget *witem;
494
495        witem = GNOME_CANVAS_WIDGET (item);
496
497        if (witem->widget)
498                gtk_widget_queue_draw (witem->widget);
499#endif
500}
501
502static double
503gnome_canvas_widget_point (GnomeCanvasItem *item, double x, double y,
504                           int cx, int cy, GnomeCanvasItem **actual_item)
505{
506        GnomeCanvasWidget *witem;
507        double x1, y1, x2, y2;
508        double dx, dy;
509
510        witem = GNOME_CANVAS_WIDGET (item);
511
512        *actual_item = item;
513
514        gnome_canvas_c2w (item->canvas, witem->cx, witem->cy, &x1, &y1);
515
516        x2 = x1 + (witem->cwidth - 1) / item->canvas->pixels_per_unit;
517        y2 = y1 + (witem->cheight - 1) / item->canvas->pixels_per_unit;
518
519        /* Is point inside widget bounds? */
520
521        if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2))
522                return 0.0;
523
524        /* Point is outside widget bounds */
525
526        if (x < x1)
527                dx = x1 - x;
528        else if (x > x2)
529                dx = x - x2;
530        else
531                dx = 0.0;
532
533        if (y < y1)
534                dy = y1 - y;
535        else if (y > y2)
536                dy = y - y2;
537        else
538                dy = 0.0;
539
540        return sqrt (dx * dx + dy * dy);
541}
542
543static void
544gnome_canvas_widget_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
545{
546        GnomeCanvasWidget *witem;
547
548        witem = GNOME_CANVAS_WIDGET (item);
549
550        *x1 = witem->x;
551        *y1 = witem->y;
552
553        switch (witem->anchor) {
554        case GTK_ANCHOR_NW:
555        case GTK_ANCHOR_W:
556        case GTK_ANCHOR_SW:
557                break;
558
559        case GTK_ANCHOR_N:
560        case GTK_ANCHOR_CENTER:
561        case GTK_ANCHOR_S:
562                *x1 -= witem->width / 2.0;
563                break;
564
565        case GTK_ANCHOR_NE:
566        case GTK_ANCHOR_E:
567        case GTK_ANCHOR_SE:
568                *x1 -= witem->width;
569                break;
570
571        default:
572                break;
573        }
574
575        switch (witem->anchor) {
576        case GTK_ANCHOR_NW:
577        case GTK_ANCHOR_N:
578        case GTK_ANCHOR_NE:
579                break;
580
581        case GTK_ANCHOR_W:
582        case GTK_ANCHOR_CENTER:
583        case GTK_ANCHOR_E:
584                *y1 -= witem->height / 2.0;
585                break;
586
587        case GTK_ANCHOR_SW:
588        case GTK_ANCHOR_S:
589        case GTK_ANCHOR_SE:
590                *y1 -= witem->height;
591                break;
592
593        default:
594                break;
595        }
596
597        *x2 = *x1 + witem->width;
598        *y2 = *y1 + witem->height;
599}
Note: See TracBrowser for help on using the repository browser.