GObject canvas changes
[ardour.git] / gtk2_ardour / canvas-simpleline.c
1 #include <stdio.h>
2 #include <math.h>
3 #include <libgnomecanvas/libgnomecanvas.h>
4
5 #include "canvas-simpleline.h"
6 #include "rgb_macros.h"
7 #include "gettext.h"
8 #define _(Text)  dgettext (PACKAGE,Text)
9
10 enum {
11         PROP_0,
12         PROP_X1,
13         PROP_Y1,
14         PROP_X2,
15         PROP_Y2,
16         PROP_COLOR_RGBA
17 };
18
19 static void gnome_canvas_simpleline_class_init (GnomeCanvasSimpleLineClass *class);
20 static void gnome_canvas_simpleline_init       (GnomeCanvasSimpleLine      *simpleline);
21 static void gnome_canvas_simpleline_set_property (GObject        *object,
22                                                   guint            prop_id,
23                                                   const GValue   *value,
24                                                   GParamSpec     *pspec);
25 static void gnome_canvas_simpleline_get_property (GObject        *object,
26                                                   guint           prop_id,
27                                                   GValue         *value,
28                                                   GParamSpec     *pspec);
29
30 static void   gnome_canvas_simpleline_update      (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
31 static void   gnome_canvas_simpleline_bounds      (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
32 static double gnome_canvas_simpleline_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item);
33 static void   gnome_canvas_simpleline_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
34 static void   gnome_canvas_simpleline_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
35
36 static GnomeCanvasItemClass *parent_class;
37
38
39 GtkType
40 gnome_canvas_simpleline_get_type (void)
41 {
42         static GtkType simpleline_type = 0;
43
44         if (!simpleline_type) {
45                 GtkTypeInfo simpleline_info = {
46                         "GnomeCanvasSimpleLine",
47                         sizeof (GnomeCanvasSimpleLine),
48                         sizeof (GnomeCanvasSimpleLineClass),
49                         (GtkClassInitFunc) gnome_canvas_simpleline_class_init,
50                         (GtkObjectInitFunc) gnome_canvas_simpleline_init,
51                         NULL, /* reserved_1 */
52                         NULL, /* reserved_2 */
53                         (GtkClassInitFunc) NULL
54                 };
55
56                 simpleline_type = gtk_type_unique (gnome_canvas_item_get_type (), &simpleline_info);
57         }
58
59         return simpleline_type;
60 }
61
62 static void
63 gnome_canvas_simpleline_class_init (GnomeCanvasSimpleLineClass *class)
64 {
65         GObjectClass *object_class;
66         GnomeCanvasItemClass *item_class;
67
68         object_class = G_OBJECT_CLASS (class);
69         item_class = (GnomeCanvasItemClass *) class;
70
71         parent_class = gtk_type_class (gnome_canvas_item_get_type ());
72
73         object_class->set_property = gnome_canvas_simpleline_set_property;
74         object_class->get_property = gnome_canvas_simpleline_get_property;
75         
76         g_object_class_install_property (object_class,
77                                          PROP_X1,
78                                          g_param_spec_double ("x1",
79                                                               _("x1"),
80                                                               _("x coordinate of upper left corner of rect"),
81                                                               -G_MAXDOUBLE,
82                                                               G_MAXDOUBLE,
83                                                               0.0,
84                                                               G_PARAM_READWRITE));  
85         
86         g_object_class_install_property (object_class,
87                                          PROP_Y1,
88                                          g_param_spec_double ("y1",
89                                                               _("y1"),
90                                                               _("y coordinate of upper left corner of rect "),
91                                                               -G_MAXDOUBLE,
92                                                               G_MAXDOUBLE,
93                                                               0.0,
94                                                               G_PARAM_READWRITE));  
95         
96
97         g_object_class_install_property (object_class,
98                                          PROP_X2,
99                                          g_param_spec_double ("x2",
100                                                               _("x2"),
101                                                               _("x coordinate of lower right corner of rect"),
102                                                               -G_MAXDOUBLE,
103                                                               G_MAXDOUBLE,
104                                                               0.0,
105                                                               G_PARAM_READWRITE));  
106         
107         g_object_class_install_property (object_class,
108                                          PROP_Y2,
109                                          g_param_spec_double ("y2",
110                                                               _("y2"),
111                                                               _("y coordinate of lower right corner of rect "),
112                                                               -G_MAXDOUBLE,
113                                                               G_MAXDOUBLE,
114                                                               0.0,
115                                                               G_PARAM_READWRITE));  
116         g_object_class_install_property (object_class,
117                                          PROP_COLOR_RGBA,
118                                          g_param_spec_uint ("color_rgba",
119                                                             _("color rgba"),
120                                                             _("color of line"),
121                                                             0,
122                                                             G_MAXUINT,
123                                                             0,
124                                                             G_PARAM_READWRITE));  
125         
126         item_class->update = gnome_canvas_simpleline_update;
127         item_class->bounds = gnome_canvas_simpleline_bounds;
128         item_class->point = gnome_canvas_simpleline_point;
129         item_class->render = gnome_canvas_simpleline_render;
130         item_class->draw = gnome_canvas_simpleline_draw;
131 }
132
133 static void
134 gnome_canvas_simpleline_init (GnomeCanvasSimpleLine *simpleline)
135 {
136         simpleline->x1 = 0.0;
137         simpleline->y1 = 0.0;
138         simpleline->x2 = 0.0;
139         simpleline->y2 = 0.0;
140         simpleline->color = RGBA_TO_UINT(98,123,174,241);
141         simpleline->horizontal = TRUE; /* reset in the _update() method */
142         // GTK2FIX
143         // GNOME_CANVAS_ITEM(simpleline)->object.flags |= GNOME_CANVAS_ITEM_NO_AUTO_REDRAW;
144 }
145
146 static void
147 gnome_canvas_simpleline_bounds_world (GnomeCanvasItem *item, int* ix1, int* iy1, int* ix2, int* iy2)
148 {
149         double x1, x2, y1, y2;
150         ArtPoint i1, i2;
151         ArtPoint w1, w2;
152         double i2w[6];
153         GnomeCanvasSimpleLine *simpleline = GNOME_CANVAS_SIMPLELINE(item);
154
155         gnome_canvas_simpleline_bounds (item, &x1, &y1, &x2, &y2);
156
157         i1.x = x1;
158         i1.y = y1;
159         i2.x = x2;
160         i2.y = y2;
161         
162         gnome_canvas_item_i2w_affine (item, i2w);
163         art_affine_point (&w1, &i1, i2w);
164         art_affine_point (&w2, &i2, i2w);
165
166         *ix1 = (int) rint(w1.x);
167         *ix2 = (int) rint(w2.x);
168         *iy1 = (int) rint(w1.y);
169         *iy2 = (int) rint(w2.y);
170
171         /* the update rect has to be of non-zero width and height */
172
173         if (x1 == x2) {
174                 simpleline->horizontal = FALSE;
175                 *ix2 += 1;
176         } else {
177                 simpleline->horizontal = TRUE;
178                 *iy2 += 1;
179         }
180 }
181
182 static void 
183 gnome_canvas_simpleline_reset_bounds (GnomeCanvasItem *item)
184 {
185         int Ix1, Ix2, Iy1, Iy2;
186
187         gnome_canvas_simpleline_bounds_world (item, &Ix1, &Iy1, &Ix2, &Iy2);
188         gnome_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
189 }
190
191 /* 
192  * CANVAS CALLBACKS 
193  */
194
195 static void
196 gnome_canvas_simpleline_set_property (GObject      *object,
197                                       guint         prop_id,
198                                       const GValue *value,
199                                       GParamSpec   *pspec)
200
201 {
202         GnomeCanvasSimpleLine *simpleline;
203         int update = FALSE;
204         int bounds_changed = FALSE;
205
206         simpleline = GNOME_CANVAS_SIMPLELINE (object);
207
208         switch (prop_id) {
209         case PROP_X1:
210                 if (simpleline->x1 != g_value_get_double (value)) {
211                         simpleline->x1 = g_value_get_double (value);
212                         bounds_changed = TRUE;
213                 }
214                 break;
215
216         case PROP_Y1:
217                 if (simpleline->y1 != g_value_get_double (value)) {
218                         simpleline->y1 = g_value_get_double (value);
219                         bounds_changed = TRUE;
220                 }
221                 break;
222
223         case PROP_X2:
224                 if (simpleline->x2 != g_value_get_double (value)) {
225                         simpleline->x2 = g_value_get_double (value);
226                         bounds_changed = TRUE;
227                 }
228                 break;
229
230         case PROP_Y2:
231                 if (simpleline->y2 != g_value_get_double (value)) {
232                         simpleline->y2 = g_value_get_double (value);
233                         bounds_changed = TRUE;
234                 }
235                 break;
236                 
237         case PROP_COLOR_RGBA:
238                 if (simpleline->color != g_value_get_uint(value)) {
239                         simpleline->color = g_value_get_uint(value);
240                         update = TRUE;
241                 }
242                 break;
243         default:
244                 break;
245         }
246
247         if (update || bounds_changed) {
248                 gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(object));
249         }
250 }
251
252 static void
253 gnome_canvas_simpleline_get_property (GObject      *object,
254                                       guint         prop_id,
255                                       GValue       *value,
256                                       GParamSpec   *pspec)
257 {
258         GnomeCanvasSimpleLine *line = GNOME_CANVAS_SIMPLELINE (object);
259         
260         switch (prop_id) {
261         case PROP_X1:
262                 g_value_set_double (value, line->x1);
263                 break;
264         case PROP_X2:
265                 g_value_set_double (value, line->x2);
266                 break;
267         case PROP_Y1:
268                 g_value_set_double (value, line->y1);
269                 break;
270         case PROP_Y2:
271                 g_value_set_double (value, line->y2);
272                 break;
273         case PROP_COLOR_RGBA:
274                 g_value_set_uint (value, line->color);
275                 break;
276         default:
277                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
278                 break;
279         }
280 }
281
282 static void
283 gnome_canvas_simpleline_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
284 {
285         GnomeCanvasSimpleLine *simpleline;
286         double x;
287         double y;
288
289         simpleline = GNOME_CANVAS_SIMPLELINE (item);
290
291         if (parent_class->update)
292                 (* parent_class->update) (item, affine, clip_path, flags);
293
294         gnome_canvas_simpleline_reset_bounds (item);
295
296         x = simpleline->x1;
297         y = simpleline->y1;
298
299         gnome_canvas_item_i2w (item, &x, &y);
300         gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x, y, &simpleline->bbox_ulx, &simpleline->bbox_uly);
301
302         x = simpleline->x2;
303         y = simpleline->y2;
304
305         gnome_canvas_item_i2w (item, &x, &y);
306         gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x, y, &simpleline->bbox_lrx, &simpleline->bbox_lry);
307 }
308
309 static void
310 gnome_canvas_simpleline_render (GnomeCanvasItem *item,
311                               GnomeCanvasBuf *buf)
312 {
313         GnomeCanvasSimpleLine *simpleline;
314         int end, begin;
315
316         simpleline = GNOME_CANVAS_SIMPLELINE (item);
317
318         if (parent_class->render) {
319                 (*parent_class->render) (item, buf);
320         }
321
322         if (buf->is_bg) {
323                 gnome_canvas_buf_ensure_buf (buf);
324                 buf->is_bg = FALSE;
325         }
326
327         // begin = MAX(simpleline->bbox_ulx,buf->rect.x0);
328         // end = MIN(simpleline->bbox_lrx,buf->rect.x1);
329         
330         begin = simpleline->bbox_ulx;
331         end = simpleline->bbox_lrx;
332
333         if (simpleline->color != 0) {
334                 if (simpleline->horizontal) {
335                         PAINT_HORIZA(buf, simpleline->r, simpleline->g, simpleline->b, simpleline->a, 
336                                      begin, end, simpleline->bbox_uly);
337                 } else {
338                         PAINT_VERTA(buf, simpleline->r, simpleline->g, simpleline->b, simpleline->a, 
339                                     begin, simpleline->bbox_uly, simpleline->bbox_lry);
340                 }
341         }
342 }
343
344 static void
345 gnome_canvas_simpleline_draw (GnomeCanvasItem *item,
346                             GdkDrawable *drawable,
347                             int x, int y,
348                             int width, int height)
349 {
350         GnomeCanvasSimpleLine *simpleline;
351
352         simpleline = GNOME_CANVAS_SIMPLELINE (item);
353
354         if (parent_class->draw) {
355                 (* parent_class->draw) (item, drawable, x, y, width, height);
356         }
357
358         fprintf (stderr, "please don't use the CanvasSimpleLine item in a non-aa Canvas\n");
359         abort ();
360 }
361
362 static void
363 gnome_canvas_simpleline_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
364 {
365         GnomeCanvasSimpleLine *simpleline = GNOME_CANVAS_SIMPLELINE (item);
366
367         *x1 = simpleline->x1;
368         *y1 = simpleline->y1;
369         *x2 = simpleline->x2;
370         *y2 = simpleline->y2;
371 }
372
373 static double
374 gnome_canvas_simpleline_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
375 {
376         GnomeCanvasSimpleLine *simpleline;
377         double x1, y1, x2, y2;
378         double dx, dy;
379
380         simpleline = GNOME_CANVAS_SIMPLELINE (item);
381
382         *actual_item = item;
383
384         /* Find the bounds for the rectangle plus its outline width */
385
386         gnome_canvas_simpleline_bounds (item, &x1, &y1, &x2, &y2);
387
388         /* Is point inside rectangle */
389         
390         if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
391                 return 0.0;
392         }
393
394         /* Point is outside rectangle */
395
396         if (x < x1)
397                 dx = x1 - x;
398         else if (x > x2)
399                 dx = x - x2;
400         else
401                 dx = 0.0;
402
403         if (y < y1)
404                 dy = y1 - y;
405         else if (y > y2)
406                 dy = y - y2;
407         else
408                 dy = 0.0;
409
410         return sqrt (dx * dx + dy * dy);
411 }