1 /* gAlan - Graphical Audio Language
2 * Copyright (C) 1999 Tony Garnock-Jones
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * this is gencomp.c from tony. I modifie it to be iscom.c
23 * iscomp only means a reference to a connector therefor
24 * it only stores a ConnectorReference.
36 #include "generator.h"
43 #define ISCOMP_ICONLENGTH 48
44 #define ISCOMP_TITLEHEIGHT 15
45 #define ISCOMP_CONNECTOR_SPACE 5
46 #define ISCOMP_CONNECTOR_WIDTH 10
47 #define ISCOMP_BORDER_WIDTH (ISCOMP_CONNECTOR_WIDTH + ISCOMP_CONNECTOR_SPACE)
50 PRIVATE
int next_component_number
= 1;
51 PRIVATE ComponentClass InterSheetComponentClass
; /* forward reference */
54 PRIVATE
void build_connectors(Component
*c
, int count
, gboolean is_outbound
, gboolean is_signal
) {
57 for (i
= 0; i
< count
; i
++)
58 comp_new_connector(c
, is_signal
? COMP_SIGNAL_CONNECTOR
: COMP_EVENT_CONNECTOR
,
63 PRIVATE
void resize_connectors(Component
*c
, int count
,
64 gboolean is_outbound
, gboolean is_signal
,
65 int hsize
, int vsize
) {
66 int spacing
= (is_signal
? vsize
: hsize
) / (count
+ 1);
67 int startpos
= is_outbound
? (ISCOMP_BORDER_WIDTH
* 2
68 + (is_signal
? hsize
: vsize
)
69 - (ISCOMP_CONNECTOR_WIDTH
>> 1))
70 : (ISCOMP_CONNECTOR_WIDTH
>> 1);
71 int x
= is_signal
? startpos
: ISCOMP_BORDER_WIDTH
+ spacing
;
72 int y
= is_signal
? ISCOMP_BORDER_WIDTH
+ spacing
: startpos
;
73 int dx
= is_signal
? 0 : spacing
;
74 int dy
= is_signal
? spacing
: 0;
77 for (i
= 0; i
< count
; i
++, x
+= dx
, y
+= dy
) {
78 ConnectorReference ref
= { c
, is_signal
? COMP_SIGNAL_CONNECTOR
: COMP_EVENT_CONNECTOR
,
80 Connector
*con
= comp_get_connector(&ref
);
87 PRIVATE
void iscomp_resize(Component
*c
) {
88 int body_vert
, body_horiz
;
89 ISCompData
*d
= c
->data
;
91 int in_sig_count
=0, out_sig_count
=0, in_count
=0, out_count
=0;
94 switch( d
->reftype
) {
110 ISCOMP_CONNECTOR_WIDTH
111 + MAX(MAX(in_sig_count
, out_sig_count
) * ISCOMP_CONNECTOR_WIDTH
,
112 ISCOMP_TITLEHEIGHT
+ (icon
? ISCOMP_ICONLENGTH
: 0));
114 ISCOMP_CONNECTOR_WIDTH
116 MAX(sheet_get_textwidth(c
->sheet
, d
->name
),
117 MAX(in_count
* ISCOMP_CONNECTOR_WIDTH
,
118 out_count
* ISCOMP_CONNECTOR_WIDTH
)));
120 resize_connectors(c
, in_count
, 0, 0, body_horiz
, body_vert
);
121 resize_connectors(c
, in_sig_count
, 0, 1, body_horiz
, body_vert
);
122 resize_connectors(c
, out_count
, 1, 0, body_horiz
, body_vert
);
123 resize_connectors(c
, out_sig_count
, 1, 1, body_horiz
, body_vert
);
125 c
->width
= body_horiz
+ 2*ISCOMP_BORDER_WIDTH
+ 1;
126 c
->height
= body_vert
+ 2*ISCOMP_BORDER_WIDTH
+ 1;
129 PRIVATE
int iscomp_initialize(Component
*c
, gpointer init_data
) {
130 ISCompData
*d
= safe_malloc(sizeof(ISCompData
));
131 ISCompInitData
*id
= (ISCompInitData
*) init_data
;
133 d
->name
= safe_malloc(strlen("con") + 20);
134 sprintf(d
->name
, "con%d", next_component_number
++);
138 d
->reftype
= id
->reftype
;
140 switch( d
->reftype
) {
142 build_connectors(c
, 1, 0, 0);
145 build_connectors(c
, 1, 0, 1);
148 build_connectors(c
, 1, 1, 0);
151 build_connectors(c
, 1, 1, 1);
154 c
->x
-= ISCOMP_BORDER_WIDTH
;
155 c
->y
-= ISCOMP_BORDER_WIDTH
;
156 c
->width
= c
->height
= 0;
165 PRIVATE
void iscomp_destroy(Component
*c
) {
166 ISCompData
*d
= c
->data
;
173 PRIVATE
void iscomp_unpickle(Component
*c
, ObjectStoreItem
*item
, ObjectStore
*db
) {
174 ISCompData
*d
= safe_malloc(sizeof(ISCompData
));
178 d
->name
= safe_string_dup( objectstore_item_get_string(item
, "name", "was geht denn hier ???" ) );
179 d
->reftype
= objectstore_item_get_integer(item
, "reftype", SIGIN
);
180 d
->poly
= objectstore_item_get_integer(item
, "poly", FALSE
);
182 if( objectstore_item_get_integer( item
, "refvalid", 1 ) )
183 d
->ref
= unpickle_connectorreference( d
->ref
, objectstore_item_get_object( item
, "ref" ) );
186 //validate_connectors(c);
187 iscomp_resize(c
); /* because things may be different if loading on a different
188 system from the one we saved with */
191 PRIVATE
void iscomp_pickle(Component
*c
, ObjectStoreItem
*item
, ObjectStore
*db
) {
192 ISCompData
*d
= c
->data
;
193 objectstore_item_set_string(item
, "name", d
->name
);
194 objectstore_item_set_integer(item
, "reftype", d
->reftype
);
195 objectstore_item_set_integer(item
, "poly", d
->poly
);
197 objectstore_item_set_object( item
, "ref", pickle_connectorreference( d
->ref
, db
) );
199 objectstore_item_set_integer( item
, "refvalid", (d
->ref
!= NULL
) );
202 PRIVATE Component
*iscomp_clone( Component
*c
, Sheet
*sheet
) {
204 ISCompData
*srcdata
= c
->data
;
205 ISCompData
*clonedata
;
208 id
.reftype
= srcdata
->reftype
;
209 id
.poly
= srcdata
->poly
;
211 clone
= comp_new_component( c
->klass
, &id
, sheet
, 0, 0 );
212 clonedata
= clone
->data
;
213 g_free( clonedata
->name
);
214 clonedata
->name
= safe_string_dup( srcdata
->name
);
216 iscomp_resize(clone
);
217 //sheet_queue_redraw_component( c->sheet, c );
222 /* %%% Is this due to GTK changing from 1.2.x to 1.3.x, or is it a bug? */
224 #define FULLCIRCLE_DEGREES_NUMBER 72000
226 #define FULLCIRCLE_DEGREES_NUMBER 36000
229 PRIVATE
void iscomp_paint(Component
*c
, GdkRectangle
*area
, GdkDrawable
*drawable
, GtkStyle
*style
, GdkColor
*colors
) {
230 ISCompData
*d
= c
->data
;
231 GList
*l
= c
->connectors
;
232 GdkGC
*gc
= style
->black_gc
;
235 Connector
*con
= l
->data
;
239 // if ((con->ref.kind == COMP_SIGNAL_CONNECTOR)
240 // && ((con->ref.is_output
241 // ? d->g->klass->out_sigs[con->ref.queue_number].flags
242 // : d->g->klass->in_sigs[con->ref.queue_number].flags) & SIG_FLAG_RANDOMACCESS))
243 // colidx = (con->refs == NULL) ? COMP_COLOR_RED : COMP_COLOR_YELLOW;
245 if( !connectorreference_equal( &(con
->ref
), &(c
->sheet
->highlight_ref
) ) )
246 colidx
= COMP_COLOR_VIOLET
;
248 colidx
= (con
->refs
== NULL
) ? COMP_COLOR_BLUE
: COMP_COLOR_GREEN
;
250 // colidx = COMP_COLOR_GREEN;
252 gdk_gc_set_foreground(gc
, &colors
[colidx
]);
253 gdk_draw_arc(drawable
, gc
, TRUE
,
254 con
->x
+ c
->x
- (ISCOMP_CONNECTOR_WIDTH
>>1),
255 con
->y
+ c
->y
- (ISCOMP_CONNECTOR_WIDTH
>>1),
256 ISCOMP_CONNECTOR_WIDTH
,
257 ISCOMP_CONNECTOR_WIDTH
,
258 0, FULLCIRCLE_DEGREES_NUMBER
);
259 gdk_gc_set_foreground(gc
, &colors
[COMP_COLOR_WHITE
]);
260 gdk_draw_arc(drawable
, gc
, FALSE
,
261 con
->x
+ c
->x
- (ISCOMP_CONNECTOR_WIDTH
>>1),
262 con
->y
+ c
->y
- (ISCOMP_CONNECTOR_WIDTH
>>1),
263 ISCOMP_CONNECTOR_WIDTH
,
264 ISCOMP_CONNECTOR_WIDTH
,
265 0, FULLCIRCLE_DEGREES_NUMBER
);
267 x
= ((con
->ref
.kind
== COMP_SIGNAL_CONNECTOR
)
268 ? (con
->ref
.is_output
269 ? con
->x
- (ISCOMP_CONNECTOR_SPACE
+ (ISCOMP_CONNECTOR_WIDTH
>>1))
270 : con
->x
+ (ISCOMP_CONNECTOR_WIDTH
>>1))
273 y
= ((con
->ref
.kind
== COMP_EVENT_CONNECTOR
)
274 ? (con
->ref
.is_output
275 ? con
->y
- (ISCOMP_CONNECTOR_SPACE
+ (ISCOMP_CONNECTOR_WIDTH
>>1))
276 : con
->y
+ (ISCOMP_CONNECTOR_WIDTH
>>1))
279 gdk_draw_line(drawable
, gc
,
281 (con
->ref
.kind
== COMP_SIGNAL_CONNECTOR
? x
+ ISCOMP_CONNECTOR_SPACE
: x
),
282 (con
->ref
.kind
== COMP_SIGNAL_CONNECTOR
? y
: y
+ ISCOMP_CONNECTOR_SPACE
));
287 gdk_gc_set_foreground(gc
, &style
->black
);
288 gdk_draw_rectangle(drawable
, gc
, TRUE
,
289 c
->x
+ ISCOMP_BORDER_WIDTH
,
290 c
->y
+ ISCOMP_BORDER_WIDTH
,
291 c
->width
- 2 * ISCOMP_BORDER_WIDTH
,
292 c
->height
- 2 * ISCOMP_BORDER_WIDTH
);
294 gdk_gc_set_foreground(gc
, &colors
[COMP_COLOR_YELLOW
]);
296 gdk_gc_set_foreground(gc
, &colors
[4]);
298 gdk_draw_rectangle(drawable
, gc
, FALSE
,
299 c
->x
+ ISCOMP_BORDER_WIDTH
,
300 c
->y
+ ISCOMP_BORDER_WIDTH
,
301 c
->width
- 2 * ISCOMP_BORDER_WIDTH
- 1,
302 c
->height
- 2 * ISCOMP_BORDER_WIDTH
- 1);
304 gdk_gc_set_foreground(gc
, &colors
[COMP_COLOR_WHITE
]);
305 gdk_draw_text(drawable
, gtk_style_get_font(style
), gc
,
306 c
->x
+ ISCOMP_BORDER_WIDTH
+ (ISCOMP_CONNECTOR_WIDTH
>>1),
307 c
->y
+ ISCOMP_BORDER_WIDTH
+ ISCOMP_TITLEHEIGHT
- 3,
308 d
->name
, strlen(d
->name
));
309 gdk_gc_set_foreground(gc
, &style
->black
);
312 gdk_draw_pixmap(drawable
, gc
, NULL
, 0, 0,
313 c
->x
+ (c
->width
>>1) - (ISCOMP_ICONLENGTH
>>1),
314 c
->y
+ ((c
->height
-ISCOMP_TITLEHEIGHT
)>>1) - (ISCOMP_ICONLENGTH
>>1)
315 + ISCOMP_TITLEHEIGHT
,
320 PRIVATE
int iscomp_find_connector_at(Component
*c
, gint x
, gint y
, ConnectorReference
*ref
) {
321 GList
*l
= c
->connectors
;
327 Connector
*con
= l
->data
;
329 if (ABS(x
- con
->x
) < (ISCOMP_CONNECTOR_WIDTH
>>1) &&
330 ABS(y
- con
->y
) < (ISCOMP_CONNECTOR_WIDTH
>>1)) {
342 PRIVATE
int iscomp_contains_point(Component
*c
, gint x
, gint y
) {
346 if (dx
>= ISCOMP_BORDER_WIDTH
&&
347 dy
>= ISCOMP_BORDER_WIDTH
&&
348 dx
< (c
->width
- ISCOMP_BORDER_WIDTH
) &&
349 dy
< (c
->height
- ISCOMP_BORDER_WIDTH
))
352 return iscomp_find_connector_at(c
, x
, y
, NULL
);
358 * \brief tries to establich a connection between \a src and \a dst.
360 * Note that galan graphs are directed.
362 * \param c The component with the source connector.
363 * \param src from ConnectorReference.
364 * \param dst to ConnectorReference.
367 PRIVATE gboolean
iscomp_accept_outbound(Component
*c
, ConnectorReference
*src
, ConnectorReference
*dst
) {
368 ISCompData
*data
= c
->data
;
370 if( data
->ref
!= NULL
)
373 data
->ref
= safe_malloc( sizeof( ConnectorReference
) );
378 PRIVATE gboolean
iscomp_accept_inbound(Component
*c
, ConnectorReference
*src
, ConnectorReference
*dst
) {
379 ISCompData
*data
= c
->data
;
381 if( data
->ref
!= NULL
)
384 data
->ref
= safe_malloc( sizeof( ConnectorReference
) );
389 PRIVATE gboolean
iscomp_unlink_outbound(Component
*c
, ConnectorReference
*src
, ConnectorReference
*dst
) {
391 if( c
->sheet
->referring_sheets
!= NULL
) {
392 popup_msgbox("Error", MSGBOX_OK
, 120000, MSGBOX_OK
,
393 "Sheet %s is connected to other sheets.\n"
394 "I cant unconnect this link. Please unconnect first.", c
->sheet
->name
);
398 ISCompData
*data
= c
->data
;
406 PRIVATE gboolean
iscomp_unlink_inbound(Component
*c
, ConnectorReference
*src
, ConnectorReference
*dst
) {
408 if( c
->sheet
->referring_sheets
!= NULL
) {
409 popup_msgbox("Error", MSGBOX_OK
, 120000, MSGBOX_OK
,
410 "Sheet %s is connected to other sheets.\n"
411 "I cant unconnect this link. Please unconnect first.", c
->sheet
->name
);
414 ISCompData
*data
= c
->data
;
422 PRIVATE
char *iscomp_get_title(Component
*c
) {
424 ISCompData
*d
= c
->data
;
425 return safe_string_dup( d
->name
);
428 PRIVATE
char *iscomp_get_connector_name(Component
*c
, ConnectorReference
*ref
) {
430 ISCompData
*d
= c
->data
;
431 return safe_string_dup( d
->name
);
434 //PRIVATE void rename_controls(Control *c, Generator *g) {
435 // control_update_names(c);
438 PRIVATE GtkWidget
*rename_text_widget
= NULL
;
440 PRIVATE
void rename_handler(MsgBoxResponse action_taken
, Component
*c
) {
441 if (action_taken
== MSGBOX_OK
) {
442 ISCompData
*d
= c
->data
;
444 d
->name
= safe_string_dup(gtk_entry_get_text(GTK_ENTRY(rename_text_widget
)));
446 sheet_queue_redraw_component(c
->sheet
, c
); /* to 'erase' the old size */
448 sheet_queue_redraw_component(c
->sheet
, c
); /* to 'fill in' the new size */
452 PRIVATE
void do_rename(Component
*c
, guint action
, GtkWidget
*widget
) {
453 ISCompData
*d
= c
->data
;
454 GtkWidget
*hb
= gtk_hbox_new(FALSE
, 5);
455 GtkWidget
*label
= gtk_label_new("Rename InterSheet:");
456 GtkWidget
*text
= gtk_entry_new();
458 gtk_box_pack_start(GTK_BOX(hb
), label
, TRUE
, FALSE
, 0);
459 gtk_box_pack_start(GTK_BOX(hb
), text
, TRUE
, FALSE
, 0);
461 gtk_widget_show(label
);
462 gtk_widget_show(text
);
464 gtk_entry_set_text(GTK_ENTRY(text
), d
->name
);
466 rename_text_widget
= text
;
467 popup_dialog("Rename", MSGBOX_OK
| MSGBOX_CANCEL
, 0, MSGBOX_OK
, hb
,
468 (MsgBoxResponseHandler
) rename_handler
, c
);
471 //PRIVATE void do_props(Component *c, guint action, GtkWidget *widget) {
472 // ISCompData *d = c->data;
474 // d->propgen(c, d->g);
477 PRIVATE
void do_delete(Component
*c
, guint action
, GtkWidget
*widget
) {
478 sheet_delete_component(c
->sheet
, c
);
481 PRIVATE GtkItemFactoryEntry popup_items
[] = {
482 { "/_Rename...", NULL
, do_rename
, 0, NULL
},
483 // { "/New _Control", NULL, NULL, 0, "<Branch>" },
484 // { "/_Properties...", NULL, do_props, 0, NULL },
485 // { "/sep1", NULL, NULL, 0, "<Separator>" },
486 { "/_Delete", NULL
, do_delete
, 0, NULL
},
489 PRIVATE
void kill_popup(GtkWidget
*popup
, GtkItemFactory
*ifact
) {
490 gtk_object_unref(GTK_OBJECT(ifact
));
493 //PRIVATE void new_control_callback(Component *c, guint control_index, GtkWidget *menuitem) {
494 // ISCompData *d = c->data;
496 // control_new_control(&d->g->klass->controls[control_index], d->g);
499 #define NEW_CONTROL_PREFIX "/New Control/"
501 PRIVATE GtkWidget
*iscomp_build_popup(Component
*c
) {
502 //ISCompData *d = c->data;
503 GtkItemFactory
*ifact
;
504 int nitems
= sizeof(popup_items
) / sizeof(popup_items
[0]);
507 ifact
= gtk_item_factory_new(GTK_TYPE_MENU
, "<iscomp-popup>", NULL
);
508 gtk_item_factory_create_items(ifact
, nitems
, popup_items
, c
);
510 // for (i = 0; i < d->g->klass->numcontrols; i++) {
511 // GtkItemFactoryEntry ent = { NULL, NULL, new_control_callback, i, NULL };
512 // char *name = malloc(strlen(NEW_CONTROL_PREFIX) + strlen(d->g->klass->controls[i].name) + 1);
514 // strcpy(name, NEW_CONTROL_PREFIX);
515 // strcat(name, d->g->klass->controls[i].name);
518 // gtk_item_factory_create_item(ifact, &ent, c, 1);
522 result
= gtk_item_factory_get_widget(ifact
, "<iscomp-popup>");
525 /* %%% Why does gtk_item_factory_get_item() not exist in the gtk-1.3 libraries?
526 Maybe it's something I'm doing wrong. I'll have another go at fixing it later. */
527 // if (d->g->klass->numcontrols == 0)
528 // gtk_widget_set_state(gtk_item_factory_get_item(ifact, "<iscomp-popup>/New Control"),
529 // GTK_STATE_INSENSITIVE);
531 // if (d->propgen == NULL)
532 // gtk_widget_set_state(gtk_item_factory_get_item(ifact, "<iscomp-popup>/Properties..."),
533 // GTK_STATE_INSENSITIVE);
536 gtk_signal_connect(GTK_OBJECT(result
), "destroy", GTK_SIGNAL_FUNC(kill_popup
), ifact
);
541 PRIVATE ComponentClass InterSheetComponentClass
= {
553 iscomp_find_connector_at
,
554 iscomp_contains_point
,
556 iscomp_accept_outbound
,
557 iscomp_accept_inbound
,
558 iscomp_unlink_outbound
,
559 iscomp_unlink_inbound
,
562 iscomp_get_connector_name
,
567 //PUBLIC void iscomp_register_class(GeneratorClass *k, gboolean prefer,
568 // char *menupath, char *iconpath,
569 // PropertiesCallback propgen) {
570 // ISCompInitData *id = safe_malloc(sizeof(ISCompInitData));
573 // id->iconpath = safe_string_dup(iconpath);
574 // id->propgen = propgen;
576 // comp_add_newmenu_item(menupath, &GeneratorComponentClass, id);
578 // /* Only insert into hash table if this name is not already taken, or if we are preferred. */
580 // ISCompInitData *oldid = g_hash_table_lookup(generatorclasses, k->name);
582 // if (oldid == NULL)
583 // g_hash_table_insert(generatorclasses, k->name, id);
584 // else if (prefer) {
585 // g_hash_table_remove(generatorclasses, k->name);
586 // g_hash_table_insert(generatorclasses, k->name, id);
590 ISCompInitData id_sigin
= { SIGIN
, FALSE
};
591 ISCompInitData id_sigout
= { SIGOUT
, FALSE
};
592 ISCompInitData id_evtin
= { EVTIN
, FALSE
};
593 ISCompInitData id_evtout
= { EVTOUT
, FALSE
};
594 ISCompInitData id_poly_sigin
= { SIGIN
, TRUE
};
595 ISCompInitData id_poly_sigout
= { SIGOUT
, TRUE
};
596 ISCompInitData id_poly_evtin
= { EVTIN
, TRUE
};
597 ISCompInitData id_poly_evtout
= { EVTOUT
, TRUE
};
599 PUBLIC
void init_iscomp(void) {
600 // generatorclasses = g_hash_table_new(g_str_hash, g_str_equal);
601 comp_register_componentclass(&InterSheetComponentClass
);
602 comp_add_newmenu_item( "InterSheet/SigOUT", &InterSheetComponentClass
, &id_sigin
);
603 comp_add_newmenu_item( "InterSheet/SigIN", &InterSheetComponentClass
, &id_sigout
);
604 comp_add_newmenu_item( "InterSheet/EvtOUT", &InterSheetComponentClass
, &id_evtin
);
605 comp_add_newmenu_item( "InterSheet/EvtIN", &InterSheetComponentClass
, &id_evtout
);
606 comp_add_newmenu_item( "InterSheet/SigOUT Poly", &InterSheetComponentClass
, &id_poly_sigin
);
607 comp_add_newmenu_item( "InterSheet/SigIN Poly", &InterSheetComponentClass
, &id_poly_sigout
);
608 comp_add_newmenu_item( "InterSheet/EvtOUT Poly", &InterSheetComponentClass
, &id_poly_evtin
);
609 comp_add_newmenu_item( "InterSheet/EvtIN Poly", &InterSheetComponentClass
, &id_poly_evtout
);
612 PUBLIC
void done_iscomp(void) {
613 //g_hash_table_destroy(generatorclasses);
614 //generatorclasses = NULL;