4
* $Id: timeline_canvas.c,v 1.4 2001/08/06 08:19:12 richi Exp $
6
* Copyright (C) 2001 Richard Guenther
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
#include "timeline_canvas.h"
35
/* Compute canvas coords from time[s] / track[nr] */
36
#define _HUNIT(x) (50.0*(x))
37
#define _HUNIT1(x) ((x)/50.0)
38
#define _VUNIT(y) (100.0*(y))
39
#define _VUNIT1(y) ((y)/100.0)
48
static void timeline_canvas_destroy(GtkObject *canvas)
50
GnomeCanvas* parent_class;
51
parent_class = gtk_type_class(GNOME_TYPE_CANVAS);
52
GTK_OBJECT_CLASS(parent_class)->destroy(canvas);
53
if (TIMELINE_CANVAS(canvas)->gpsm_handler0)
54
glsig_delete_handler(TIMELINE_CANVAS(canvas)->gpsm_handler0);
55
if (TIMELINE_CANVAS(canvas)->gpsm_handler1)
56
glsig_delete_handler(TIMELINE_CANVAS(canvas)->gpsm_handler1);
59
static void timeline_canvas_class_init(TimelineCanvasClass *class)
61
GtkObjectClass *object_class;
62
object_class = GTK_OBJECT_CLASS(class);
63
object_class->destroy = timeline_canvas_destroy;
66
static void timeline_canvas_init(TimelineCanvas *canvas)
68
canvas->gpsm_handler0 = NULL;
69
canvas->gpsm_handler1 = NULL;
71
canvas->active_item = NULL;
72
canvas->active_group = NULL;
75
GtkType timeline_canvas_get_type(void)
77
static GtkType timeline_canvas_type = 0;
79
if (!timeline_canvas_type){
80
GtkTypeInfo timeline_canvas_info = {
82
sizeof(TimelineCanvas),
83
sizeof(TimelineCanvasClass),
84
(GtkClassInitFunc)timeline_canvas_class_init,
85
(GtkObjectInitFunc)timeline_canvas_init,
86
NULL,NULL,(GtkClassInitFunc)NULL,};
87
timeline_canvas_type = gtk_type_unique(
88
GNOME_TYPE_CANVAS, &timeline_canvas_info);
89
gtk_type_set_chunk_alloc(timeline_canvas_type, 8);
92
return timeline_canvas_type;
95
static void timeline_canvas_handle_root(glsig_handler_t *handler, long sig, va_list va)
97
TimelineCanvas *canvas = TIMELINE_CANVAS(glsig_handler_private(handler));
98
GnomeCanvasItem *root = GNOME_CANVAS_ITEM(
99
gnome_canvas_root(GNOME_CANVAS(canvas)));
102
if (root->object.flags & GNOME_CANVAS_ITEM_AFFINE_FULL) {
103
scale = root->xform[0];
106
gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), 0.0, 0.0,
107
scale*_HUNIT(gpsm_item_hsize(canvas->root)/44100.0/*FIXME*/),
108
_VUNIT(gpsm_item_vsize(canvas->root)));
111
TimelineCanvas *timeline_canvas_new(gpsm_grp_t *root)
113
TimelineCanvas *canvas;
115
canvas = TIMELINE_CANVAS(gtk_type_new(timeline_canvas_get_type()));
118
/* Register handler to adjust canvas and invoke it one time. */
119
canvas->gpsm_handler0 = glsig_add_handler(gpsm_item_emitter(root), GPSM_SIG_ITEM_CHANGED, timeline_canvas_handle_root, canvas);
120
glsig_handler_exec(canvas->gpsm_handler0, GPSM_SIG_ITEM_CHANGED, root);
125
void timeline_canvas_scale(TimelineCanvas *canvas, double scale)
127
double affine[6] = { scale, 0.0, 0.0, 1.0, 0.0, 0.0};
128
gnome_canvas_item_affine_relative(
129
GNOME_CANVAS_ITEM(gnome_canvas_root(GNOME_CANVAS(canvas))),
131
glsig_handler_exec(canvas->gpsm_handler0, GPSM_SIG_ITEM_CHANGED,
141
static void timeline_canvas_item_destroy(GtkObject *item)
143
GnomeCanvasGroupClass* parent_class;
144
parent_class = gtk_type_class(GNOME_TYPE_CANVAS_GROUP);
145
GTK_OBJECT_CLASS(parent_class)->destroy(item);
146
if (TIMELINE_CANVAS_ITEM(item)->gpsm_handler)
147
glsig_delete_handler(TIMELINE_CANVAS_ITEM(item)->gpsm_handler);
150
static void timeline_canvas_item_class_init(TimelineCanvasItemClass *class)
152
GtkObjectClass *object_class;
153
object_class = GTK_OBJECT_CLASS(class);
154
object_class->destroy = timeline_canvas_item_destroy;
155
class->update = NULL;
156
class->highlight = NULL;
159
static void timeline_canvas_item_init(TimelineCanvasItem *item)
161
item->gpsm_handler = NULL;
165
GtkType timeline_canvas_item_get_type(void)
167
static GtkType timeline_canvas_item_type = 0;
169
if (!timeline_canvas_item_type){
170
GtkTypeInfo timeline_canvas_item_info = {
171
"TimelineCanvasItem",
172
sizeof(TimelineCanvasItem),
173
sizeof(TimelineCanvasItemClass),
174
(GtkClassInitFunc)timeline_canvas_item_class_init,
175
(GtkObjectInitFunc)timeline_canvas_item_init,
176
NULL,NULL,(GtkClassInitFunc)NULL,};
177
timeline_canvas_item_type = gtk_type_unique(
178
GNOME_TYPE_CANVAS_GROUP, &timeline_canvas_item_info);
179
gtk_type_set_chunk_alloc(timeline_canvas_item_type, 8);
182
return timeline_canvas_item_type;
185
void timeline_canvas_item_update(TimelineCanvasItem *item)
187
TIMELINE_CANVAS_ITEM_CLASS(G_OBJECT_GET_CLASS(item))->update(item);
190
void timeline_canvas_item_highlight(TimelineCanvasItem *item, gboolean lite)
192
TIMELINE_CANVAS_ITEM_CLASS(G_OBJECT_GET_CLASS(item))->highlight(item, lite);
195
void timeline_canvas_item_gpsm2w(long hposition, long vposition,
196
long hsize, long vsize,
198
double *x1, double *y1,
199
double *x2, double *y2)
201
*x1 = _HUNIT(hposition/(double)rate);
202
*y1 = _VUNIT(vposition);
203
*x2 = *x1 + _HUNIT(hsize/(double)rate);
204
*y2 = *y1 + _VUNIT(vsize);
207
void timeline_canvas_item_w2gpsm(long *hposition, long *vposition,
208
long *hsize, long *vsize,
210
double x1, double y1,
211
double x2, double y2)
213
*hposition = _HUNIT1(x1*(double)rate);
214
*vposition = _VUNIT1(y1) + 0.5;
215
*hsize = _HUNIT1((x2-x1)*(double)rate);
216
*vsize = _VUNIT1((y2-y1));
223
* TimelineCanvasGroup
226
static void timeline_canvas_group_update(TimelineCanvasItem *item);
227
static void timeline_canvas_group_highlight(TimelineCanvasItem *item,
230
static void timeline_canvas_group_destroy(GtkObject *group)
232
TimelineCanvasItemClass* parent_class;
233
parent_class = gtk_type_class(TIMELINE_CANVAS_ITEM_TYPE);
234
GTK_OBJECT_CLASS(parent_class)->destroy(group);
237
static void timeline_canvas_group_class_init(TimelineCanvasGroupClass *class)
239
GtkObjectClass *object_class;
240
TimelineCanvasItemClass *item_class;
241
object_class = GTK_OBJECT_CLASS(class);
242
object_class->destroy = timeline_canvas_group_destroy;
243
item_class = TIMELINE_CANVAS_ITEM_CLASS(class);
244
item_class->update = timeline_canvas_group_update;
245
item_class->highlight = timeline_canvas_group_highlight;
248
static void timeline_canvas_group_init(TimelineCanvasGroup *grp)
254
GtkType timeline_canvas_group_get_type(void)
256
static GtkType timeline_canvas_group_type = 0;
258
if (!timeline_canvas_group_type){
259
GtkTypeInfo timeline_canvas_group_info = {
260
"TimelineCanvasGroup",
261
sizeof(TimelineCanvasGroup),
262
sizeof(TimelineCanvasGroupClass),
263
(GtkClassInitFunc)timeline_canvas_group_class_init,
264
(GtkObjectInitFunc)timeline_canvas_group_init,
265
NULL,NULL,(GtkClassInitFunc)NULL,};
266
timeline_canvas_group_type = gtk_type_unique(
267
TIMELINE_CANVAS_ITEM_TYPE,
268
&timeline_canvas_group_info);
269
gtk_type_set_chunk_alloc(timeline_canvas_group_type, 8);
272
return timeline_canvas_group_type;
275
static void timeline_canvas_group_update(TimelineCanvasItem *item)
277
TimelineCanvasGroup *group = TIMELINE_CANVAS_GROUP(item);
278
double x1, y1, x2, y2;
281
/* Update the rect hsize. */
282
x2 = _HUNIT(gpsm_item_hsize(item->item)/44100.0/*FIXME*/);
283
y2 = _VUNIT(gpsm_item_vsize(item->item));
284
gnome_canvas_item_set(group->rect,
285
"x2", x2, "y2", y2, NULL);
287
/* Update the label. */
288
gnome_canvas_item_set(group->text,
289
"text", gpsm_item_label(item->item), NULL);
292
x1 = _HUNIT(gpsm_item_hposition(item->item)/44100.0/*FIXME*/);
293
y1 = _VUNIT(gpsm_item_vposition(item->item));
294
gnome_canvas_item_set(GNOME_CANVAS_ITEM(group),
299
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(item));
300
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(group->text)); /* doenst seem to handle position change only -- GNOME bug */
302
/* Somehow we need to trigger updates on all childs. Ugh. */
303
gpsm_grp_foreach_item(item->item, it) {
304
GnomeCanvasItem *child;
305
child = timeline_canvas_find_gpsm_item(GNOME_CANVAS_GROUP(group), it);
310
timeline_canvas_item_update(TIMELINE_CANVAS_ITEM(child));
314
TimelineCanvasGroup *timeline_canvas_group_new(GnomeCanvasGroup *group,
317
TimelineCanvasGroup *item;
318
double x1, x2, y1, y2;
320
x1 = _HUNIT(gpsm_item_hposition(grp)/44100.0/*FIXME*/);
321
y1 = _VUNIT(gpsm_item_vposition(grp));
322
item = TIMELINE_CANVAS_GROUP(
323
gnome_canvas_item_new(group, TIMELINE_CANVAS_GROUP_TYPE,
326
TIMELINE_CANVAS_ITEM(item)->item = (gpsm_item_t *)grp;
331
x2 = _HUNIT(gpsm_item_hsize(grp)/44100.0/*FIXME*/);
332
y2 = _VUNIT(gpsm_item_vsize(grp));
333
item->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(item),
334
gnome_canvas_rect_get_type(),
339
"outline_color", "black",
344
item->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(item),
345
gnome_canvas_text_get_type(),
346
"x", x1+5.0, "y", y1+5.0,
347
"anchor", GTK_ANCHOR_NORTH_WEST,
348
"fill_color", "black",
349
"font", "-adobe-helvetica-medium-r-normal-*-12-120-*-*-p-*-iso8859-1",
350
"text", gpsm_item_label(grp),
356
static void timeline_canvas_group_highlight(TimelineCanvasItem *item, gboolean lite)
358
TimelineCanvasGroup *group = TIMELINE_CANVAS_GROUP(item);
359
gnome_canvas_item_set(group->rect,
360
"outline_color", lite ? "blue" : "black",
362
gnome_canvas_item_raise_to_top(group->rect);
363
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(item));
372
static void timeline_canvas_file_update(TimelineCanvasItem *item);
373
static void timeline_canvas_file_highlight(TimelineCanvasItem *item,
376
static void timeline_canvas_file_destroy(GtkObject *file)
378
TimelineCanvasItemClass* parent_class;
379
parent_class = gtk_type_class(TIMELINE_CANVAS_ITEM_TYPE);
380
GTK_OBJECT_CLASS(parent_class)->destroy(file);
383
static void timeline_canvas_file_class_init(TimelineCanvasFileClass *class)
385
GtkObjectClass *object_class;
386
TimelineCanvasItemClass *item_class;
387
object_class = GTK_OBJECT_CLASS(class);
388
object_class->destroy = timeline_canvas_file_destroy;
389
item_class = TIMELINE_CANVAS_ITEM_CLASS(class);
390
item_class->update = timeline_canvas_file_update;
391
item_class->highlight = timeline_canvas_file_highlight;
394
static void timeline_canvas_file_init(TimelineCanvasFile *file)
400
GtkType timeline_canvas_file_get_type(void)
402
static GtkType timeline_canvas_file_type = 0;
404
if (!timeline_canvas_file_type){
405
GtkTypeInfo timeline_canvas_file_info = {
406
"TimelineCanvasFile",
407
sizeof(TimelineCanvasFile),
408
sizeof(TimelineCanvasFileClass),
409
(GtkClassInitFunc)timeline_canvas_file_class_init,
410
(GtkObjectInitFunc)timeline_canvas_file_init,
411
NULL,NULL,(GtkClassInitFunc)NULL,};
412
timeline_canvas_file_type = gtk_type_unique(
413
TIMELINE_CANVAS_ITEM_TYPE, &timeline_canvas_file_info);
414
gtk_type_set_chunk_alloc(timeline_canvas_file_type, 8);
417
return timeline_canvas_file_type;
420
static void timeline_canvas_file_update(TimelineCanvasItem *item)
422
TimelineCanvasFile *file = TIMELINE_CANVAS_FILE(item);
425
/* Update the rect hsize. */
426
x2 = _HUNIT(gpsm_item_hsize(item->item)/(double)gpsm_swfile_samplerate(item->item));
427
gnome_canvas_item_set(file->rect, "x2", x2, NULL);
429
/* Update the label. */
430
gnome_canvas_item_set(file->text,
431
"text", gpsm_item_label(item->item), NULL);
434
x1 = _HUNIT(gpsm_item_hposition(item->item)/(double)gpsm_swfile_samplerate(item->item));
435
y1 = _VUNIT(gpsm_item_vposition(item->item)) + _VBORDER;
436
gnome_canvas_item_set(GNOME_CANVAS_ITEM(file),
441
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(item));
442
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(file->text)); /* doenst seem to handle position change only -- GNOME bug */
445
TimelineCanvasFile *timeline_canvas_file_new(GnomeCanvasGroup *group,
446
gpsm_swfile_t *swfile)
448
TimelineCanvasFile *item;
449
double x1, x2, y1, y2;
451
x1 = _HUNIT(gpsm_item_hposition(swfile)/(double)gpsm_swfile_samplerate(swfile));
452
y1 = _VUNIT(gpsm_item_vposition(swfile)) + _VBORDER;
453
item = TIMELINE_CANVAS_FILE(
454
gnome_canvas_item_new(group, TIMELINE_CANVAS_FILE_TYPE,
455
"x", x1, "y", y1, NULL));
456
TIMELINE_CANVAS_ITEM(item)->item = (gpsm_item_t *)swfile;
460
x2 = _HUNIT(gpsm_item_hsize(swfile)/(double)gpsm_swfile_samplerate(swfile));
461
y2 = _VUNIT(1) - 2.0*_VBORDER;
462
item->rect = gnome_canvas_item_new(GNOME_CANVAS_GROUP(item),
463
gnome_canvas_rect_get_type(),
468
"outline_color", "black",
470
"fill_color_rgba", 0xffffff00,
473
item->text = gnome_canvas_item_new(GNOME_CANVAS_GROUP(item),
474
gnome_canvas_text_get_type(),
475
"x", x1+5.0, "y", y1+5.0,
476
"anchor", GTK_ANCHOR_NORTH_WEST,
477
"fill_color", "black",
478
"font", "-adobe-helvetica-medium-r-normal-*-12-120-*-*-p-*-iso8859-1",
479
"text", gpsm_item_label(swfile),
485
static void timeline_canvas_file_highlight(TimelineCanvasItem *item, gboolean lite)
487
TimelineCanvasFile *file = TIMELINE_CANVAS_FILE(item);
488
gnome_canvas_item_set(file->rect,
489
"outline_color", lite ? "yellow" : "black",
491
gnome_canvas_item_request_update(GNOME_CANVAS_ITEM(item));
497
* Utils tightly coupled with the canvas items.
500
GnomeCanvasItem *timeline_canvas_find_gpsm_item(GnomeCanvasGroup *grp,
505
litem = grp->item_list;
507
GnomeCanvasItem *citem = GNOME_CANVAS_ITEM(litem->data);
508
if (TIMELINE_IS_CANVAS_ITEM(citem)
509
&& (TIMELINE_CANVAS_ITEM(citem)->item == item))
511
litem = g_list_next(litem);