1 /* Copyright (c) 1997-2001 Miller Puckette and others.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 /* this file defines the "glist" class, also known as "canvas" (the two used
6 to be different but are now unified except for some fossilized names.) */
8 /* changes by Thomas Musil IEM KUG Graz Austria 2001 */
10 /* bug-fix: canvas_menuclose(): by Krzysztof Czaja */
11 /* bug-fix: table_new(): I reversed the y-bounds */
14 * changed the canvas_restore, so that it might accept $args as well
16 * so you can make multiple & distinguishable templates
17 * 1511:forum::für::umläute:2001
18 * changes marked with IOhannes
23 #include "../../pdbox.h"
28 #include "g_all_guis.h"
37 #include "g_all_guis.h"
40 struct _canvasenvironment
42 t_symbol
*ce_dir
; /* directory patch lives in */
43 int ce_argc
; /* number of "$" arguments */
44 t_atom
*ce_argv
; /* array of "$" arguments */
45 int ce_dollarzero
; /* value of "$0" */
48 #define GLIST_DEFCANVASWIDTH 240
49 #define GLIST_DEFCANVASHEIGHT 300
52 #define GLIST_DEFCANVASYLOC 22
54 #define GLIST_DEFCANVASYLOC 0
57 /* ---------------------- variables --------------------------- */
60 t_class
*canvas_class
;
61 static int canvas_dspstate
; /* whether DSP is on or off */
62 t_canvas
*canvas_editing
; /* last canvas to start text edting */
63 t_canvas
*canvas_whichfind
; /* last canvas we did a find in */
64 t_canvas
*canvas_list
; /* list of all root canvases */
66 /* ------------------ forward function declarations --------------- */
67 static void canvas_start_dsp(void);
68 static void canvas_stop_dsp(void);
69 static void canvas_drawlines(t_canvas
*x
);
70 static void canvas_setbounds(t_canvas
*x
, int x1
, int y1
, int x2
, int y2
);
71 static void canvas_reflecttitle(t_canvas
*x
);
72 static void canvas_addtolist(t_canvas
*x
);
73 static void canvas_takeofflist(t_canvas
*x
);
74 static void canvas_pop(t_canvas
*x
, t_floatarg fvis
);
75 void canvas_create_editor(t_glist
*x
, int createit
);
77 /* --------- functions to handle the canvas environment ----------- */
79 static t_symbol
*canvas_newfilename
= &s_
;
80 static t_symbol
*canvas_newdirectory
= &s_
;
81 static int canvas_newargc
;
82 static t_atom
*canvas_newargv
;
84 static void glist_doupdatewindowlist(t_glist
*gl
, char *sbuf
)
89 /* this is a canvas; if we have a window, put on "windows" list */
90 t_canvas
*canvas
= (t_canvas
*)gl
;
91 if (canvas
->gl_havewindow
)
93 if (strlen(sbuf
) + strlen(gl
->gl_name
->s_name
) + 100 <= 1024)
97 snprintf(tbuf
, sizeof(tbuf
),
98 "{%s .x%lx} ", gl
->gl_name
->s_name
,
99 (unsigned long) (t_int
) canvas
);
101 sprintf(tbuf
, "{%s .x%x} ", gl
->gl_name
->s_name
, (t_int
)canvas
);
107 for (g
= gl
->gl_list
; g
; g
= g
->g_next
)
109 if (pd_class(&g
->g_pd
) == canvas_class
)
110 glist_doupdatewindowlist((t_glist
*)g
, sbuf
);
115 /* maintain the list of visible toplevels for the GUI's "windows" menu */
116 void canvas_updatewindowlist( void)
120 strcpy(sbuf
, "set menu_windowlist {");
121 /* find all root canvases */
122 for (x
= canvas_list
; x
; x
= x
->gl_next
)
123 glist_doupdatewindowlist(x
, sbuf
);
124 /* next line updates the window menu state before -postcommand tries it */
125 strcat(sbuf
, "}\npdtk_fixwindowmenu\n");
131 /* add a glist the list of "root" canvases (toplevels without parents.) */
132 static void canvas_addtolist(t_canvas
*x
)
134 x
->gl_next
= canvas_list
;
138 static void canvas_takeofflist(t_canvas
*x
)
140 /* take it off the window list */
141 if (x
== canvas_list
) canvas_list
= x
->gl_next
;
145 for (z
= canvas_list
; z
->gl_next
!= x
; z
= z
->gl_next
)
147 z
->gl_next
= x
->gl_next
;
152 void canvas_setargs(int argc
, t_atom
*argv
)
154 /* if there's an old one lying around free it here. This
155 happens if an abstraction is loaded but never gets as far
156 as calling canvas_new(). */
158 freebytes(canvas_newargv
, canvas_newargc
* sizeof(t_atom
));
159 canvas_newargc
= argc
;
160 canvas_newargv
= copybytes(argv
, argc
* sizeof(t_atom
));
163 void glob_setfilename(void *dummy
, t_symbol
*filesym
, t_symbol
*dirsym
)
168 canvas_newfilename
= filesym
;
169 canvas_newdirectory
= dirsym
;
172 t_canvas
*canvas_getcurrent(void)
174 return ((t_canvas
*)pd_findbyclass(&s__X
, canvas_class
));
177 void canvas_setcurrent(t_canvas
*x
)
179 pd_pushsym(&x
->gl_pd
);
182 void canvas_unsetcurrent(t_canvas
*x
)
184 pd_popsym(&x
->gl_pd
);
187 t_canvasenvironment
*canvas_getenv(t_canvas
*x
)
189 if (!x
) bug("canvas_getenv");
191 if (!(x
= x
->gl_owner
))
192 bug("t_canvasenvironment", x
);
196 int canvas_getdollarzero( void)
198 t_canvas
*x
= canvas_getcurrent();
199 t_canvasenvironment
*env
= (x
? canvas_getenv(x
) : 0);
201 return (env
->ce_dollarzero
);
205 void canvas_getargs(int *argcp
, t_atom
**argvp
)
207 t_canvasenvironment
*e
= canvas_getenv(canvas_getcurrent());
212 t_symbol
*canvas_realizedollar(t_canvas
*x
, t_symbol
*s
)
215 char *name
= s
->s_name
;
216 if (*name
== '$' && name
[1] >= '0' && name
[1] <= '9')
218 t_canvasenvironment
*env
= canvas_getenv(x
);
219 canvas_setcurrent(x
);
220 ret
= binbuf_realizedollsym(gensym(name
+1),
221 env
->ce_argc
, env
->ce_argv
, 1);
222 canvas_unsetcurrent(x
);
228 t_symbol
*canvas_getcurrentdir(void)
230 t_canvasenvironment
*e
= canvas_getenv(canvas_getcurrent());
234 t_symbol
*canvas_getdir(t_canvas
*x
)
236 t_canvasenvironment
*e
= canvas_getenv(x
);
240 void canvas_makefilename(t_canvas
*x
, char *file
, char *result
, int resultsize
)
242 char *dir
= canvas_getenv(x
)->ce_dir
->s_name
;
243 if (file
[0] == '/' || (file
[0] && file
[1] == ':') || !*dir
)
245 strncpy(result
, file
, resultsize
);
246 result
[resultsize
-1] = 0;
251 strncpy(result
, dir
, resultsize
);
252 result
[resultsize
-1] = 0;
253 nleft
= resultsize
- strlen(result
) - 1;
254 if (nleft
<= 0) return;
256 strncat(result
, file
, nleft
);
257 result
[resultsize
-1] = 0;
261 void canvas_rename(t_canvas
*x
, t_symbol
*s
, t_symbol
*dir
)
263 if (strcmp(x
->gl_name
->s_name
, "Pd"))
264 pd_unbind(&x
->gl_pd
, canvas_makebindsym(x
->gl_name
));
266 if (strcmp(x
->gl_name
->s_name
, "Pd"))
267 pd_bind(&x
->gl_pd
, canvas_makebindsym(x
->gl_name
));
268 if (glist_isvisible(x
))
269 canvas_reflecttitle(x
);
270 if (dir
&& dir
!= &s_
)
272 t_canvasenvironment
*e
= canvas_getenv(x
);
277 /* --------------- traversing the set of lines in a canvas ----------- */
279 int canvas_getindex(t_canvas
*x
, t_gobj
*y
)
283 for (indexno
= 0, y2
= x
->gl_list
; y2
&& y2
!= y
; y2
= y2
->g_next
)
288 void linetraverser_start(t_linetraverser
*t
, t_canvas
*x
)
293 t
->tr_nextoutno
= t
->tr_nout
= 0;
296 t_outconnect
*linetraverser_next(t_linetraverser
*t
)
298 t_outconnect
*rval
= t
->tr_nextoc
;
302 outno
= t
->tr_nextoutno
;
303 while (outno
== t
->tr_nout
)
307 if (!t
->tr_ob
) y
= t
->tr_x
->gl_list
;
308 else y
= t
->tr_ob
->ob_g
.g_next
;
309 for (; y
; y
= y
->g_next
)
310 if((ob
= pd_checkobject(&y
->g_pd
))) break;
313 t
->tr_nout
= obj_noutlets(ob
);
315 if (glist_isvisible(t
->tr_x
))
316 gobj_getrect(y
, t
->tr_x
,
317 &t
->tr_x11
, &t
->tr_y11
, &t
->tr_x12
, &t
->tr_y12
);
318 else t
->tr_x11
= t
->tr_y11
= t
->tr_x12
= t
->tr_y12
= 0;
320 t
->tr_nextoutno
= outno
+ 1;
321 rval
= obj_starttraverseoutlet(t
->tr_ob
, &t
->tr_outlet
, outno
);
324 t
->tr_nextoc
= obj_nexttraverseoutlet(rval
, &t
->tr_ob2
,
325 &t
->tr_inlet
, &t
->tr_inno
);
326 t
->tr_nin
= obj_ninlets(t
->tr_ob2
);
327 if (!t
->tr_nin
) bug("drawline");
328 if (glist_isvisible(t
->tr_x
))
330 int inplus
= (t
->tr_nin
== 1 ? 1 : t
->tr_nin
- 1);
331 int outplus
= (t
->tr_nout
== 1 ? 1 : t
->tr_nout
- 1);
332 gobj_getrect(&t
->tr_ob2
->ob_g
, t
->tr_x
,
333 &t
->tr_x21
, &t
->tr_y21
, &t
->tr_x22
, &t
->tr_y22
);
334 t
->tr_lx1
= t
->tr_x11
+
335 ((t
->tr_x12
- t
->tr_x11
- IOWIDTH
) * t
->tr_outno
) /
337 t
->tr_ly1
= t
->tr_y12
;
338 t
->tr_lx2
= t
->tr_x21
+
339 ((t
->tr_x22
- t
->tr_x21
- IOWIDTH
) * t
->tr_inno
)/inplus
+
341 t
->tr_ly2
= t
->tr_y21
;
345 t
->tr_x21
= t
->tr_y21
= t
->tr_x22
= t
->tr_y22
= 0;
346 t
->tr_lx1
= t
->tr_ly1
= t
->tr_lx2
= t
->tr_ly2
= 0;
352 void linetraverser_skipobject(t_linetraverser
*t
)
355 t
->tr_nextoutno
= t
->tr_nout
;
358 /* -------------------- the canvas object -------------------------- */
359 int glist_valid
= 10000;
361 void glist_init(t_glist
*x
)
363 /* zero out everyone except "pd" field */
364 memset(((char *)x
) + sizeof(x
->gl_pd
), 0, sizeof(*x
) - sizeof(x
->gl_pd
));
365 x
->gl_stub
= gstub_new(x
, 0);
366 x
->gl_valid
= ++glist_valid
;
367 x
->gl_xlabel
= (t_symbol
**)t_getbytes(0);
368 x
->gl_ylabel
= (t_symbol
**)t_getbytes(0);
371 /* make a new glist. It will either be a "root" canvas or else
372 its parent will be a "text" object in another window... we don't
374 t_canvas
*canvas_new(void *dummy
, t_symbol
*sel
, int argc
, t_atom
*argv
)
376 t_canvas
*x
= (t_canvas
*)pd_new(canvas_class
);
377 t_canvas
*owner
= canvas_getcurrent();
379 int vis
= 0, width
= GLIST_DEFCANVASWIDTH
, height
= GLIST_DEFCANVASHEIGHT
;
380 int xloc
= 0, yloc
= GLIST_DEFCANVASYLOC
;
386 int font
= (owner
? owner
->gl_font
: sys_defaultfont
);
389 x
->gl_obj
.te_type
= T_OBJECT
;
392 /* post("canvas %x, owner %x", x, owner); */
394 if (argc
== 5) /* toplevel: x, y, w, h, font */
396 xloc
= atom_getintarg(0, argc
, argv
);
397 yloc
= atom_getintarg(1, argc
, argv
);
398 width
= atom_getintarg(2, argc
, argv
);
399 height
= atom_getintarg(3, argc
, argv
);
400 font
= atom_getintarg(4, argc
, argv
);
402 else if (argc
== 6) /* subwindow: x, y, w, h, name, vis */
404 xloc
= atom_getintarg(0, argc
, argv
);
405 yloc
= atom_getintarg(1, argc
, argv
);
406 width
= atom_getintarg(2, argc
, argv
);
407 height
= atom_getintarg(3, argc
, argv
);
408 s
= atom_getsymbolarg(4, argc
, argv
);
409 vis
= atom_getintarg(5, argc
, argv
);
411 /* (otherwise assume we're being created from the menu.) */
413 if (canvas_newdirectory
->s_name
[0])
415 static int dollarzero
= 1000;
416 t_canvasenvironment
*env
= x
->gl_env
=
417 (t_canvasenvironment
*)getbytes(sizeof(*x
->gl_env
));
418 env
->ce_dir
= canvas_newdirectory
;
419 env
->ce_argc
= canvas_newargc
;
420 env
->ce_argv
= canvas_newargv
;
421 env
->ce_dollarzero
= dollarzero
++;
422 canvas_newdirectory
= &s_
;
428 if (yloc
< GLIST_DEFCANVASYLOC
)
429 yloc
= GLIST_DEFCANVASYLOC
;
436 canvas_setbounds(x
, xloc
, yloc
, xloc
+ width
, yloc
+ height
);
438 x
->gl_name
= (*s
->s_name
? s
:
439 (canvas_newfilename
? canvas_newfilename
: gensym("Pd")));
440 if (strcmp(x
->gl_name
->s_name
, "Pd"))
441 pd_bind(&x
->gl_pd
, canvas_makebindsym(x
->gl_name
));
444 x
->gl_edit
= !strncmp(x
->gl_name
->s_name
, "Untitled", 8);
448 x
->gl_font
= sys_nearestfontsize(font
);
450 pd_pushsym(&x
->gl_pd
);
454 void canvas_setgraph(t_glist
*x
, int flag
);
456 static void canvas_coords(t_glist
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
461 x
->gl_x1
= atom_getfloatarg(0, argc
, argv
);
462 x
->gl_y1
= atom_getfloatarg(1, argc
, argv
);
463 x
->gl_x2
= atom_getfloatarg(2, argc
, argv
);
464 x
->gl_y2
= atom_getfloatarg(3, argc
, argv
);
465 x
->gl_pixwidth
= atom_getintarg(4, argc
, argv
);
466 x
->gl_pixheight
= atom_getintarg(5, argc
, argv
);
467 canvas_setgraph(x
, atom_getintarg(6, argc
, argv
));
470 /* make a new glist and add it to this glist. It will appear as
471 a "graph", not a text object. */
472 t_glist
*glist_addglist(t_glist
*g
, t_symbol
*sym
,
473 float x1
, float y1
, float x2
, float y2
,
474 float px1
, float py1
, float px2
, float py2
)
476 static int gcount
= 0;
480 t_glist
*x
= (t_glist
*)pd_new(canvas_class
);
482 x
->gl_obj
.te_type
= T_OBJECT
;
487 snprintf(buf
, sizeof(buf
), "graph%d", ++gcount
);
489 sprintf(buf
, "graph%d", ++gcount
);
494 else if (!strncmp((str
= sym
->s_name
), "graph", 5)
495 && (zz
= atoi(str
+ 5)) > gcount
)
497 /* in 0.34 and earlier, the pixel rectangle and the y bounds were
498 reversed; this would behave the same, except that the dialog window
499 would be confusing. The "correct" way is to have "py1" be the value
500 that is higher on the screen. */
511 if (x1
== x2
|| y1
== y2
)
512 x1
= 0, x2
= 100, y1
= 1, y2
= -1;
513 if (px1
>= px2
|| py1
>= py2
)
514 px1
= 100, py1
= 20, px2
= 100 + GLIST_DEFGRAPHWIDTH
,
515 py2
= 20 + GLIST_DEFGRAPHHEIGHT
;
521 x
->gl_obj
.te_xpix
= px1
;
522 x
->gl_obj
.te_ypix
= py1
;
523 x
->gl_pixwidth
= px2
- px1
;
524 x
->gl_pixheight
= py2
- py1
;
528 x
->gl_font
= (canvas_getcurrent() ?
529 canvas_getcurrent()->gl_font
: sys_defaultfont
);
531 x
->gl_screenx1
= x
->gl_screeny1
= 0;
532 x
->gl_screenx2
= 240;
533 x
->gl_screeny2
= 300;
534 if (strcmp(x
->gl_name
->s_name
, "Pd"))
535 pd_bind(&x
->gl_pd
, canvas_makebindsym(x
->gl_name
));
539 x
->gl_obj
.te_binbuf
= binbuf_new();
540 binbuf_addv(x
->gl_obj
.te_binbuf
, "s", gensym("graph"));
542 pd_pushsym(&x
->gl_pd
);
543 glist_add(g
, &x
->gl_gobj
);
544 if (glist_isvisible(g
))
545 canvas_create_editor(x
, 1);
549 /* call glist_addglist from a Pd message */
550 void glist_glist(t_glist
*g
, t_symbol
*s
, int argc
, t_atom
*argv
)
555 t_symbol
*sym
= atom_getsymbolarg(0, argc
, argv
);
556 float x1
= atom_getfloatarg(1, argc
, argv
);
557 float y1
= atom_getfloatarg(2, argc
, argv
);
558 float x2
= atom_getfloatarg(3, argc
, argv
);
559 float y2
= atom_getfloatarg(4, argc
, argv
);
560 float px1
= atom_getfloatarg(5, argc
, argv
);
561 float py1
= atom_getfloatarg(6, argc
, argv
);
562 float px2
= atom_getfloatarg(7, argc
, argv
);
563 float py2
= atom_getfloatarg(8, argc
, argv
);
564 glist_addglist(g
, sym
, x1
, y1
, x2
, y2
, px1
, py1
, px2
, py2
);
567 /* return true if the glist should appear as a graph on parent;
568 otherwise it appears as a text box. */
569 int glist_isgraph(t_glist
*x
)
571 return (x
->gl_isgraph
);
574 /* This is sent from the GUI to inform a toplevel that its window has been
576 static void canvas_setbounds(t_canvas
*x
, int x1
, int y1
, int x2
, int y2
)
578 int heightwas
= y2
- y1
;
579 int heightchange
= y2
- y1
- (x
->gl_screeny2
- x
->gl_screeny1
);
584 /* post("set bounds %d %d %d %d", x1, y1, x2, y2); */
585 if (!glist_isgraph(x
) && (x
->gl_y2
< x
->gl_y1
))
587 /* if it's flipped so that y grows upward,
588 fix so that zero is bottom edge and redraw. This is
589 only appropriate if we're a regular "text" object on the
591 float diff
= x
->gl_y1
- x
->gl_y2
;
593 x
->gl_y1
= heightwas
* diff
;
594 x
->gl_y2
= x
->gl_y1
- diff
;
595 /* and move text objects accordingly; they should stick
596 to the bottom, not the top. */
597 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
598 if (pd_checkobject(&y
->g_pd
))
599 gobj_displace(y
, x
, 0, heightchange
);
604 t_symbol
*canvas_makebindsym(t_symbol
*s
)
606 char buf
[MAXPDSTRING
];
608 strcat(buf
, s
->s_name
);
609 return (gensym(buf
));
612 void canvas_reflecttitle(t_canvas
*x
)
614 char namebuf
[MAXPDSTRING
];
615 t_canvasenvironment
*env
= canvas_getenv(x
);
619 strcpy(namebuf
, " (");
620 for (i
= 0; i
< env
->ce_argc
; i
++)
622 if (strlen(namebuf
) > MAXPDSTRING
/2 - 5)
625 strcat(namebuf
, " ");
626 atom_string(&env
->ce_argv
[i
], namebuf
+ strlen(namebuf
),
629 strcat(namebuf
, ")");
633 sys_vgui("wm title .x%x {%s%c%s - %s}\n",
634 x
, x
->gl_name
->s_name
, (x
->gl_dirty
? '*' : ' '), namebuf
,
635 canvas_getdir(x
)->s_name
);
639 void canvas_dirty(t_canvas
*x
, t_int n
)
641 t_canvas
*x2
= canvas_getrootfor(x
);
642 if ((unsigned)n
!= x2
->gl_dirty
)
645 canvas_reflecttitle(x2
);
649 /* the window becomes "mapped" (visible and not miniaturized) or
650 "unmapped" (either miniaturized or just plain gone.) This should be
651 called from the GUI after the fact to "notify" us that we're mapped. */
652 void canvas_map(t_canvas
*x
, t_floatarg f
)
658 if (!glist_isvisible(x
))
661 if (!x
->gl_havewindow
)
666 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
668 for (sel
= x
->gl_editor
->e_selection
; sel
; sel
= sel
->sel_next
)
669 gobj_select(sel
->sel_what
, x
, 1);
672 /* simulate a mouse up so u_main will calculate scrollbars...
675 sys_vgui("pdtk_canvas_mouseup .x%x.c 0 0 0\n", x
);
681 if (glist_isvisible(x
))
683 /* just clear out the whole canvas... */
685 sys_vgui(".x%x.c delete all\n", x
);
687 /* alternatively, we could have erased them one by one...
688 for (y = x->gl_list; y; y = y->g_next)
690 ... but we should go through and erase the lines as well
691 if we do it that way. */
697 void canvas_redraw(t_canvas
*x
)
699 if (glist_isvisible(x
))
706 /* ---- editors -- perhaps this and "vis" should go to g_editor.c ------- */
708 static t_editor
*editor_new(t_glist
*owner
)
711 t_editor
*x
= (t_editor
*)getbytes(sizeof(*x
));
712 x
->e_connectbuf
= binbuf_new();
713 x
->e_deleted
= binbuf_new();
716 snprintf(buf
, sizeof(buf
), ".x%lx", (unsigned long) (t_int
) owner
);
718 sprintf(buf
, ".x%x", (t_int
)owner
);
720 x
->e_guiconnect
= guiconnect_new(&owner
->gl_pd
, gensym(buf
));
724 static void editor_free(t_editor
*x
, t_glist
*y
)
727 guiconnect_notarget(x
->e_guiconnect
, 1000);
728 binbuf_free(x
->e_connectbuf
);
729 binbuf_free(x
->e_deleted
);
730 freebytes((void *)x
, sizeof(*x
));
733 /* recursively create or destroy all editors of a glist and its
734 sub-glists, as long as they aren't toplevels. */
735 void canvas_create_editor(t_glist
*x
, int createit
)
742 bug("canvas_create_editor");
745 x
->gl_editor
= editor_new(x
);
746 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
747 if((ob
= pd_checkobject(&y
->g_pd
)))
754 bug("canvas_create_editor");
757 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
758 if((ob
= pd_checkobject(&y
->g_pd
)))
759 rtext_free(glist_findrtext(x
, ob
));
760 editor_free(x
->gl_editor
, x
);
764 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
765 if (pd_class(&y
->g_pd
) == canvas_class
&&
766 ((t_canvas
*)y
)->gl_isgraph
)
767 canvas_create_editor((t_canvas
*)y
, createit
);
770 /* we call this when we want the window to become visible, mapped, and
771 in front of all windows; or with "f" zero, when we want to get rid of
773 void canvas_vis(t_canvas
*x
, t_floatarg f
)
781 /* test if we're already visible and toplevel */
782 if (glist_isvisible(x
) && !x
->gl_isgraph
)
783 { /* just put us in front */
789 sys_vgui("raise .x%x\n", x
);
790 sys_vgui("focus .x%x.c\n", x
);
791 sys_vgui("wm deiconify .x%x\n", x
);
797 canvas_create_editor(x
, 1);
799 sys_vgui("pdtk_canvas_new .x%x %d %d +%d+%d %d\n", x
,
800 (int)(x
->gl_screenx2
- x
->gl_screenx1
),
801 (int)(x
->gl_screeny2
- x
->gl_screeny1
),
802 (int)(x
->gl_screenx1
), (int)(x
->gl_screeny1
),
805 canvas_reflecttitle(x
);
806 x
->gl_havewindow
= 1;
807 canvas_updatewindowlist();
810 else /* make invisible */
814 if (!x
->gl_havewindow
)
816 /* bug workaround -- a graph in a visible patch gets "invised"
817 when the patch is closed, and must lose the editor here. It's
818 probably not the natural place to do this. Other cases like
819 subpatches fall here too but don'd need the editor freed, so
820 we check if it exists. */
822 canvas_create_editor(x
, 0);
826 if (glist_isvisible(x
))
828 canvas_create_editor(x
, 0);
830 sys_vgui("destroy .x%x\n", x
);
832 for (i
= 1, x2
= x
; x2
; x2
= x2
->gl_next
, i
++)
835 sys_vgui(".mbar.find delete %d\n", i
);
837 /* if we're a graph on our parent, and if the parent exists
838 and is visible, show ourselves on parent. */
839 if (glist_isgraph(x
) && x
->gl_owner
)
841 t_glist
*gl2
= x
->gl_owner
;
842 canvas_create_editor(x
, 1);
843 if (glist_isvisible(gl2
))
844 gobj_vis(&x
->gl_gobj
, gl2
, 0);
845 x
->gl_havewindow
= 0;
846 if (glist_isvisible(gl2
))
847 gobj_vis(&x
->gl_gobj
, gl2
, 1);
849 else x
->gl_havewindow
= 0;
850 canvas_updatewindowlist();
854 /* we call this on a non-toplevel glist to "open" it into its
856 void glist_menu_open(t_glist
*x
)
858 if (glist_isvisible(x
) && !glist_istoplevel(x
))
860 t_glist
*gl2
= x
->gl_owner
;
862 bug("canvas_vis"); /* shouldn't happen but don't get too upset. */
865 /* erase ourself in parent window */
866 gobj_vis(&x
->gl_gobj
, gl2
, 0);
867 /* get rid of our editor (and subeditors) */
868 canvas_create_editor(x
, 0);
869 x
->gl_havewindow
= 1;
870 /* redraw ourself in parent window (blanked out this time) */
871 gobj_vis(&x
->gl_gobj
, gl2
, 1);
877 int glist_isvisible(t_glist
*x
)
879 return ((!x
->gl_loading
) && glist_getcanvas(x
)->gl_mapped
);
882 int glist_istoplevel(t_glist
*x
)
884 /* we consider a graph "toplevel" if it has its own window
885 or if it appears as a box in its parent window so that we
886 don't draw the actual contents there. */
887 return (x
->gl_havewindow
|| !x
->gl_isgraph
);
890 int glist_getfont(t_glist
*x
)
892 return (glist_getcanvas(x
)->gl_font
);
895 void canvas_free(t_canvas
*x
)
898 int dspstate
= canvas_suspend_dsp();
900 if (canvas_editing
== x
)
902 if (canvas_whichfind
== x
)
903 canvas_whichfind
= 0;
905 while((y
= x
->gl_list
))
909 if (strcmp(x
->gl_name
->s_name
, "Pd"))
910 pd_unbind(&x
->gl_pd
, canvas_makebindsym(x
->gl_name
));
913 freebytes(x
->gl_env
->ce_argv
, x
->gl_env
->ce_argc
* sizeof(t_atom
));
914 freebytes(x
->gl_env
, sizeof(*x
->gl_env
));
916 canvas_resume_dsp(dspstate
);
919 gfxstub_deleteforkey(x
); /* probably unnecessary */
922 canvas_takeofflist(x
);
925 /* ----------------- lines ---------- */
927 static void canvas_drawlines(t_canvas
*x
)
932 linetraverser_start(&t
, x
);
933 while((oc
= linetraverser_next(&t
)))
937 sys_vgui(".x%x.c create line %d %d %d %d -width %d -tags l%x\n",
939 t
.tr_lx1
, t
.tr_ly1
, t
.tr_lx2
, t
.tr_ly2
,
940 (outlet_getsymbol(t
.tr_outlet
) == &s_signal
? 2:1),
946 void canvas_fixlinesfor(t_canvas
*x
, t_text
*text
)
951 linetraverser_start(&t
, x
);
952 while((oc
= linetraverser_next(&t
)))
954 if (t
.tr_ob
== text
|| t
.tr_ob2
== text
)
957 sys_vgui(".x%x.c coords l%x %d %d %d %d\n",
958 glist_getcanvas(x
), oc
,
959 t
.tr_lx1
, t
.tr_ly1
, t
.tr_lx2
, t
.tr_ly2
);
965 /* kill all lines for the object */
966 void canvas_deletelinesfor(t_canvas
*x
, t_text
*text
)
970 linetraverser_start(&t
, x
);
971 while((oc
= linetraverser_next(&t
)))
973 if (t
.tr_ob
== text
|| t
.tr_ob2
== text
)
978 sys_vgui(".x%x.c delete l%x\n",
979 glist_getcanvas(x
), oc
);
982 obj_disconnect(t
.tr_ob
, t
.tr_outno
, t
.tr_ob2
, t
.tr_inno
);
987 /* kill all lines for one inlet or outlet */
988 void canvas_deletelinesforio(t_canvas
*x
, t_text
*text
,
989 t_inlet
*inp
, t_outlet
*outp
)
993 linetraverser_start(&t
, x
);
994 while((oc
= linetraverser_next(&t
)))
996 if ((t
.tr_ob
== text
&& t
.tr_outlet
== outp
) ||
997 (t
.tr_ob2
== text
&& t
.tr_inlet
== inp
))
1002 sys_vgui(".x%x.c delete l%x\n",
1003 glist_getcanvas(x
), oc
);
1006 obj_disconnect(t
.tr_ob
, t
.tr_outno
, t
.tr_ob2
, t
.tr_inno
);
1011 static void canvas_pop(t_canvas
*x
, t_floatarg fvis
)
1015 pd_popsym(&x
->gl_pd
);
1016 canvas_resortinlets(x
);
1017 canvas_resortoutlets(x
);
1021 void canvas_objfor(t_glist
*gl
, t_text
*x
, int argc
, t_atom
*argv
);
1024 void canvas_restore(t_canvas
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
1030 /* this should be unnecessary, but sometimes the canvas's name gets
1031 out of sync with the owning box's argument; this fixes that */
1035 if (ap
->a_type
== A_SYMBOL
)
1037 char *buf
=ap
->a_w
.w_symbol
->s_name
, *bufp
;
1038 if (*buf
== '$' && buf
[1] >= '0' && buf
[1] <= '9')
1040 for (bufp
= buf
+2; *bufp
; bufp
++)
1041 if (*bufp
< '0' || *bufp
> '9')
1043 SETDOLLSYM(ap
, gensym(buf
+1));
1046 SETDOLLAR(ap
, atoi(buf
+1));
1051 if (ap
->a_type
== A_DOLLSYM
)
1053 t_canvasenvironment
*e
= canvas_getenv(canvas_getcurrent());
1054 canvas_rename(x
, binbuf_realizedollsym(ap
->a_w
.w_symbol
,
1055 e
->ce_argc
, e
->ce_argv
, 1), 0);
1057 else if (ap
->a_type
== A_SYMBOL
)
1058 canvas_rename(x
, argv
[3].a_w
.w_symbol
, 0);
1060 canvas_pop(x
, x
->gl_willvis
);
1062 if (!(z
= gensym("#X")->s_thing
)) error("canvas_restore: out of context");
1063 else if (*z
!= canvas_class
) error("canvas_restore: wasn't a canvas");
1066 t_canvas
*x2
= (t_canvas
*)z
;
1068 canvas_objfor(x2
, &x
->gl_obj
, argc
, argv
);
1072 static void canvas_loadbangabstractions(t_canvas
*x
)
1078 t_symbol
*s
= gensym("loadbang");
1080 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
1081 if (pd_class(&y
->g_pd
) == canvas_class
)
1083 if (canvas_isabstraction((t_canvas
*)y
))
1084 canvas_loadbang((t_canvas
*)y
);
1086 canvas_loadbangabstractions((t_canvas
*)y
);
1090 void canvas_loadbangsubpatches(t_canvas
*x
)
1093 t_symbol
*s
= gensym("loadbang");
1094 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
1095 if (pd_class(&y
->g_pd
) == canvas_class
)
1097 if (!canvas_isabstraction((t_canvas
*)y
))
1098 canvas_loadbangsubpatches((t_canvas
*)y
);
1100 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
1101 if ((pd_class(&y
->g_pd
) != canvas_class
) &&
1102 zgetfn(&y
->g_pd
, s
))
1103 pd_vmess(&y
->g_pd
, s
, "");
1106 void canvas_loadbang(t_canvas
*x
)
1111 canvas_loadbangabstractions(x
);
1112 canvas_loadbangsubpatches(x
);
1115 /* When you ask a canvas its size the result is 2 pixels more than what
1116 you gave it to open it; perhaps there's a 1-pixel border all around it
1117 or something. Anyway, we just add the 2 pixels back here; seems we
1118 have to do this for linux but not MSW; not sure about MacOS.\x11 */
1121 #define HORIZBORDER 0
1122 #define VERTBORDER 0
1124 #define HORIZBORDER 2
1125 #define VERTBORDER 2
1128 static void canvas_relocate(t_canvas
*x
, t_symbol
*canvasgeom
,
1136 int cxpix
, cypix
, cw
, ch
, txpix
, typix
, tw
, th
;
1137 if (sscanf(canvasgeom
->s_name
, "%dx%d+%d+%d", &cw
, &ch
, &cxpix
, &cypix
)
1139 sscanf(topgeom
->s_name
, "%dx%d+%d+%d", &tw
, &th
, &txpix
, &typix
) < 4)
1140 bug("canvas_relocate");
1141 /* for some reason this is initially called with cw=ch=1 so
1142 we just suppress that here. */
1143 if (cw
> 5 && ch
> 5)
1144 canvas_setbounds(x
, txpix
, typix
,
1145 txpix
+ cw
- HORIZBORDER
, typix
+ ch
- VERTBORDER
);
1146 #endif /* ROCKBOX */
1149 void canvas_popabstraction(t_canvas
*x
)
1152 pd_popsym(&x
->gl_pd
);
1154 canvas_resortinlets(x
);
1155 canvas_resortoutlets(x
);
1158 void canvas_logerror(t_object
*y
)
1165 if (!glist_isselected(x
, &y
->ob_g
))
1166 glist_select(x
, &y
->ob_g
);
1170 /* -------------------------- subcanvases ---------------------- */
1172 static void *subcanvas_new(t_symbol
*s
)
1175 t_canvas
*x
, *z
= canvas_getcurrent();
1176 if (!*s
->s_name
) s
= gensym("/SUBPATCH/");
1178 SETFLOAT(a
+1, GLIST_DEFCANVASYLOC
);
1179 SETFLOAT(a
+2, GLIST_DEFCANVASWIDTH
);
1180 SETFLOAT(a
+3, GLIST_DEFCANVASHEIGHT
);
1183 x
= canvas_new(0, 0, 6, a
);
1189 static void canvas_click(t_canvas
*x
,
1190 t_floatarg xpos
, t_floatarg ypos
,
1191 t_floatarg shift
, t_floatarg ctrl
, t_floatarg alt
)
1204 /* find out from subcanvas contents how much to fatten the box */
1205 void canvas_fattensub(t_canvas
*x
,
1206 int *xp1
, int *yp1
, int *xp2
, int *yp2
)
1214 #endif /* ROCKBOX */
1215 *xp2
+= 50; /* fake for now */
1219 static void canvas_rename_method(t_canvas
*x
, t_symbol
*s
, int ac
, t_atom
*av
)
1224 if (ac
&& av
->a_type
== A_SYMBOL
)
1225 canvas_rename(x
, av
->a_w
.w_symbol
, 0);
1226 else canvas_rename(x
, gensym("Pd"), 0);
1229 /* ------------------ table ---------------------------*/
1231 static int tabcount
= 0;
1233 static void *table_new(t_symbol
*s
, t_floatarg f
)
1237 t_canvas
*x
, *z
= canvas_getcurrent();
1241 t_symbol
*t
= gensym("table");
1243 snprintf(tabname
, sizeof(tabname
), "%s%d", t
->s_name
, tabcount
++);
1245 sprintf(tabname
, "%s%d", t
->s_name
, tabcount
++);
1246 #endif /* ROCKBOX */
1247 s
= gensym(tabname
);
1252 SETFLOAT(a
+1, GLIST_DEFCANVASYLOC
);
1257 x
= canvas_new(0, 0, 6, a
);
1261 /* create a graph for the table */
1262 gl
= glist_addglist((t_glist
*)x
, &s_
, 0, -1, (f
> 1 ? f
-1 : 1), 1,
1265 graph_array(gl
, s
, &s_float
, f
, 0);
1272 /* return true if the "canvas" object is an abstraction (so we don't
1273 save its contents, fogr example.) */
1274 int canvas_isabstraction(t_canvas
*x
)
1276 return (x
->gl_env
!= 0);
1279 /* return true if the "canvas" object is a "table". */
1280 int canvas_istable(t_canvas
*x
)
1282 t_atom
*argv
= (x
->gl_obj
.te_binbuf
? binbuf_getvec(x
->gl_obj
.te_binbuf
):0);
1283 int argc
= (x
->gl_obj
.te_binbuf
? binbuf_getnatom(x
->gl_obj
.te_binbuf
) : 0);
1284 int istable
= (argc
&& argv
[0].a_type
== A_SYMBOL
&&
1285 argv
[0].a_w
.w_symbol
== gensym("table"));
1289 /* return true if the "canvas" object should be treated as a text
1290 object. This is true for abstractions but also for "table"s... */
1291 int canvas_showtext(t_canvas
*x
)
1293 t_atom
*argv
= (x
->gl_obj
.te_binbuf
? binbuf_getvec(x
->gl_obj
.te_binbuf
):0);
1294 int argc
= (x
->gl_obj
.te_binbuf
? binbuf_getnatom(x
->gl_obj
.te_binbuf
) : 0);
1295 int isarray
= (argc
&& argv
[0].a_type
== A_SYMBOL
&&
1296 argv
[0].a_w
.w_symbol
== gensym("graph"));
1300 static void canvas_dodsp(t_canvas
*x
, int toplevel
, t_signal
**sp
);
1301 static void canvas_dsp(t_canvas
*x
, t_signal
**sp
)
1303 canvas_dodsp(x
, 0, sp
);
1306 /* get the document containing this canvas */
1307 t_canvas
*canvas_getrootfor(t_canvas
*x
)
1309 if ((!x
->gl_owner
) || canvas_isabstraction(x
))
1311 else return (canvas_getrootfor(x
->gl_owner
));
1314 /* ------------------------- DSP chain handling ------------------------- */
1316 EXTERN_STRUCT _dspcontext
;
1317 #define t_dspcontext struct _dspcontext
1319 void ugen_start(void);
1320 void ugen_stop(void);
1322 t_dspcontext
*ugen_start_graph(int toplevel
, t_signal
**sp
,
1323 int ninlets
, int noutlets
);
1324 void ugen_add(t_dspcontext
*dc
, t_object
*x
);
1325 void ugen_connect(t_dspcontext
*dc
, t_object
*x1
, int outno
,
1326 t_object
*x2
, int inno
);
1327 void ugen_done_graph(t_dspcontext
*dc
);
1329 /* schedule one canvas for DSP. This is called below for all "root"
1330 canvases, but is also called from the "dsp" method for sub-
1331 canvases, which are treated almost like any other tilde object. */
1333 static void canvas_dodsp(t_canvas
*x
, int toplevel
, t_signal
**sp
)
1339 t_symbol
*dspsym
= gensym("dsp");
1342 /* create a new "DSP graph" object to use in sorting this canvas.
1343 If we aren't toplevel, there are already other dspcontexts around. */
1345 dc
= ugen_start_graph(toplevel
, sp
,
1346 obj_nsiginlets(&x
->gl_obj
),
1347 obj_nsigoutlets(&x
->gl_obj
));
1349 /* find all the "dsp" boxes and add them to the graph */
1351 for (y
= x
->gl_list
; y
; y
= y
->g_next
)
1352 if ((ob
= pd_checkobject(&y
->g_pd
)) && zgetfn(&y
->g_pd
, dspsym
))
1355 /* ... and all dsp interconnections */
1356 linetraverser_start(&t
, x
);
1357 while((oc
= linetraverser_next(&t
)))
1358 if (obj_issignaloutlet(t
.tr_ob
, t
.tr_outno
))
1359 ugen_connect(dc
, t
.tr_ob
, t
.tr_outno
, t
.tr_ob2
, t
.tr_inno
);
1361 /* finally, sort them and add them to the DSP chain */
1362 ugen_done_graph(dc
);
1365 /* this routine starts DSP for all root canvases. */
1366 static void canvas_start_dsp(void)
1369 if (canvas_dspstate
) ugen_stop();
1371 else sys_gui("pdtk_pd_dsp ON\n");
1375 for (x
= canvas_list
; x
; x
= x
->gl_next
)
1376 canvas_dodsp(x
, 1, 0);
1378 canvas_dspstate
= 1;
1381 static void canvas_stop_dsp(void)
1383 if (canvas_dspstate
)
1387 sys_gui("pdtk_pd_dsp OFF\n");
1389 canvas_dspstate
= 0;
1393 /* DSP can be suspended before, and resumed after, operations which
1394 might affect the DSP chain. For example, we suspend before loading and
1395 resume afterward, so that DSP doesn't get resorted for every DSP object
1398 int canvas_suspend_dsp(void)
1400 int rval
= canvas_dspstate
;
1401 if (rval
) canvas_stop_dsp();
1405 void canvas_resume_dsp(int oldstate
)
1407 if (oldstate
) canvas_start_dsp();
1410 /* this is equivalent to suspending and resuming in one step. */
1411 void canvas_update_dsp(void)
1413 if (canvas_dspstate
) canvas_start_dsp();
1416 void glob_dsp(void *dummy
, t_symbol
*s
, int argc
, t_atom
*argv
)
1425 newstate
= atom_getintarg(0, argc
, argv
);
1426 if (newstate
&& !canvas_dspstate
)
1428 sys_set_audio_state(1);
1431 else if (!newstate
&& canvas_dspstate
)
1434 sys_set_audio_state(0);
1437 else post("dsp state %d", canvas_dspstate
);
1440 /* LATER replace this with a queueing scheme */
1441 void glist_redrawitem(t_glist
*owner
, t_gobj
*gobj
)
1443 if (glist_isvisible(owner
))
1445 gobj_vis(gobj
, owner
, 0);
1446 gobj_vis(gobj
, owner
, 1);
1450 /* redraw all "scalars" (do this if a drawing command is changed.)
1451 LATER we'll use the "template" information to select which ones we
1453 static void glist_redrawall(t_glist
*gl
)
1456 int vis
= glist_isvisible(gl
);
1457 for (g
= gl
->gl_list
; g
; g
= g
->g_next
)
1462 if (vis
&& g
->g_pd
== scalar_class
)
1463 glist_redrawitem(gl
, g
);
1464 else if (g
->g_pd
== canvas_class
)
1465 glist_redrawall((t_glist
*)g
);
1469 /* public interface for above */
1470 void canvas_redrawallfortemplate(t_canvas
*templatecanvas
)
1474 (void) templatecanvas
;
1476 /* find all root canvases */
1477 for (x
= canvas_list
; x
; x
= x
->gl_next
)
1481 /* ------------------------------- setup routine ------------------------ */
1483 /* why are some of these "glist" and others "canvas"? */
1484 extern void glist_text(t_glist
*x
, t_symbol
*s
, int argc
, t_atom
*argv
);
1485 extern void canvas_obj(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1486 extern void canvas_bng(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1487 extern void canvas_toggle(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1488 extern void canvas_vslider(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1489 extern void canvas_hslider(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1490 extern void canvas_vdial(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1491 /* old version... */
1492 extern void canvas_hdial(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1493 extern void canvas_hdial(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1495 extern void canvas_hradio(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1496 extern void canvas_vradio(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1497 extern void canvas_vumeter(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1498 extern void canvas_mycnv(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1499 extern void canvas_numbox(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1500 extern void canvas_msg(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1501 extern void canvas_floatatom(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1502 extern void canvas_symbolatom(t_glist
*gl
, t_symbol
*s
, int argc
, t_atom
*argv
);
1503 extern void glist_scalar(t_glist
*canvas
, t_symbol
*s
, int argc
, t_atom
*argv
);
1505 void g_graph_setup(void);
1506 void g_editor_setup(void);
1507 void g_readwrite_setup(void);
1508 extern void graph_properties(t_gobj
*z
, t_glist
*owner
);
1510 void g_canvas_setup(void)
1512 /* we prevent the user from typing "canvas" in an object box
1513 by sending 0 for a creator function. */
1514 canvas_class
= class_new(gensym("canvas"), 0,
1515 (t_method
)canvas_free
, sizeof(t_canvas
), CLASS_NOINLET
, 0);
1516 /* here is the real creator function, invoked in patch files
1517 by sending the "canvas" message to #N, which is bound
1518 to pd_camvasmaker. */
1519 class_addmethod(pd_canvasmaker
, (t_method
)canvas_new
, gensym("canvas"),
1521 class_addmethod(canvas_class
, (t_method
)canvas_restore
,
1522 gensym("restore"), A_GIMME
, 0);
1523 class_addmethod(canvas_class
, (t_method
)canvas_coords
,
1524 gensym("coords"), A_GIMME
, 0);
1526 /* -------------------------- objects ----------------------------- */
1527 class_addmethod(canvas_class
, (t_method
)canvas_obj
,
1528 gensym("obj"), A_GIMME
, A_NULL
);
1529 class_addmethod(canvas_class
, (t_method
)canvas_msg
,
1530 gensym("msg"), A_GIMME
, A_NULL
);
1531 class_addmethod(canvas_class
, (t_method
)canvas_floatatom
,
1532 gensym("floatatom"), A_GIMME
, A_NULL
);
1533 class_addmethod(canvas_class
, (t_method
)canvas_symbolatom
,
1534 gensym("symbolatom"), A_GIMME
, A_NULL
);
1535 class_addmethod(canvas_class
, (t_method
)glist_text
,
1536 gensym("text"), A_GIMME
, A_NULL
);
1537 class_addmethod(canvas_class
, (t_method
)glist_glist
, gensym("graph"),
1539 class_addmethod(canvas_class
, (t_method
)glist_scalar
,
1540 gensym("scalar"), A_GIMME
, A_NULL
);
1542 /* -------------- Thomas Musil's GUI objects ------------ */
1543 class_addmethod(canvas_class
, (t_method
)canvas_bng
, gensym("bng"),
1545 class_addmethod(canvas_class
, (t_method
)canvas_toggle
, gensym("toggle"),
1547 class_addmethod(canvas_class
, (t_method
)canvas_vslider
, gensym("vslider"),
1549 class_addmethod(canvas_class
, (t_method
)canvas_hslider
, gensym("hslider"),
1551 class_addmethod(canvas_class
, (t_method
)canvas_hdial
, gensym("hdial"),
1553 class_addmethod(canvas_class
, (t_method
)canvas_vdial
, gensym("vdial"),
1555 class_addmethod(canvas_class
, (t_method
)canvas_hradio
, gensym("hradio"),
1557 class_addmethod(canvas_class
, (t_method
)canvas_vradio
, gensym("vradio"),
1559 class_addmethod(canvas_class
, (t_method
)canvas_vumeter
, gensym("vumeter"),
1561 class_addmethod(canvas_class
, (t_method
)canvas_mycnv
, gensym("mycnv"),
1563 class_addmethod(canvas_class
, (t_method
)canvas_numbox
, gensym("numbox"),
1566 /* ------------------------ gui stuff --------------------------- */
1567 class_addmethod(canvas_class
, (t_method
)canvas_pop
, gensym("pop"),
1568 A_DEFFLOAT
, A_NULL
);
1569 class_addmethod(canvas_class
, (t_method
)canvas_loadbang
,
1570 gensym("loadbang"), A_NULL
);
1571 class_addmethod(canvas_class
, (t_method
)canvas_relocate
,
1572 gensym("relocate"), A_SYMBOL
, A_SYMBOL
, A_NULL
);
1573 class_addmethod(canvas_class
, (t_method
)canvas_vis
,
1574 gensym("vis"), A_FLOAT
, A_NULL
);
1575 class_addmethod(canvas_class
, (t_method
)glist_menu_open
,
1576 gensym("menu-open"), A_NULL
);
1577 class_addmethod(canvas_class
, (t_method
)canvas_map
,
1578 gensym("map"), A_FLOAT
, A_NULL
);
1579 class_setpropertiesfn(canvas_class
, graph_properties
);
1581 /* ---------------------- list handling ------------------------ */
1582 class_addmethod(canvas_class
, (t_method
)glist_clear
, gensym("clear"),
1585 /* ----- subcanvases, which you get by typing "pd" in a box ---- */
1586 class_addcreator((t_newmethod
)subcanvas_new
, gensym("pd"), A_DEFSYMBOL
, 0);
1587 class_addcreator((t_newmethod
)subcanvas_new
, gensym("page"), A_DEFSYMBOL
, 0);
1589 class_addmethod(canvas_class
, (t_method
)canvas_click
,
1590 gensym("click"), A_FLOAT
, A_FLOAT
, A_FLOAT
, A_FLOAT
, A_FLOAT
, 0);
1591 class_addmethod(canvas_class
, (t_method
)canvas_dsp
, gensym("dsp"), 0);
1592 class_addmethod(canvas_class
, (t_method
)canvas_rename_method
,
1593 gensym("rename"), A_GIMME
, 0);
1595 /*---------------------------- tables -- GG ------------------- */
1597 class_addcreator((t_newmethod
)table_new
, gensym("table"),
1598 A_DEFSYM
, A_DEFFLOAT
, 0);
1600 /* -------------- setups from other files for canvas_class ---------------- */
1603 g_readwrite_setup();