Initial import of gtk2_ardour.
[ardour.git] / gtk2_ardour / canvas-ruler.c
1 #include <stdio.h>
2 #include <math.h>
3 #include <gtk-canvas.h>
4
5 #include "canvas-ruler.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_FRAMES_PER_UNIT,
15         ARG_FILL_COLOR,
16         ARG_TICK_COLOR
17
18 };
19
20 static void gtk_canvas_ruler_class_init (GtkCanvasRulerClass *class);
21 static void gtk_canvas_ruler_init       (GtkCanvasRuler      *ruler);
22 static void gtk_canvas_ruler_set_arg    (GtkObject              *object,
23                                               GtkArg                 *arg,
24                                               guint                   arg_id);
25 static void gtk_canvas_ruler_get_arg    (GtkObject              *object,
26                                               GtkArg                 *arg,
27                                               guint                   arg_id);
28
29 static void   gtk_canvas_ruler_update      (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
30 static void   gtk_canvas_ruler_bounds      (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
31 static double gtk_canvas_ruler_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item);
32 static void   gtk_canvas_ruler_render (GtkCanvasItem *item, GtkCanvasBuf *buf);
33 static void   gtk_canvas_ruler_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
34
35 static GtkCanvasItemClass *parent_class;
36
37
38 GtkType
39 gtk_canvas_ruler_get_type (void)
40 {
41         static GtkType ruler_type = 0;
42
43         if (!ruler_type) {
44                 GtkTypeInfo ruler_info = {
45                         "GtkCanvasRuler",
46                         sizeof (GtkCanvasRuler),
47                         sizeof (GtkCanvasRulerClass),
48                         (GtkClassInitFunc) gtk_canvas_ruler_class_init,
49                         (GtkObjectInitFunc) gtk_canvas_ruler_init,
50                         NULL, /* reserved_1 */
51                         NULL, /* reserved_2 */
52                         (GtkClassInitFunc) NULL
53                 };
54
55                 ruler_type = gtk_type_unique (gtk_canvas_item_get_type (), &ruler_info);
56         }
57
58         return ruler_type;
59 }
60
61 static void
62 gtk_canvas_ruler_class_init (GtkCanvasRulerClass *class)
63 {
64         GtkObjectClass *object_class;
65         GtkCanvasItemClass *item_class;
66
67         object_class = (GtkObjectClass *) class;
68         item_class = (GtkCanvasItemClass *) class;
69
70         parent_class = gtk_type_class (gtk_canvas_item_get_type ());
71
72         gtk_object_add_arg_type ("GtkCanvasRuler::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1);
73         gtk_object_add_arg_type ("GtkCanvasRuler::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1);
74         gtk_object_add_arg_type ("GtkCanvasRuler::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2);
75         gtk_object_add_arg_type ("GtkCanvasRuler::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2);
76         gtk_object_add_arg_type ("GtkCanvasRuler::frames_per_unit", GTK_TYPE_LONG, GTK_ARG_READWRITE, ARG_FRAMES_PER_UNIT);
77         gtk_object_add_arg_type ("GtkCanvasRuler::fill_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR);
78         gtk_object_add_arg_type ("GtkCanvasRuler::tick_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_TICK_COLOR);
79
80         object_class->set_arg = gtk_canvas_ruler_set_arg;
81         object_class->get_arg = gtk_canvas_ruler_get_arg;
82
83         item_class->update = gtk_canvas_ruler_update;
84         item_class->bounds = gtk_canvas_ruler_bounds;
85         item_class->point = gtk_canvas_ruler_point;
86         item_class->render = gtk_canvas_ruler_render;
87         item_class->draw = gtk_canvas_ruler_draw;
88 }
89
90 static void
91 gtk_canvas_ruler_init (GtkCanvasRuler *ruler)
92 {
93         ruler->x1 = 0.0;
94         ruler->y1 = 0.0;
95         ruler->x2 = 0.0;
96         ruler->y2 = 0.0;
97         ruler->frames_per_unit = 1;
98         ruler->fill_color = 0;
99         ruler->tick_color = 0;
100
101         GTK_CANVAS_ITEM(ruler)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW;
102 }
103
104 static void 
105 gtk_canvas_ruler_reset_bounds (GtkCanvasItem *item)
106
107 {
108         double x1, x2, y1, y2;
109         ArtPoint i1, i2;
110         ArtPoint w1, w2;
111         int Ix1, Ix2, Iy1, Iy2;
112         double i2w[6];
113
114         gtk_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2);
115
116         i1.x = x1;
117         i1.y = y1;
118         i2.x = x2;
119         i2.y = y2;
120
121         gtk_canvas_item_i2w_affine (item, i2w);
122         art_affine_point (&w1, &i1, i2w);
123         art_affine_point (&w2, &i2, i2w);
124
125         Ix1 = (int) rint(w1.x);
126         Ix2 = (int) rint(w2.x);
127         Iy1 = (int) rint(w1.y);
128         Iy2 = (int) rint(w2.y);
129
130         gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
131 }
132
133 /* 
134  * CANVAS CALLBACKS 
135  */
136
137 static void
138 gtk_canvas_ruler_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
139 {
140         GtkCanvasItem *item;
141         GtkCanvasRuler *ruler;
142         int redraw;
143         int calc_bounds;
144
145         item = GTK_CANVAS_ITEM (object);
146         ruler = GTK_CANVAS_RULER (object);
147
148         redraw = FALSE;
149         calc_bounds = FALSE;
150
151         switch (arg_id) {
152         case ARG_X1:
153                 if (ruler->x1 != GTK_VALUE_DOUBLE (*arg)) {
154                         ruler->x1 = GTK_VALUE_DOUBLE (*arg);
155                         calc_bounds = TRUE;
156                 }
157                 break;
158
159         case ARG_Y1:
160                 if (ruler->y1 != GTK_VALUE_DOUBLE (*arg)) {
161                         ruler->y1 = GTK_VALUE_DOUBLE (*arg);
162                         calc_bounds = TRUE;
163                 }
164                 break;
165
166         case ARG_X2:
167                 if (ruler->x2 != GTK_VALUE_DOUBLE (*arg)) {
168                         ruler->x2 = GTK_VALUE_DOUBLE (*arg);
169                         calc_bounds = TRUE;
170                 }
171                 break;
172
173         case ARG_Y2:
174                 if (ruler->y2 != GTK_VALUE_DOUBLE (*arg)) {
175                         ruler->y2 = GTK_VALUE_DOUBLE (*arg);
176                         calc_bounds = TRUE;
177                 }
178                 break;
179
180         case ARG_FRAMES_PER_UNIT:
181                 if (ruler->frames_per_unit != GTK_VALUE_LONG(*arg)) {
182                         ruler->frames_per_unit = GTK_VALUE_LONG(*arg);
183                         redraw = TRUE;
184                 }
185                 break;
186
187         case ARG_FILL_COLOR:
188                 if (ruler->fill_color != GTK_VALUE_INT(*arg)) {
189                         ruler->fill_color = GTK_VALUE_INT(*arg);
190                         redraw = TRUE;
191                 }
192                 break;
193
194         case ARG_TICK_COLOR:
195                 if (ruler->tick_color != GTK_VALUE_INT(*arg)) {
196                         ruler->tick_color = GTK_VALUE_INT(*arg);
197                         redraw = TRUE;
198                 }
199                 break;
200
201         default:
202                 break;
203         }
204
205         if (calc_bounds) {
206                 gtk_canvas_ruler_reset_bounds (item);
207         }
208
209         if (redraw) {
210                 gtk_canvas_item_request_update (item);
211         }
212
213 }
214
215 static void
216 gtk_canvas_ruler_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
217 {
218         GtkCanvasRuler *ruler;
219
220         ruler = GTK_CANVAS_RULER (object);
221
222         switch (arg_id) {
223         case ARG_X1:
224                 GTK_VALUE_DOUBLE (*arg) = ruler->x1;
225                 break;
226         case ARG_Y1:
227                 GTK_VALUE_DOUBLE (*arg) = ruler->y1;
228                 break;
229         case ARG_X2:
230                 GTK_VALUE_DOUBLE (*arg) = ruler->x2;
231                 break;
232         case ARG_Y2:
233                 GTK_VALUE_DOUBLE (*arg) = ruler->y2;
234                 break;
235         case ARG_FRAMES_PER_UNIT:
236                 GTK_VALUE_LONG (*arg) = ruler->frames_per_unit;
237                 break;
238         case ARG_FILL_COLOR:
239                 GTK_VALUE_INT (*arg) = ruler->fill_color;
240                 break;
241         case ARG_TICK_COLOR:
242                 GTK_VALUE_INT (*arg) = ruler->tick_color;
243                 break;
244         default:
245                 arg->type = GTK_TYPE_INVALID;
246                 break;
247         }
248 }
249
250 static void
251 gtk_canvas_ruler_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
252 {
253         GtkCanvasRuler *ruler;
254         double x;
255         double y;
256
257         ruler = GTK_CANVAS_RULER (item);
258
259         if (parent_class->update)
260                 (* parent_class->update) (item, affine, clip_path, flags);
261
262         gtk_canvas_ruler_reset_bounds (item);
263
264         x = ruler->x1;
265         y = ruler->y1;
266
267         gtk_canvas_item_i2w (item, &x, &y);
268         gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &ruler->bbox_ulx, &ruler->bbox_uly);
269
270         x = ruler->x2;
271         y = ruler->y2;
272
273         gtk_canvas_item_i2w (item, &x, &y);
274         gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &ruler->bbox_lrx, &ruler->bbox_lry);
275
276         UINT_TO_RGB (ruler->tick_color, &ruler->tick_r, &ruler->tick_g, &ruler->tick_b);
277         UINT_TO_RGB (ruler->fill_color, &ruler->fill_r, &ruler->fill_g, &ruler->fill_b);
278 }
279
280 static void
281 gtk_canvas_ruler_render (GtkCanvasItem *item,
282                               GtkCanvasBuf *buf)
283 {
284         GtkCanvasRuler *ruler;
285         int end, begin;
286
287         ruler = GTK_CANVAS_RULER (item);
288
289         if (parent_class->render) {
290                 (*parent_class->render) (item, buf);
291         }
292
293         if (buf->is_bg) {
294                 gtk_canvas_buf_ensure_buf (buf);
295                 buf->is_bg = FALSE;
296         }
297
298         begin = MAX(ruler->bbox_ulx,buf->rect.x0);
299
300         if (ruler->bbox_lrx >= 0) {
301                 end = MIN(ruler->bbox_lrx,buf->rect.x1);
302         } else {
303                 end = buf->rect.x1;
304         }
305
306         if (begin == end) {
307                 return;
308         }
309
310         PAINT_BOX (buf, ruler->fill_r, ruler->fill_g, ruler->fill_b, 255, begin, ruler->bbox_uly, end, ruler->bbox_lry - 1);
311         PAINT_HORIZ (buf, ruler->tick_r, ruler->tick_g, ruler->tick_b, begin, end, ruler->bbox_lry - 1);
312 }
313
314 static void
315 gtk_canvas_ruler_draw (GtkCanvasItem *item,
316                             GdkDrawable *drawable,
317                             int x, int y,
318                             int width, int height)
319 {
320         GtkCanvasRuler *ruler;
321
322         ruler = GTK_CANVAS_RULER (item);
323
324         if (parent_class->draw) {
325                 (* parent_class->draw) (item, drawable, x, y, width, height);
326         }
327
328         fprintf (stderr, "please don't use the CanvasRuler item in a non-aa Canvas\n");
329         abort ();
330 }
331
332 static void
333 gtk_canvas_ruler_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
334 {
335         GtkCanvasRuler *ruler = GTK_CANVAS_RULER (item);
336
337         *x1 = ruler->x1;
338         *y1 = ruler->y1;
339         *x2 = ruler->x2;
340         *y2 = ruler->y2;
341 }
342
343 static double
344 gtk_canvas_ruler_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item)
345 {
346         GtkCanvasRuler *ruler;
347         double x1, y1, x2, y2;
348         double dx, dy;
349
350         ruler = GTK_CANVAS_RULER (item);
351
352         *actual_item = item;
353
354         /* Find the bounds for the rectangle plus its outline width */
355
356         gtk_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2);
357
358         /* Is point inside rectangle */
359         
360         if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
361                 return 0.0;
362         }
363
364         /* Point is outside rectangle */
365
366         if (x < x1)
367                 dx = x1 - x;
368         else if (x > x2)
369                 dx = x - x2;
370         else
371                 dx = 0.0;
372
373         if (y < y1)
374                 dy = y1 - y;
375         else if (y > y2)
376                 dy = y - y2;
377         else
378                 dy = 0.0;
379
380         return sqrt (dx * dx + dy * dy);
381 }