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