3 different data wheel modes for tranzport, plus lock on writes, and more
[ardour.git] / gtk2_ardour / canvas-ruler.c
1 #include <stdio.h>
2 #include <math.h>
3 #include <libgnomecanvas/libgnomecanvas.h>
4
5 #include "canvas-ruler.h"
6 #include "rgb_macros.h"
7
8 enum {
9         PROP_0,
10         PROP_X1,
11         PROP_Y1,
12         PROP_X2,
13         PROP_Y2,
14         PROP_FRAMES_PER_UNIT,
15         PROP_FILL_COLOR,
16         PROP_TICK_COLOR
17
18 };
19
20 static void gnome_canvas_ruler_class_init (GnomeCanvasRulerClass *class);
21 static void gnome_canvas_ruler_init       (GnomeCanvasRuler      *ruler);
22 static void gnome_canvas_ruler_set_arg    (GObject              *object,
23                                            guint                   prop_id
24                                            const GValue   *value,
25                                            GParamSpec     *pspec);
26 static void gnome_canvas_ruler_get_arg    (GObject              *object,
27                                            guint                   prop_id
28                                            GValue   *value,
29                                            GParamSpec     *pspec);
30 static void   gnome_canvas_ruler_update      (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
31 static void   gnome_canvas_ruler_bounds      (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
32 static double gnome_canvas_ruler_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item);
33 static void   gnome_canvas_ruler_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
34 static void   gnome_canvas_ruler_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_ruler_get_type (void)
41 {
42         static GtkType ruler_type = 0;
43
44         if (!ruler_type) {
45                 GtkTypeInfo ruler_info = {
46                         "GnomeCanvasRuler",
47                         sizeof (GnomeCanvasRuler),
48                         sizeof (GnomeCanvasRulerClass),
49                         (GtkClassInitFunc) gnome_canvas_ruler_class_init,
50                         (GtkObjectInitFunc) gnome_canvas_ruler_init,
51                         NULL, /* reserved_1 */
52                         NULL, /* reserved_2 */
53                         (GtkClassInitFunc) NULL
54                 };
55
56                 ruler_type = gtk_type_unique (gnome_canvas_item_get_type (), &ruler_info);
57         }
58
59         return ruler_type;
60 }
61
62 static void
63 gnome_canvas_ruler_class_init (GnomeCanvasRulerClass *class)
64 {
65         GtkObjectClass *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_ruler_set_property;
74         object_class->get_property = gnome_canvas_ruler_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         
117         
118         g_object_class_install_property (object_class,
119                                          PROP_FRAMES_PER_UNIT,
120                                          g_param_spec_long ("frames_per_unit",
121                                                             _("frames_per_unit"),
122                                                             _("frames_per_unit of ruler"),
123                                                             -G_MAXLONG,
124                                                             G_MAXLONG,
125                                                             0,
126                                                             G_PARAM_READWRITE)); 
127         
128         
129         g_object_class_install_property (object_class,
130                                          PROP_FILL_COLOR,
131                                          g_param_spec_uint ("fill_color",
132                                                             _("fill color"),
133                                                             _("color of fill"),
134                                                             0,
135                                                             G_MAXINT,
136                                                             0,
137                                                             G_PARAM_READWRITE)); 
138         
139         
140         g_object_class_install_property (object_class,
141                                          PROP_TICK_COLOR,
142                                          g_param_spec_uint ("tick_color",
143                                                             _("tick color"),
144                                                             _("color of tick"),
145                                                             0,
146                                                             G_MAXINT,
147                                                             0,
148                                                             G_PARAM_READWRITE)); 
149         item_class->update = gnome_canvas_ruler_update;
150         item_class->bounds = gnome_canvas_ruler_bounds;
151         item_class->point = gnome_canvas_ruler_point;
152         item_class->render = gnome_canvas_ruler_render;
153         item_class->draw = gnome_canvas_ruler_draw;
154 }
155
156 static void
157 gnome_canvas_ruler_init (GnomeCanvasRuler *ruler)
158 {
159         ruler->x1 = 0.0;
160         ruler->y1 = 0.0;
161         ruler->x2 = 0.0;
162         ruler->y2 = 0.0;
163         ruler->frames_per_unit = 1;
164         ruler->fill_color = 0;
165         ruler->tick_color = 0;
166
167         // GTK2FIX
168         //GNOME_CANVAS_ITEM(ruler)->object.flags |= GNOME_CANVAS_ITEM_NO_AUTO_REDRAW;
169 }
170
171 static void 
172 gnome_canvas_ruler_reset_bounds (GnomeCanvasItem *item)
173
174 {
175         double x1, x2, y1, y2;
176         ArtPoint i1, i2;
177         ArtPoint w1, w2;
178         int Ix1, Ix2, Iy1, Iy2;
179         double i2w[6];
180
181         gnome_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2);
182
183         i1.x = x1;
184         i1.y = y1;
185         i2.x = x2;
186         i2.y = y2;
187
188         gnome_canvas_item_i2w_affine (item, i2w);
189         art_affine_point (&w1, &i1, i2w);
190         art_affine_point (&w2, &i2, i2w);
191
192         Ix1 = (int) rint(w1.x);
193         Ix2 = (int) rint(w2.x);
194         Iy1 = (int) rint(w1.y);
195         Iy2 = (int) rint(w2.y);
196
197         gnome_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
198 }
199
200 /* 
201  * CANVAS CALLBACKS 
202  */
203
204 static void
205 gnome_canvas_ruler_set_property (GObject *object,
206 guint         prop_id,
207                                       const GValue *value,
208                                       GParamSpec   *pspec)
209 {
210         GnomeCanvasItem *item;
211         GnomeCanvasRuler *ruler;
212         int redraw;
213         int calc_bounds;
214
215         item = GNOME_CANVAS_ITEM (object);
216         ruler = GNOME_CANVAS_RULER (object);
217
218         redraw = FALSE;
219         calc_bounds = FALSE;
220
221         switch (prop_id) {
222         case PROP_X1:
223                 if (ruler->x1 != g_value_get_double (value)) {
224                         ruler->x1 = g_value_get_double (value);
225                         calc_bounds = TRUE;
226                 }
227                 break;
228
229         case PROP_Y1:
230                 if (ruler->y1 != g_value_get_double (value)) {
231                         ruler->y1 = g_value_get_double (value);
232                         calc_bounds = TRUE;
233                 }
234                 break;
235
236         case PROP_X2:
237                 if (ruler->x2 != g_value_get_double (value)) {
238                         ruler->x2 = g_value_get_double (value);
239                         calc_bounds = TRUE;
240                 }
241                 break;
242
243         case PROP_Y2:
244                 if (ruler->y2 != g_value_get_double (value)) {
245                         ruler->y2 = g_value_get_double (value);
246                         calc_bounds = TRUE;
247                 }
248                 break;
249
250         case PROP_FRAMES_PER_UNIT:
251                 if (ruler->frames_per_unit != g_value_get_long(value)) {
252                         ruler->frames_per_unit = g_value_get_long(value);
253                         redraw = TRUE;
254                 }
255                 break;
256
257         case PROP_FILL_COLOR:
258                 if (ruler->fill_color != g_value_get_uint(value)) {
259                         ruler->fill_color = g_value_get_uint(value);
260                         redraw = TRUE;
261                 }
262                 break;
263
264         case PROP_TICK_COLOR:
265                 if (ruler->tick_color != g_value_get_uint(value)) {
266                         ruler->tick_color = g_value_get_uint(value);
267                         redraw = TRUE;
268                 }
269                 break;
270
271         default:
272                 break;
273         }
274
275         if (calc_bounds) {
276                 gnome_canvas_ruler_reset_bounds (item);
277         }
278
279         if (redraw) {
280                 gnome_canvas_item_request_update (item);
281         }
282
283 }
284
285 static void
286 gnome_canvas_ruler_get_property (GObject *object,
287   guint         prop_id,
288                                       GValue       *value,
289                                       GParamSpec   *pspec)
290
291 {
292         GnomeCanvasRuler *ruler;
293
294         ruler = GNOME_CANVAS_RULER (object);
295
296         switch (prop_id) {
297         case PROP_X1:
298           g_value_set_double (value, ruler->x1);
299                 break;
300         case PROP_Y1:
301           g_value_set_double (value, ruler->y1);
302                 break;
303         case PROP_X2:
304           g_value_set_double (value, ruler->x2);
305                 break;
306         case PROP_Y2:
307           g_value_set_double (value, ruler->y2);
308                 break;
309         case PROP_FRAMES_PER_UNIT:
310           g_value_set_long (value, ruler->frames_per_unit);
311                 break;
312         case PROP_FILL_COLOR:
313           g_value_set_uint (value, ruler->fill_color);
314                 break;
315         case PROP_TICK_COLOR:
316           g_value_set_uint (value, ruler->tick_color);
317                 break;
318         default:
319                 arg->type = GTK_TYPE_INVALID;
320                 break;
321         }
322 }
323
324 static void
325 gnome_canvas_ruler_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
326 {
327         GnomeCanvasRuler *ruler;
328         double x;
329         double y;
330
331         ruler = GNOME_CANVAS_RULER (item);
332
333         if (parent_class->update)
334                 (* parent_class->update) (item, affine, clip_path, flags);
335
336         gnome_canvas_ruler_reset_bounds (item);
337
338         x = ruler->x1;
339         y = ruler->y1;
340
341         gnome_canvas_item_i2w (item, &x, &y);
342         gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x, y, &ruler->bbox_ulx, &ruler->bbox_uly);
343
344         x = ruler->x2;
345         y = ruler->y2;
346
347         gnome_canvas_item_i2w (item, &x, &y);
348         gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x, y, &ruler->bbox_lrx, &ruler->bbox_lry);
349
350         UINT_TO_RGB (ruler->tick_color, &ruler->tick_r, &ruler->tick_g, &ruler->tick_b);
351         UINT_TO_RGB (ruler->fill_color, &ruler->fill_r, &ruler->fill_g, &ruler->fill_b);
352 }
353
354 static void
355 gnome_canvas_ruler_render (GnomeCanvasItem *item,
356                               GnomeCanvasBuf *buf)
357 {
358         GnomeCanvasRuler *ruler;
359         int end, begin;
360
361         ruler = GNOME_CANVAS_RULER (item);
362
363         if (parent_class->render) {
364                 (*parent_class->render) (item, buf);
365         }
366
367         if (buf->is_bg) {
368                 gnome_canvas_buf_ensure_buf (buf);
369                 buf->is_bg = FALSE;
370         }
371
372         begin = MAX(ruler->bbox_ulx,buf->rect.x0);
373
374         if (ruler->bbox_lrx >= 0) {
375                 end = MIN(ruler->bbox_lrx,buf->rect.x1);
376         } else {
377                 end = buf->rect.x1;
378         }
379
380         if (begin == end) {
381                 return;
382         }
383
384         PAINT_BOX (buf, ruler->fill_r, ruler->fill_g, ruler->fill_b, 255, begin, ruler->bbox_uly, end, ruler->bbox_lry - 1);
385         PAINT_HORIZ (buf, ruler->tick_r, ruler->tick_g, ruler->tick_b, begin, end, ruler->bbox_lry - 1);
386 }
387
388 static void
389 gnome_canvas_ruler_draw (GnomeCanvasItem *item,
390                             GdkDrawable *drawable,
391                             int x, int y,
392                             int width, int height)
393 {
394         GnomeCanvasRuler *ruler;
395
396         ruler = GNOME_CANVAS_RULER (item);
397
398         if (parent_class->draw) {
399                 (* parent_class->draw) (item, drawable, x, y, width, height);
400         }
401
402         fprintf (stderr, "please don't use the CanvasRuler item in a non-aa Canvas\n");
403         abort ();
404 }
405
406 static void
407 gnome_canvas_ruler_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
408 {
409         GnomeCanvasRuler *ruler = GNOME_CANVAS_RULER (item);
410
411         *x1 = ruler->x1;
412         *y1 = ruler->y1;
413         *x2 = ruler->x2;
414         *y2 = ruler->y2;
415 }
416
417 static double
418 gnome_canvas_ruler_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
419 {
420         GnomeCanvasRuler *ruler;
421         double x1, y1, x2, y2;
422         double dx, dy;
423
424         ruler = GNOME_CANVAS_RULER (item);
425
426         *actual_item = item;
427
428         /* Find the bounds for the rectangle plus its outline width */
429
430         gnome_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2);
431
432         /* Is point inside rectangle */
433         
434         if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
435                 return 0.0;
436         }
437
438         /* Point is outside rectangle */
439
440         if (x < x1)
441                 dx = x1 - x;
442         else if (x > x2)
443                 dx = x - x2;
444         else
445                 dx = 0.0;
446
447         if (y < y1)
448                 dy = y1 - y;
449         else if (y > y2)
450                 dy = y - y2;
451         else
452                 dy = 0.0;
453
454         return sqrt (dx * dx + dy * dy);
455 }