4
* $Id: canvaspipe.c,v 1.22.2.1 2002/01/16 21:08:02 richi Exp $
6
* Copyright (C) 2001 Johannes Hirche
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
26
#include <sys/param.h>
30
#include "glamecanvas.h"
31
#include "canvasitem.h"
32
#include "util/glame_gui_utils.h"
37
extern long nPopupTimeout;
39
HASH(gcpipe, GlameCanvasPipe, 8,
40
(gcpipe->pipe == key ),
42
((long)gcpipe->pipe/4),
46
/* GlameCanvasFilter* hash_find_GCfilter(filter_t*);
47
void hash_add_GCFilter(GlameCanvasFilter*);
55
/*Yukky gtk class stuff
64
static guint pipe_signals[LAST_SIGNAL] = { 0 };
69
glame_canvas_pipe_destroy (GtkObject *object)
71
GnomeCanvasGroupClass* parent_class;
72
hash_remove_gcpipe(GLAME_CANVAS_PIPE(object));
73
parent_class = gtk_type_class (GNOME_TYPE_CANVAS_GROUP);
74
GTK_OBJECT_CLASS (parent_class)->destroy (object);
79
glame_canvas_pipe_class_init(GlameCanvasPipeClass* class)
82
GtkObjectClass *object_class;
83
object_class = GTK_OBJECT_CLASS(class);
84
object_class->destroy = glame_canvas_pipe_destroy;
86
pipe_signals[DELETED] = gtk_signal_new("deleted",
89
GTK_SIGNAL_OFFSET(GlameCanvasPipeClass,deleted),
90
gtk_marshal_NONE__NONE,
93
gtk_object_class_add_signals(object_class,pipe_signals,LAST_SIGNAL);
94
class->deleted = NULL;
98
glame_canvas_pipe_init(GlameCanvasPipe *p)
101
p->property_texts = NULL;
112
glame_canvas_pipe_get_type(void)
114
static GtkType canvas_pipe_type = 0;
116
if(!canvas_pipe_type){
117
GtkTypeInfo canvas_pipe_info={
119
sizeof(GlameCanvasPipe),
120
sizeof(GlameCanvasPipeClass),
121
(GtkClassInitFunc) glame_canvas_pipe_class_init,
122
(GtkObjectInitFunc) glame_canvas_pipe_init,
123
NULL,NULL,(GtkClassInitFunc)NULL,};
124
canvas_pipe_type = gtk_type_unique(GNOME_TYPE_CANVAS_GROUP,
126
gtk_type_set_chunk_alloc(canvas_pipe_type,8);
129
return canvas_pipe_type;
134
glame_canvas_find_pipe(filter_pipe_t *p)
136
return hash_find_gcpipe(p);
140
glame_canvas_pipe_reroute(GlameCanvasPipe *p)
142
/* draw connection depending on start and end coords */
143
double xs, ys, xd,yd;
144
double xOffset, dist;
146
xs = p->points->coords[0];
147
ys = p->points->coords[1];
148
xd = p->points->coords[10];
149
yd = p->points->coords[11];
155
xOffset=(xOffset<5.0)?5.0:xOffset;
158
p->points->coords[2]=xs+xOffset+(p->sourceId*4);
159
p->points->coords[3]=ys;
161
p->points->coords[4]=xs+xOffset+(p->sourceId*4);
162
p->points->coords[5]=(ys+yd)/2.0 + dy;
164
p->points->coords[6]=xd-25.0-(p->destId*4);
165
p->points->coords[7]=(ys+yd)/2.0+dy;
167
p->points->coords[8]=xd-25.0-(p->destId*4);
168
p->points->coords[9]=yd;
170
gnome_canvas_item_set(GNOME_CANVAS_ITEM(p->line),
174
gnome_canvas_item_set(GNOME_CANVAS_ITEM(p->circle),
175
"x1",((xs+xd)/2.0)-6.0,
176
"x2",((xs+xd)/2.0)+6.0,
177
"y1",((ys+yd)/2.0+dy)-6.0,
178
"y2",((ys+yd)/2.0+dy)+6.0,
184
glame_canvas_pipe_redraw(GlameCanvasPipe *p)
186
double sourcex,sourcey,destx,desty;
187
GlameCanvasPort *port;
192
port = glame_canvas_find_port(filterpipe_connection_source(p->pipe));
193
pipes = filterport_nrpipes(filterpipe_source(p->pipe));
196
DPRINTF("canvasport not found\n");
199
sourcex = GNOME_CANVAS_RE(port)->x1 + 16.0;
200
sourcey = GNOME_CANVAS_RE(port)->y1 + ((GNOME_CANVAS_RE(port)->y2 - GNOME_CANVAS_RE(port)->y1)/(float)(pipes+1))*p->sourceId;
201
gnome_canvas_item_i2w(GNOME_CANVAS_ITEM(port),&sourcex,&sourcey);
203
port = glame_canvas_find_port(filterpipe_connection_dest(p->pipe));
204
pipes = filterport_nrpipes(filterpipe_dest(p->pipe));
206
destx = GNOME_CANVAS_RE(port)->x1;
208
desty = GNOME_CANVAS_RE(port)->y1 + ((GNOME_CANVAS_RE(port)->y2 - GNOME_CANVAS_RE(port)->y1)/(float)(pipes+1))*p->destId;
209
gnome_canvas_item_i2w(GNOME_CANVAS_ITEM(port),&destx,&desty);
211
p->points->coords[0] = sourcex;
212
p->points->coords[1] = sourcey;
213
p->points->coords[10] = destx;
214
p->points->coords[11] = desty;
215
glame_canvas_pipe_reroute(p);
220
glame_canvas_pipe_end_moved_cb(GlameCanvasPort* p,double dx, double dy, GlameCanvasPipe* pipe)
222
pipe->points->coords[10] += dx;
223
pipe->points->coords[11] += dy;
224
glame_canvas_pipe_reroute(pipe);
228
glame_canvas_pipe_begin_moved_cb(GlameCanvasPort* p,double dx, double dy, GlameCanvasPipe* pipe)
230
pipe->points->coords[0] += dx;
231
pipe->points->coords[1] += dy;
232
glame_canvas_pipe_reroute(pipe);
237
glame_canvas_pipe_port_changed_cb(GlameCanvasPort* p, GlameCanvasPipe* pipe)
239
glame_canvas_pipe_redraw(pipe);
243
glame_canvas_pipe_deleted_cb(glsig_handler_t *handler,long sig,va_list va)
245
GlameCanvasPipe* gPipe;
248
/* Ignore not existing pipes (and delete handler) */
249
GLSIGH_GETARGS1(va, pipe);
250
if (!hash_find_gcpipe(pipe)) {
251
glsig_delete_handler(handler);
255
gPipe = GLAME_CANVAS_PIPE(glsig_handler_private(handler));
256
gtk_signal_emit_by_name(GTK_OBJECT(gPipe),"deleted");
257
gtk_object_destroy(GTK_OBJECT(gPipe));
262
glame_canvas_pipe_event_cb(GnomeCanvasItem* i, GdkEvent* event, GlameCanvasPipe* p);
270
static void canvas_pipe_source_properties_cb(GtkObject *foo,
274
p = glame_gui_filter_properties(filterpipe_sourceparamdb(pipe),
275
filterport_label(filterpipe_connection_source(pipe)), NULL);
278
static void canvas_pipe_dest_properties_cb(GtkObject *foo, filter_pipe_t *pipe)
281
p = glame_gui_filter_properties(filterpipe_destparamdb(pipe),
282
filterport_label(filterpipe_connection_dest(pipe)), NULL);
285
static void canvas_pipe_delete_cb(GtkObject* foo, filter_pipe_t* pipe)
287
filterpipe_delete(pipe);
290
static GnomeUIInfo pipe_menu[]=
292
GNOMEUIINFO_ITEM(N_("_Source properties..."), NULL, canvas_pipe_source_properties_cb, NULL),
293
GNOMEUIINFO_ITEM(N_("D_estination properties..."), NULL, canvas_pipe_dest_properties_cb, NULL),
294
GNOMEUIINFO_SEPARATOR,
295
GNOMEUIINFO_ITEM(N_("_Delete"), NULL, canvas_pipe_delete_cb,NULL),
302
glame_canvas_pipe_grabbing_cb(GnomeCanvasItem* i, GdkEvent* event, GlameCanvasPipe* p)
306
case GDK_MOTION_NOTIFY:
307
/* do something here */
308
p->dy -= p->last_y - event->button.y;
309
p->last_y = event->button.y;
310
glame_canvas_pipe_reroute(p);
313
case GDK_BUTTON_RELEASE:
314
gnome_canvas_item_ungrab(i,event->button.time);
315
gtk_signal_disconnect_by_func(GTO(i),GTK_SIGNAL_FUNC(glame_canvas_pipe_grabbing_cb),p);
316
gtk_signal_handler_unblock_by_func(GTO(i),GTK_SIGNAL_FUNC(glame_canvas_pipe_event_cb),p);
318
case GDK_2BUTTON_PRESS:
319
switch(event->button.button){
322
menu = gnome_popup_menu_new(pipe_menu);
323
gnome_popup_menu_do_popup(menu,NULL,NULL,&event->button,p->pipe);
327
gnome_canvas_item_ungrab(i,event->button.time);
328
gtk_signal_disconnect_by_func(GTO(i),GTK_SIGNAL_FUNC(glame_canvas_pipe_grabbing_cb),p);
329
gtk_signal_handler_unblock_by_func(GTO(i),GTK_SIGNAL_FUNC(glame_canvas_pipe_event_cb),p);
340
glame_canvas_pipe_show_properties(GlameCanvasPipe* pipe)
343
filter_param_t* param;
344
GnomeCanvasText * text;
345
GnomeCanvasGroup *group;
346
GnomeCanvasRect* rect;
348
const char* font = glame_gui_get_font(GLAME_CANVAS(GNOME_CANVAS_ITEM(pipe)->canvas));
350
double xOffset,yOffset;
351
double bmaxx,bminx,bminy,bmaxy, recx1,recx2,recy1,recy2;
352
gboolean params = FALSE;
353
if(pipe->timeout_id){
354
gtk_timeout_remove(pipe->timeout_id);
355
pipe->timeout_id = 0;
364
xOffset = (GNOME_CANVAS_RE(pipe->circle)->x1+GNOME_CANVAS_RE(pipe->circle)->x2)/2.0;
365
yOffset = GNOME_CANVAS_RE(pipe->circle)->y2;
370
group = GNOME_CANVAS_GROUP(CANVAS_ITEM_ROOT(pipe));
371
group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(group,
372
gnome_canvas_group_get_type(),
374
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(group));
376
snprintf(buffer,255,_("Samplerate: %d"),filterpipe_sample_rate(pipe->pipe));
377
text = GNOME_CANVAS_TEXT(gnome_canvas_item_new(group,
378
gnome_canvas_text_get_type(),
386
"anchor",GTK_ANCHOR_WEST,
387
"justification",GTK_JUSTIFY_LEFT,
390
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(text));
392
gnome_canvas_item_get_bounds(GCI(text),&recx1,&recy1,&recx2,&recy2);
393
bmaxx = bmaxx<recx2?recx2:bmaxx;
394
bmaxy = bmaxy<recy2?recy2:bmaxy;
395
bminx = bminx>recx1?recx1:bminx;
396
bminy = bminy>recy1?recy1:bminy;
399
snprintf(buffer,255,_("Hangle: %f"),filterpipe_sample_hangle(pipe->pipe));
400
text = GNOME_CANVAS_TEXT(gnome_canvas_item_new(group,
401
gnome_canvas_text_get_type(),
409
"anchor",GTK_ANCHOR_WEST,
410
"justification",GTK_JUSTIFY_LEFT,
413
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(text));
415
gnome_canvas_item_get_bounds(GCI(text),&recx1,&recy1,&recx2,&recy2);
416
bmaxx = bmaxx<recx2?recx2:bmaxx;
417
bmaxy = bmaxy<recy2?recy2:bmaxy;
418
bminx = bminx>recx1?recx1:bminx;
419
bminy = bminy>recy1?recy1:bminy;
423
if(filterparamdb_nrparams(filterpipe_sourceparamdb(pipe->pipe))){
425
snprintf(buffer,255, _("Source params:"));
426
text = GNOME_CANVAS_TEXT(gnome_canvas_item_new(group,
427
gnome_canvas_text_get_type(),
435
"anchor",GTK_ANCHOR_WEST,
436
"justification",GTK_JUSTIFY_LEFT,
439
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(text));
441
gnome_canvas_item_get_bounds(GCI(text),&recx1,&recy1,&recx2,&recy2);
442
bmaxx = bmaxx<recx2?recx2:bmaxx;
443
bmaxy = bmaxy<recy2?recy2:bmaxy;
444
bminx = bminx>recx1?recx1:bminx;
445
bminy = bminy>recy1?recy1:bminy;
449
filterparamdb_foreach_param(filterpipe_sourceparamdb(pipe->pipe),param){
451
str = filterparam_to_string(param);
452
snprintf(buffer, 255, "%s: %s", filterparam_label(param), str);
454
text = GNOME_CANVAS_TEXT(gnome_canvas_item_new(group,
455
gnome_canvas_text_get_type(),
462
"fill_color","black",
463
"anchor",GTK_ANCHOR_WEST,
464
"justification",GTK_JUSTIFY_LEFT,
467
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(text));
469
gnome_canvas_item_get_bounds(GCI(text),&recx1,&recy1,&recx2,&recy2);
470
bmaxx = bmaxx<recx2?recx2:bmaxx;
471
bmaxy = bmaxy<recy2?recy2:bmaxy;
472
bminx = bminx>recx1?recx1:bminx;
473
bminy = bminy>recy1?recy1:bminy;
478
if(filterparamdb_nrparams(filterpipe_destparamdb(pipe->pipe))){
480
snprintf(buffer,255, _("Dest params:"));
481
text = GNOME_CANVAS_TEXT(gnome_canvas_item_new(group,
482
gnome_canvas_text_get_type(),
490
"anchor",GTK_ANCHOR_WEST,
491
"justification",GTK_JUSTIFY_LEFT,
494
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(text));
496
gnome_canvas_item_get_bounds(GCI(text),&recx1,&recy1,&recx2,&recy2);
497
bmaxx = bmaxx<recx2?recx2:bmaxx;
498
bmaxy = bmaxy<recy2?recy2:bmaxy;
499
bminx = bminx>recx1?recx1:bminx;
500
bminy = bminy>recy1?recy1:bminy;
504
filterparamdb_foreach_param(filterpipe_destparamdb(pipe->pipe),param){
506
str = filterparam_to_string(param);
507
snprintf(buffer, 255, "%s: %s", filterparam_label(param), str);
509
text = GNOME_CANVAS_TEXT(gnome_canvas_item_new(group,
510
gnome_canvas_text_get_type(),
517
"fill_color","black",
518
"anchor",GTK_ANCHOR_WEST,
519
"justification",GTK_JUSTIFY_LEFT,
522
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(text));
524
gnome_canvas_item_get_bounds(GCI(text),&recx1,&recy1,&recx2,&recy2);
525
bmaxx = bmaxx<recx2?recx2:bmaxx;
526
bmaxy = bmaxy<recy2?recy2:bmaxy;
527
bminx = bminx>recx1?recx1:bminx;
528
bminy = bminy>recy1?recy1:bminy;
534
rect = GNOME_CANVAS_RECT(gnome_canvas_item_new(group,
535
gnome_canvas_rect_get_type(),
540
"outline_color","black",
542
"fill_color_rgba",0xd0d0ff00,
544
gnome_canvas_item_lower_to_bottom(GNOME_CANVAS_ITEM(rect));
546
pipe->popupGroup = group;
551
glame_canvas_pipe_hide_properties(GlameCanvasPipe *pipe)
553
if(!pipe->popupGroup){
556
gtk_object_destroy(GTO(pipe->popupGroup));
557
pipe->popupGroup = NULL;
563
glame_canvas_pipe_register_popup(GlameCanvasPipe* pipe)
565
if(pipe->timeout_id){
566
gtk_timeout_remove(pipe->timeout_id);
568
pipe->timeout_id = gtk_timeout_add(nPopupTimeout,(GtkFunction)glame_canvas_pipe_show_properties,pipe);
571
glame_canvas_pipe_deregister_popup(GlameCanvasPipe* pipe)
573
if(pipe->timeout_id){
574
gtk_timeout_remove(pipe->timeout_id);
575
pipe->timeout_id = 0;
577
glame_canvas_pipe_hide_properties(pipe);
582
glame_canvas_pipe_event_cb(GnomeCanvasItem* i, GdkEvent* event, GlameCanvasPipe* p)
587
case GDK_BUTTON_PRESS:
588
switch(event->button.button){
590
p->last_y = event->button.y;
591
fleur = gdk_cursor_new(GDK_FLEUR);
592
/* block other handlers (this one ;-) */
593
gtk_signal_handler_block_by_func(GTK_OBJECT(i),GTK_SIGNAL_FUNC(glame_canvas_pipe_event_cb),p);
594
gtk_signal_connect(GTK_OBJECT(i),"event", GTK_SIGNAL_FUNC(glame_canvas_pipe_grabbing_cb), p);
595
gnome_canvas_item_grab(GNOME_CANVAS_ITEM(i),GDK_POINTER_MOTION_MASK|GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK,fleur,
597
gdk_cursor_destroy(fleur);
602
menu = gnome_popup_menu_new(pipe_menu);
603
gnome_popup_menu_do_popup(menu,NULL,NULL,&event->button,p->pipe);
610
case GDK_2BUTTON_PRESS:
611
switch(event->button.button){
614
menu = gnome_popup_menu_new(pipe_menu);
615
gnome_popup_menu_do_popup(menu,NULL,NULL,&event->button,p->pipe);
620
case GDK_ENTER_NOTIFY:
621
glame_canvas_pipe_register_popup(p);
623
case GDK_LEAVE_NOTIFY:
624
glame_canvas_pipe_deregister_popup(p);
633
GlameCanvasPipe* glame_canvas_pipe_new(GnomeCanvasGroup *group, filter_pipe_t * pipe)
635
GlameCanvasPipe* gPipe;
636
GnomeCanvasGroup * gGroup;
637
GlameCanvasPort *gSource, *gDest;
640
if(glame_canvas_find_pipe(pipe)){
641
DPRINTF("Trying to add duplicate pipe!\n");
642
return glame_canvas_find_pipe(pipe);
644
gPipe = GLAME_CANVAS_PIPE(gnome_canvas_item_new(group,
645
glame_canvas_pipe_get_type(),
647
gGroup = GNOME_CANVAS_GROUP(gPipe);
649
/* create and clear line coords */
650
gPipe->points = gnome_canvas_points_new(6);
652
gPipe->points->coords[i] = 0.0;
654
gPipe->line = GNOME_CANVAS_LINE(gnome_canvas_item_new(gGroup,
655
gnome_canvas_line_get_type(),
656
"points",gPipe->points,
657
"fill_color","black",
659
"arrow_shape_a",18.0,
660
"arrow_shape_b",20.0,
664
"last_arrowhead",TRUE,
666
gPipe->circle = GNOME_CANVAS_ELLIPSE(gnome_canvas_item_new(gGroup,
667
gnome_canvas_ellipse_get_type(),
672
"fill_color","black",
677
/* connect to backend destroy sig */
678
glsig_add_handler(filterpipe_emitter(pipe),GLSIG_PIPE_DELETED,glame_canvas_pipe_deleted_cb,gPipe);
680
hash_add_gcpipe(gPipe);
682
gtk_signal_connect_after(GTK_OBJECT(gPipe->circle),
684
GTK_SIGNAL_FUNC(glame_canvas_pipe_event_cb),
687
gSource = glame_canvas_find_port(filterpipe_connection_source(pipe));
688
gDest = glame_canvas_find_port(filterpipe_connection_dest(pipe));
690
/* connect to movement of ports */
691
gtk_signal_connect(GTK_OBJECT(gDest),
693
GTK_SIGNAL_FUNC(glame_canvas_pipe_end_moved_cb),
696
gtk_signal_connect(GTK_OBJECT(gSource),
698
GTK_SIGNAL_FUNC(glame_canvas_pipe_begin_moved_cb),
701
/* connect to reordering of connections at port */
702
gtk_signal_connect(GTK_OBJECT(gDest),
703
"connections_changed",
704
GTK_SIGNAL_FUNC(glame_canvas_pipe_port_changed_cb),
707
gtk_signal_connect(GTK_OBJECT(gSource),
708
"connections_changed",
709
GTK_SIGNAL_FUNC(glame_canvas_pipe_port_changed_cb),
712
gtk_signal_connect(GTK_OBJECT(gPipe),"deleted",
713
GTK_SIGNAL_FUNC(glame_canvas_port_pipe_deleted_cb),
716
gtk_signal_connect(GTK_OBJECT(gPipe),"deleted",
717
GTK_SIGNAL_FUNC(glame_canvas_port_pipe_deleted_cb),
721
/* reorder all pipes */
722
gtk_signal_emit_by_name(GTK_OBJECT(glame_canvas_find_port(filterpipe_connection_dest(pipe))),
723
"connections_changed");
724
gtk_signal_emit_by_name(GTK_OBJECT(glame_canvas_find_port(filterpipe_connection_source(pipe))),
725
"connections_changed");
732
/* destroy all pipes in a canvas */
733
void glame_canvas_pipe_destroy_all(GnomeCanvas* canvas)
735
GlameCanvasPipe * gcp;
738
for(i=0;i<(1<<8);i++){
739
gcp = hash_getslot_gcpipe(i);
742
if(CANVAS_ITEM_CANVAS(gcp) == canvas){
743
/* FIXME doesnt take other windows into account! */
744
gtk_object_destroy(GTO(gcp));
746
gcp = hash_next_gcpipe(gcp);