diff options
-rw-r--r-- | shared/common/Makefile.sources | 1 | ||||
-rw-r--r-- | shared/common/patchvalue.c | 265 | ||||
-rw-r--r-- | shared/common/patchvalue.h | 24 | ||||
-rw-r--r-- | shared/notes.txt | 6 | ||||
-rw-r--r-- | shared/toxy/scriptlet.c | 18 | ||||
-rw-r--r-- | shared/toxy/scriptlet.h | 9 | ||||
-rw-r--r-- | shared/unstable/fragile.c | 7 | ||||
-rw-r--r-- | shared/unstable/fragile.h | 2 | ||||
-rw-r--r-- | test/cyclone/speedlim-rescheduling.pd | 54 | ||||
-rw-r--r-- | test/toxy/button-test.pd | 2 | ||||
-rw-r--r-- | test/toxy/editors/bpf-test.pd | 13 | ||||
-rw-r--r-- | test/toxy/editors/bpf.wid | 224 | ||||
-rw-r--r-- | test/toxy/listbox-test.pd | 2 | ||||
-rw-r--r-- | test/toxy/popcustom-test.pd | 2 | ||||
-rw-r--r-- | test/toxy/setup.wid | 47 | ||||
-rw-r--r-- | test/toxy/testmess.wid | 3 | ||||
-rw-r--r-- | test/toxy/tow-test.pd | 2 | ||||
-rw-r--r-- | toxy/Makefile.objects | 2 | ||||
-rw-r--r-- | toxy/build_counter | 4 | ||||
-rw-r--r-- | toxy/notes.txt | 26 | ||||
-rw-r--r-- | toxy/widget.c | 351 | ||||
-rw-r--r-- | toxy/widget.h | 46 | ||||
-rw-r--r-- | toxy/widgethandlers.c | 211 | ||||
-rw-r--r-- | toxy/widgettype.c | 192 | ||||
-rw-r--r-- | toxy/widgettype.h | 41 |
25 files changed, 1205 insertions, 349 deletions
diff --git a/shared/common/Makefile.sources b/shared/common/Makefile.sources index 76fd3cc..33bf597 100644 --- a/shared/common/Makefile.sources +++ b/shared/common/Makefile.sources @@ -8,6 +8,7 @@ lex.c \ loud.c \ mifi.c \ os.c \ +patchvalue.c \ port.c \ props.c \ qtree.c \ diff --git a/shared/common/patchvalue.c b/shared/common/patchvalue.c new file mode 100644 index 0000000..b75b565 --- /dev/null +++ b/shared/common/patchvalue.c @@ -0,0 +1,265 @@ +/* Copyright (c) 2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "patchvalue.h" + +#ifdef KRZYSZCZ +# include "loud.h" +# define PATCHVALUE_DEBUG +#else +# define loudbug_bug(msg) fprintf(stderr, "BUG: %s\n", msg), bug(msg) +#endif + +typedef struct _patchstorage +{ + t_glist *ps_glist; + t_patchvalue *ps_values; + struct _patchstorage *ps_next; +} t_patchstorage; + +typedef struct _patchboard +{ + t_pd pb_pd; + t_symbol *pb_category; + t_patchstorage *pb_contents; +} t_patchboard; + +static t_class *patchboard_class = 0; + +/* assuming there is no 'name' in the storage */ +static t_patchvalue *patchstorage_addvalue( + t_patchstorage *ps, t_patchvalue *prv, t_class *cls, t_symbol *name) +{ + t_patchvalue *pv = (t_patchvalue *)pd_new(cls); + pv->pv_name = name; + pv->pv_refcount = 0; + if (prv) + { + pv->pv_next = prv->pv_next; + prv->pv_next = pv; + } + else + { + pv->pv_next = ps->ps_values; + ps->ps_values = pv; + } + return (pv); +} + +/* assuming there is no 'glist' on the board */ +static t_patchstorage *patchboard_addstorage( + t_patchboard *pb, t_patchstorage *prv, t_glist *glist) +{ + t_patchstorage *ps = getbytes(sizeof(*ps)); + ps->ps_glist = glist; + ps->ps_values = 0; + if (prv) + { + ps->ps_next = prv->ps_next; + prv->ps_next = ps; + } + else + { + ps->ps_next = pb->pb_contents; + pb->pb_contents = ps; + } + return (ps); +} + +/* not used (LATER find a gc scheme) */ +static void patchstorage_removevalue( + t_patchstorage *ps, t_patchvalue *prv, t_patchvalue *pv, int force) +{ + if (force || pv->pv_refcount < 1) + { + if (prv) + prv->pv_next = pv->pv_next; + else + ps->ps_values = pv->pv_next; + pd_free((t_pd *)pv); + } +} + +/* not used (LATER find a gc scheme) */ +static void patchboard_removestorage( + t_patchboard *pb, t_patchstorage *prv, t_patchstorage *ps, int force) +{ + if (prv) + prv->ps_next = ps->ps_next; + else + pb->pb_contents = ps->ps_next; + if (force) + { + t_patchvalue *pv, *pvnext = ps->ps_values; + while (pv = pvnext) + { + pvnext = pv->pv_next; + pd_free((t_pd *)pv); + } + } + else if (ps->ps_values) + return; + freebytes(ps, sizeof(*ps)); +} + +static t_patchvalue *patchstorage_findvalue( + t_patchstorage *ps, t_symbol *name) +{ + t_patchvalue *pv; + for (pv = ps->ps_values; pv; pv = pv->pv_next) + if (pv->pv_name == name) + break; + return (pv); +} + +static t_patchstorage *patchboard_findstorage( + t_patchboard *pb, t_glist *glist) +{ + t_patchstorage *ps; + for (ps = pb->pb_contents; ps; ps = ps->ps_next) + if (ps->ps_glist == glist) + break; + return (ps); +} + +static t_patchboard *patchboard_find(t_symbol *category) +{ + if (!patchboard_class) + patchboard_class = + patchvalue_classnew(gensym("_patchboard"), sizeof(t_patchboard)); + return ((t_patchboard *)pd_findbyclass(category, patchboard_class)); +} + +static t_patchboard *patchboard_use(t_symbol *category) +{ + if (!patchboard_class) + patchboard_class = + patchvalue_classnew(gensym("_patchboard"), sizeof(t_patchboard)); + if (category && *category->s_name == '#') + { + t_patchboard *pb; + if (!(pb = (t_patchboard *)pd_findbyclass(category, patchboard_class))) + { + pb = (t_patchboard *)pd_new(patchboard_class); + pb->pb_category = category; + pd_bind((t_pd *)pb, category); /* never unbound */ + pb->pb_contents = 0; + } + return (pb); + } + else + { + loudbug_bug("patchboard_use"); + return (0); + } +} + +static t_patchstorage *patchstorage_use(t_symbol *category, t_glist *glist) +{ + t_patchboard *pb; + if (pb = patchboard_use(category)) + { + t_patchstorage *ps; + if (!(ps = patchboard_findstorage(pb, glist))) + ps = patchboard_addstorage(pb, 0, glist); + return (ps); + } + else return (0); +} + +/* The class might have been created by another dll... + This is public, because apart from the "_patchboard" class above, + it is called for the "_raftentry" class too. LATER rethink. */ +t_class *patchvalue_classnew(t_symbol *cname, size_t size) +{ + t_class *cls; + t_symbol *bindsym; + char buf[MAXPDSTRING]; + sprintf(buf, "#%s", cname->s_name); + bindsym = gensym(buf); + if (bindsym->s_thing) + { + t_pd *pd = bindsym->s_thing; + char *name = class_getname(*pd); + if (strcmp(name, cname->s_name)) + { + /* FIXME handle this properly... */ + loudbug_bug("patchvalue_classnew"); + } + else return (*pd); + } + cls = class_new(cname, 0, 0, size, CLASS_PD | CLASS_NOINLET, 0); + pd_bind(pd_new(cls), bindsym); /* never unbound */ + return (cls); +} + +t_patchvalue *patchvalue_use(t_symbol *category, t_glist *glist, + t_class *cls, t_symbol *name) +{ + t_patchstorage *ps; + if (ps = patchstorage_use(category, glist)) + { + t_patchvalue *pv; + if (pv = patchstorage_findvalue(ps, name)) + { + if (*(t_pd *)pv != cls) + { + loudbug_bug("patchvalue_use"); + return (0); + } + } + else pv = patchstorage_addvalue(ps, 0, cls, name); + return (pv); + } + else return (0); +} + +t_patchvalue *patchvalue_get(t_symbol *category, t_glist *glist, + t_class *cls, t_symbol *name) +{ + t_patchboard *pb; + t_patchstorage *ps; + t_patchvalue *pv; + if ((pb = patchboard_find(category)) && + (ps = patchboard_findstorage(pb, glist)) && + (pv = patchstorage_findvalue(ps, name))) + { + if (*(t_pd *)pv == cls) + return (pv); + else + loudbug_bug("patchvalue_get"); + } + return (0); +} + +t_patchvalue *patchvalue_resolve(t_symbol *category, t_glist *glist, + t_class *cls, t_symbol *name) +{ + t_patchboard *pb; + if (pb = patchboard_find(category)) + { + t_patchstorage *ps; + t_patchvalue *pv; + while (glist) + { + if ((ps = patchboard_findstorage(pb, glist)) && + (pv = patchstorage_findvalue(ps, name))) + { + if (*(t_pd *)pv == cls) + return (pv); + else + loudbug_bug("patchvalue_resolve"); + } + else if (canvas_isabstraction(glist)) + break; + else + glist = glist->gl_owner; + } + } + return (0); +} diff --git a/shared/common/patchvalue.h b/shared/common/patchvalue.h new file mode 100644 index 0000000..1a7bc79 --- /dev/null +++ b/shared/common/patchvalue.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __PATCHVALUE_H__ +#define __PATCHVALUE_H__ + +typedef struct _patchvalue +{ + t_pd pv_pd; + t_symbol *pv_name; + int pv_refcount; + struct _patchvalue *pv_next; +} t_patchvalue; + +t_class *patchvalue_classnew(t_symbol *cname, size_t size); +t_patchvalue *patchvalue_use(t_symbol *category, t_glist *glist, + t_class *cls, t_symbol *name); +t_patchvalue *patchvalue_get(t_symbol *category, t_glist *glist, + t_class *cls, t_symbol *name); +t_patchvalue *patchvalue_resolve(t_symbol *category, t_glist *glist, + t_class *cls, t_symbol *name); + +#endif diff --git a/shared/notes.txt b/shared/notes.txt index 9f92507..3f35ae2 100644 --- a/shared/notes.txt +++ b/shared/notes.txt @@ -5,6 +5,12 @@ TODO for root and shared DONE for root and shared +with rafts prealpha1 + * new module: patchvalue + +with toxy alpha17 + * scriptlet: new call scriptlet_newalike() + with cyclone alpha54 and toxy alpha16 * props: . code cleanup diff --git a/shared/toxy/scriptlet.c b/shared/toxy/scriptlet.c index bf207c1..42e3c02 100644 --- a/shared/toxy/scriptlet.c +++ b/shared/toxy/scriptlet.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003-2004 krzYszcz and others. +/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ @@ -46,7 +46,7 @@ struct _scriptlet t_glist *s_glist; /* containing glist (empty allowed) */ t_symbol *s_rptarget; /* reply target */ t_symbol *s_cbtarget; /* callback target */ - t_symbol *s_item; + t_symbol *s_item; /* item's name (readable part of its path) */ t_scriptlet_cvfn s_cvfn; /* if empty, passing resolveall is a bug */ t_canvas *s_cv; /* as returned by cvfn */ int s_cvstate; @@ -1048,8 +1048,10 @@ void scriptlet_free(t_scriptlet *sp) /* The parameter 'gl' (null accepted) is necessary, because the 's_glist' field, if implicitly set, would be dangerous (after a glist is gone) and confusing (current directory used for i/o of a global scriptlet). */ -t_scriptlet *scriptlet_new(t_pd *owner, t_symbol *rptarget, t_symbol *cbtarget, - t_symbol *item, t_glist *gl, t_scriptlet_cvfn cvfn) +t_scriptlet *scriptlet_new(t_pd *owner, + t_symbol *rptarget, t_symbol *cbtarget, + t_symbol *item, t_glist *glist, + t_scriptlet_cvfn cvfn) { t_scriptlet *sp = getbytes(sizeof(*sp)); if (sp) @@ -1065,7 +1067,7 @@ t_scriptlet *scriptlet_new(t_pd *owner, t_symbol *rptarget, t_symbol *cbtarget, configured = 1; } sp->s_owner = owner; - sp->s_glist = gl; + sp->s_glist = glist; sp->s_rptarget = rptarget; sp->s_cbtarget = cbtarget; sp->s_item = item; @@ -1079,3 +1081,9 @@ t_scriptlet *scriptlet_new(t_pd *owner, t_symbol *rptarget, t_symbol *cbtarget, } return (sp); } + +t_scriptlet *scriptlet_newalike(t_scriptlet *sp) +{ + return (scriptlet_new(sp->s_owner, sp->s_rptarget, sp->s_cbtarget, + sp->s_item, sp->s_glist, sp->s_cvfn)); +} diff --git a/shared/toxy/scriptlet.h b/shared/toxy/scriptlet.h index c9411ae..5887950 100644 --- a/shared/toxy/scriptlet.h +++ b/shared/toxy/scriptlet.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2003-2004 krzYszcz and others. +/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ @@ -41,7 +41,10 @@ void scriptlet_setowner(t_scriptlet *sp, t_pd *owner); void scriptlet_clone(t_scriptlet *to, t_scriptlet *from); void scriptlet_append(t_scriptlet *to, t_scriptlet *from); void scriptlet_free(t_scriptlet *sp); -t_scriptlet *scriptlet_new(t_pd *owner, t_symbol *rptarget, t_symbol *cbtarget, - t_symbol *item, t_glist *gl, t_scriptlet_cvfn cvfn); +t_scriptlet *scriptlet_new(t_pd *owner, + t_symbol *rptarget, t_symbol *cbtarget, + t_symbol *item, t_glist *glist, + t_scriptlet_cvfn cvfn); +t_scriptlet *scriptlet_newalike(t_scriptlet *sp); #endif diff --git a/shared/unstable/fragile.c b/shared/unstable/fragile.c index d91ea58..e65e6d4 100644 --- a/shared/unstable/fragile.c +++ b/shared/unstable/fragile.c @@ -15,15 +15,20 @@ int fragile_class_count(void) return (pd_objectmaker->c_nmethod); } -void fragile_class_getnames(t_atom *av) +int fragile_class_getnames(t_atom *av, int maxnames) { int ac = pd_objectmaker->c_nmethod; t_methodentry *mp = pd_objectmaker->c_methods; + if (ac > maxnames) + ac = maxnames; + else + maxnames = ac; while (ac--) { SETSYMBOL(av, mp->me_name); mp++; av++; } + return (maxnames); } /* Raising and voluntary mutation is a method of resolving name clashes. diff --git a/shared/unstable/fragile.h b/shared/unstable/fragile.h index b59bb14..1e2ea0e 100644 --- a/shared/unstable/fragile.h +++ b/shared/unstable/fragile.h @@ -6,7 +6,7 @@ #define __FRAGILE_H__ int fragile_class_count(void); -void fragile_class_getnames(t_atom *av); +int fragile_class_getnames(t_atom *av, int maxnames); void fragile_class_raise(t_symbol *cname, t_newmethod thiscall); t_pd *fragile_class_mutate(t_symbol *cname, t_newmethod thiscall, int ac, t_atom *av); diff --git a/test/cyclone/speedlim-rescheduling.pd b/test/cyclone/speedlim-rescheduling.pd new file mode 100644 index 0000000..62727ae --- /dev/null +++ b/test/cyclone/speedlim-rescheduling.pd @@ -0,0 +1,54 @@ +#N canvas 246 121 642 393 12; +#X msg 126 17 bang; +#X obj 126 58 t b b b; +#X msg 151 108 1; +#X msg 60 151 2; +#X msg 401 17 bang; +#X obj 401 58 t b b b; +#X msg 426 108 1; +#X msg 335 151 2; +#X obj 151 288 timer; +#X obj 151 241 sel 1 2; +#X obj 426 288 timer; +#X obj 426 241 sel 1 2; +#X obj 285 241 print; +#X floatatom 151 332 5 0 0 0 - - -; +#X floatatom 426 332 5 0 0 0 - - -; +#X msg 242 108 1000; +#X obj 151 198 speedlim 200; +#X msg 202 151 200; +#X msg 517 108 1000; +#X msg 478 151 200; +#X obj 426 198 speedlim 200; +#X obj 60 108 del 600; +#X obj 335 108 del 600; +#X connect 0 0 1 0; +#X connect 1 0 21 0; +#X connect 1 1 15 0; +#X connect 1 2 2 0; +#X connect 2 0 16 0; +#X connect 3 0 16 0; +#X connect 4 0 5 0; +#X connect 5 0 22 0; +#X connect 5 1 6 0; +#X connect 5 2 18 0; +#X connect 6 0 20 0; +#X connect 7 0 20 0; +#X connect 8 0 13 0; +#X connect 9 0 8 0; +#X connect 9 1 8 1; +#X connect 9 1 17 0; +#X connect 10 0 14 0; +#X connect 11 0 10 0; +#X connect 11 1 10 1; +#X connect 11 1 19 0; +#X connect 15 0 16 1; +#X connect 16 0 9 0; +#X connect 16 0 12 0; +#X connect 17 0 16 1; +#X connect 18 0 20 1; +#X connect 19 0 20 1; +#X connect 20 0 11 0; +#X connect 20 0 12 0; +#X connect 21 0 3 0; +#X connect 22 0 7 0; diff --git a/test/toxy/button-test.pd b/test/toxy/button-test.pd index 26e181b..2210319 100644 --- a/test/toxy/button-test.pd +++ b/test/toxy/button-test.pd @@ -21,7 +21,7 @@ red -command .<.>; #X msg 90 213 -command .(set c [tk_chooseColor] .: eval .<| set "-bg" $c "-text" $c.>.); #X obj 294 268 loadbang; -#X msg 294 295 ini .- config -textvariable ""; +#X msg 294 295 set @vis .- config -textvariable ""; #X obj 250 21 widget button bb -bg green -activebackground yellow -command .<.> ; #X connect 0 0 3 0; diff --git a/test/toxy/editors/bpf-test.pd b/test/toxy/editors/bpf-test.pd new file mode 100644 index 0000000..77fc3fc --- /dev/null +++ b/test/toxy/editors/bpf-test.pd @@ -0,0 +1,13 @@ +#N canvas 212 48 778 592 12; +#X obj 70 95 widget bpf f1; +#X obj 240 321 widget bpf f1; +#X obj 432 92 widget bpf f2; +#X msg 77 331 redefine; +#X obj 77 370 tow . bpf f1; +#X msg 80 432 redefine; +#X msg 578 336 redefine; +#X obj 578 375 tow . bpf f2; +#X obj 80 471 tow . bpf; +#X connect 3 0 4 0; +#X connect 5 0 8 0; +#X connect 6 0 7 0; diff --git a/test/toxy/editors/bpf.wid b/test/toxy/editors/bpf.wid new file mode 100644 index 0000000..1b30646 --- /dev/null +++ b/test/toxy/editors/bpf.wid @@ -0,0 +1,224 @@ +catch {console show} +::toxy::package_require BLT "e:/Tcl/bin/BLT24.dll" + +namespace eval ::toxy::bpf {} + +proc ::toxy::bpf::ondrag {path ndx} { + set ${path}::idrag $ndx + if {$ndx > 0} { + incr ndx -1 + set ${path}::mindrag [${path}::xvec range $ndx $ndx] + incr ndx + } else { + set ${path}::mindrag 0 + } + incr ndx + if {$ndx < [${path}::xvec length]} { + set ${path}::maxdrag [${path}::xvec range $ndx $ndx] + } else { + set ${path}::maxdrag [set ${path}::xmax] + } +} + +proc ::toxy::bpf::atData {path args} { + set cmd [lindex $args 0] + switch -- $cmd { + set { + set idrag [lindex $args 1] + set gx [lindex $args 2] + set gy [lindex $args 3] + if {[string is double -strict $idrag] && + [string is double -strict $gx] && + [string is double -strict $gy]} { + + ${path}::xvec variable xvec + ${path}::yvec variable yvec + array set xvec [list $idrag $gx] + array set yvec [list $idrag $gy] + ${path}::xvec sort ${path}::yvec ${path}::zvec + } + } + add { + set gx [lindex $args 1] + set gy [lindex $args 2] + if {[string is double -strict $gx] && + [string is double -strict $gy]} { + + ${path}::xvec append $gx + ${path}::yvec append $gy + ${path}::zvec append 0 + ${path}::xvec sort ${path}::yvec ${path}::zvec + set ndx [${path}::xvec search $gx] + if {[llength $ndx] > 1} { + set ndx [lindex $ndx 0] + } elseif {[llength $ndx] < 1} { + set ${path}::idrag -1 + return + } + ::toxy::bpf::ondrag $path $ndx + } + } + } +} + +proc ::toxy::bpf::motion {path x y} { + if {[set ${path}::locked]} { return } + if {[$path element closest $x $y cl -halo 10 el]} { + $path config -cursor arrow + } else { + $path config -cursor crosshair + } +} + +proc ::toxy::bpf::b1motion {path x y} { + if {[set ${path}::locked]} { return } + variable ${path}::idrag + if {$idrag >= 0 && [$path inside $x $y]} { + variable ${path}::mindrag + variable ${path}::maxdrag + set gxy [$path invtransform $x $y] + set gx [lindex $gxy 0] + if {$gx < $mindrag} { + set gx $mindrag + } elseif {$gx > $maxdrag} { + set gx $maxdrag + } + ${path}::xvec variable xvec + ${path}::yvec variable yvec + array set xvec [list $idrag $gx] + array set yvec [list $idrag [lindex $gxy 1]] + } +} + +proc ::toxy::bpf::b1release {path x y} { + if {[set ${path}::locked]} { return } + variable ${path}::idrag + if {$idrag >= 0 && [$path inside $x $y]} { + variable ${path}::mindrag + variable ${path}::maxdrag + set gxy [$path invtransform $x $y] + set gx [lindex $gxy 0] + set gy [lindex $gxy 1] + if {$gx < $mindrag} { + set gx $mindrag + } elseif {$gx > $maxdrag} { + set gx $maxdrag + } + + variable ${path}::target + pd $target.rp _data set $idrag $gx $gy \; + } + set ${path}::idrag -1 + set ${path}::mindrag 0 + set ${path}::maxdrag ${path}::xmax +} + +proc ::toxy::bpf::b1click {path x y} { + if {[set ${path}::locked]} { return } + if {[$path element closest $x $y cl -halo 10 el]} { + set gxy [$path invtransform $x $y] + set ${path}::xdrag [lindex $gxy 0] + set ${path}::ydrag [lindex $gxy 1] + ::toxy::bpf::ondrag $path $cl(index) + } elseif {[$path inside $x $y]} { + set gxy [$path invtransform $x $y] + set ${path}::xdrag [lindex $gxy 0] + set ${path}::ydrag [lindex $gxy 1] + variable ${path}::xdrag + variable ${path}::ydrag + + variable ${path}::target + pd $target.rp _data add $xdrag $ydrag \; + } else { + set ${path}::idrag -1 + } +} + +proc ::toxy::bpf::shiftb1click {path x y} { + if {[set ${path}::locked]} { return } + if {[$path element closest $x $y cl -halo 10 el]} { + set ndx $cl(index) + ${path}::xvec delete $ndx + ${path}::yvec delete $ndx + ${path}::zvec delete $ndx + } + set ${path}::idrag -1 +} + +proc ::toxy::bpf::lock {path v} { + set ${path}::locked $v + if {$v} { + $path config -cursor hand2 + } else { + $path config -cursor crosshair + } +} + +proc ::toxy::bpf::atVis {path} { + bind $path <Motion> +[concat ::toxy::bpf::motion %W %x %y] + bind $path <1> +[concat ::toxy::bpf::b1click %W %x %y] + bind $path <B1-Motion> +[concat ::toxy::bpf::b1motion %W %x %y] + bind $path <ButtonRelease> +[concat ::toxy::bpf::b1release %W %x %y] + bind $path <<disable>> +[concat ::toxy::bpf::lock %W 1] + bind $path <<enable>> +[concat ::toxy::bpf::lock %W 0] + $path element bind el <Shift-1> "::toxy::bpf::shiftb1click %W %x %y" +} + +proc ::toxy::bpf::atNew {path} { + variable ${path}::xmax + variable ${path}::ymin + variable ${path}::ymax + $path axis configure x -min 0.0 -max $xmax + $path axis configure y -min $ymin -max $ymax + $path element create el -x ${path}::xvec -y ${path}::yvec \ + -symbol "circle" -pixels 2 -linewidth 2 -color darkgreen -hide 0 + $path legend config -hide yes +} + +proc ::toxy::bpf::atFree {path} { + blt::vector destroy ${path}::xvec + blt::vector destroy ${path}::yvec + blt::vector destroy ${path}::zvec +} + +#> bpf blt::graph +#. -width 300 -height 200 -bg lightblue -plotbackground lightgrey -halo 10 +#. #domain 1000. + +#@ vis + +# LATER reconsider calling standard procs implicitly, followed by scripts +::toxy::bpf::atVis .- + +#@ new + +# LATER reconsider replacing this with global .- (using ::${path} in procs) +namespace eval ::toxy::bpf::.- { +# this might be implicit + set target .| + +# array interface seems broken inside namespaces +# (cf sf.net/projects/blt bug 651993) + blt::vector create xvec -variable "" + blt::vector create yvec -variable "" + blt::vector create zvec -variable "" + set locked 0 + set xmax .#domain + set ymin 0.0 + set ymax 1.0 + set idrag -1 + set mindrag 0 + set maxdrag $xmax + set xdrag 0 + set ydrag 0 +} + +::toxy::bpf::atNew .- + +#@ free + +::toxy::bpf::atFree .- + +#@ data + +::toxy::bpf::atData .- .#args diff --git a/test/toxy/listbox-test.pd b/test/toxy/listbox-test.pd index 751fb58..99bf2e8 100644 --- a/test/toxy/listbox-test.pd +++ b/test/toxy/listbox-test.pd @@ -12,7 +12,7 @@ white @bang ::toxy::lbcommand .- .|; #X msg 33 179 bang; #X msg 20 57 tot proc ::toxy::lbcommand .(path target.) .(if .([$path curselection] != "".) .(pd [concat $target _cb set [$path get [$path -curselection]] .`.:].).) \, ini if .([.- size] == 0.) .(foreach fn +curselection]] .`.:].).) \, @vis if .([.- size] == 0.) .(foreach fn [lsort [glob *]] .(.- insert end $fn.) .: bind .- <Double-Button-1> .(::toxy::lbcommand .- .|.).) \, @bang ::toxy::lbcommand .- .|; #X connect 1 0 5 0; diff --git a/test/toxy/popcustom-test.pd b/test/toxy/popcustom-test.pd index 7f49162..2589bfe 100644 --- a/test/toxy/popcustom-test.pd +++ b/test/toxy/popcustom-test.pd @@ -12,7 +12,7 @@ yellow -width 5 -text one @float if .(.#1 >= 1.) .(.-.pop invoke .#1.) #X obj 23 12 loadbang; #X obj 96 110 widget pop1 p1; #X obj 188 110 widget pop2 p2; -#X msg 23 41 ini ::toxy::popup .- .| rpop [list one two three four five] +#X msg 23 41 set @vis ::toxy::popup .- .| rpop [list one two three four five] -bg green -activebackground yellow .: destroy .^.m .: .^.scrollvert configure -width 0 .: .^.scrollhort configure -width 0 .: .^.c configure -bg black; diff --git a/test/toxy/setup.wid b/test/toxy/setup.wid index ce498c4..05e0164 100644 --- a/test/toxy/setup.wid +++ b/test/toxy/setup.wid @@ -1,4 +1,4 @@ -package provide toxywidgets 0.1.0.16 +package provide toxywidgets 0.1.0.17 # LATER keep standard widget setup in a .tcl file (transfered into a .wiq), and # glue separate .wid files with standard widget definitions into another .wiq @@ -10,15 +10,24 @@ package provide toxywidgets 0.1.0.16 # LATER ask for adding something of the sort to pd.tk: bind Canvas <1> {+focus %W} -# In order to keep the state after our canvas has been destroyed -# (i.e. our subpatch closed) -- use 'store' and 'restore' handlers, -# if defined, otherwise try setting -variable and -textvariable traces. +# FIXME args +proc ::toxy::package_require {pkg dll} { + if {[catch {package require $pkg} res] == 0} { + puts stderr "using package $pkg $res" + } elseif {[catch {load $dll $pkg}] != 0} { + puts stderr "ERROR: missing package $pkg ($res)" + } +} + +# FIXME this should be explicitly requested +# In order to keep the state after tk canvas has been destroyed +# try setting -variable and -textvariable traces proc ::toxy::item_dotrace {target varname ndxname op} { if {[catch {set v [set $varname]} res] == 0} { if {$v != [set $varname.last]} { # FIXME activate this on demand (for explicit traces) -# pd $target.rp _value $v \; +# pd $target.rp _data $v \; set $varname.last $v } } else { puts stderr [concat failed ::toxy::item_dotrace: $res] } @@ -100,10 +109,16 @@ proc ::toxy::item_visconfig {path target name varname cvpath px py} { if {$failed} { error [concat in $path config: $res] } } + if {[info exists ::toxy::longnewhook]} { + set failed [catch {eval $::toxy::longnewhook} res] + unset ::toxy::longnewhook + if {$failed} { error [concat in ::toxy::longnewhook: $res] } + } + $cvpath create window $px $py \ -anchor nw -window $path -tags [concat toxy$name $target] -# FIXME +# FIXME use ${name}::explicittrace if {[info exists ::toxy::storethispath]} { # FIXME explicit traces set needtraces 0 @@ -129,15 +144,15 @@ proc ::toxy::item_visconfig {path target name varname cvpath px py} { set failed [catch {::toxy::master $path $cvpath $target} res] if {$failed} { error [concat in ::toxy::master: $res] } - if {[info exists ::toxy::typeinit]} { - set failed [catch {eval $::toxy::typeinit} res] - unset ::toxy::typeinit - if {$failed} { error [concat in ::toxy::typeinit: $res] } + if {[info exists ::toxy::longvishook]} { + set failed [catch {eval $::toxy::longvishook} res] + unset ::toxy::longvishook + if {$failed} { error [concat in ::toxy::longvishook: $res] } } - if {[info exists ::toxy::iteminit]} { - set failed [catch {eval $::toxy::iteminit} res] - unset ::toxy::iteminit - if {$failed} { error [concat in ::toxy::iteminit: $res] } + if {[info exists ::toxy::shortvishook]} { + set failed [catch {eval $::toxy::shortvishook} res] + unset ::toxy::shortvishook + if {$failed} { error [concat in ::toxy::shortvishook: $res] } } ::toxy::item_getconfig $path $target @@ -220,7 +235,7 @@ proc ::toxy::master {path cvpath target} { } } -# to be called explicitly from type initializer, LATER rethink +# to be called explicitly from vis proc, LATER rethink proc ::toxy::subwidget {path parent cvpath target} { bind $path <ButtonRelease> "::toxy::master_release $target $cvpath %X %Y %b" bind $path <1> "::toxy::item_click $target $cvpath %X %Y %b 0" @@ -305,6 +320,7 @@ set ::toxy::scale_isactive 1 #. -bg pink -font .(helvetica 24.) -width 16 #. @symbol .- delete 0 end .: .- insert 0 .#1 +#@ vis bind .- <Return> {eval .<[.- get].>; focus .^.c} #> popup menubutton @@ -315,4 +331,5 @@ bind .- <Return> {eval .<[.- get].>; focus .^.c} #. #items test #. #iprops "-bg" purple "-fg" white "-activebackground" magenta "-borderwidth" 3 +#@ vis ::toxy::popup .- .| . [concat .#items] .#iprops diff --git a/test/toxy/testmess.wid b/test/toxy/testmess.wid index 0481e2f..85894be 100644 --- a/test/toxy/testmess.wid +++ b/test/toxy/testmess.wid @@ -42,6 +42,3 @@ puts "another initializer part added from \"#@ vis\" block" #@ free puts "\ndestructor: evaluated once, after Pd object destruction" puts "(Tk widget should be already gone)" - -#@ ini -puts "yet another initializer part added from \"#@ ini\" block" diff --git a/test/toxy/tow-test.pd b/test/toxy/tow-test.pd index d0a8c95..cf6ece4 100644 --- a/test/toxy/tow-test.pd +++ b/test/toxy/tow-test.pd @@ -42,7 +42,7 @@ #X msg 63 183 -bg orange; #X msg 50 153 -bg brown; #X obj 136 21 loadbang; -#X msg 136 56 ini .^.c configure -bg darkgreen; +#X msg 136 56 set @vis .^.c configure -bg darkgreen; #X connect 0 0 5 0; #X connect 2 0 4 0; #X connect 4 0 3 0; diff --git a/toxy/Makefile.objects b/toxy/Makefile.objects index 1ac718e..8139856 100644 --- a/toxy/Makefile.objects +++ b/toxy/Makefile.objects @@ -43,4 +43,4 @@ hammer/file.o \ common/props.o \ toxy/scriptlet.o -WIDGET_PRIVATEOBJECTS = widgettype.o +WIDGET_PRIVATEOBJECTS = widgettype.o widgethandlers.o diff --git a/toxy/build_counter b/toxy/build_counter index 8e0975b..53f4151 100644 --- a/toxy/build_counter +++ b/toxy/build_counter @@ -1,7 +1,7 @@ #define TOXY_VERSION "0.1" #define TOXY_RELEASE "alpha" -#define TOXY_BUILD 16 +#define TOXY_BUILD 17 #if 0 -TOXY_SNAPSHOT = 0.1-alpha16 +TOXY_SNAPSHOT = 0.1-alpha17 #endif diff --git a/toxy/notes.txt b/toxy/notes.txt index 775bbcd..120f0db 100644 --- a/toxy/notes.txt +++ b/toxy/notes.txt @@ -1,13 +1,35 @@ TODO for toxy * widget - . cached handlers + . push long message handlers if defined, instead of short + . widgetcontainer: woc and wiw-list . better megawidgets . editor: handle semicolons (need to revisit resolution rules) - . editor: differentiate argument keys from casual #strings (color-names) + . editor: break editorhook into separate properties, add them in single mode + . find a way for "package require" to work out-of-the-box on windows * tow: canvas-wide and type-on-canvas-wide broadcasting DONE for toxy +alpha17 + * widget: + . first sketch of an editor widget (bpf), introducing a basic set of rules: + - instance data kept in its own namespace + - gui sends '_data' (replaces '_value') requests to pd, specifying one + of the standard submessages: add, delete, set, get + - pd uses the new special handler for replying: @data + (for the time being, there is only an idle loop between the two sides) + . maintaining a scriptlet collection, which mirrors type and instance + handler properties (including specials: @vis, @new, @free and @data) + . lookup in the mirror for faster and more robust handling of messages + . '@ini' section and 'ini' message removed, after being unified as the + @vis special handler (use 'set @vis' message form for passing options) + . all special handlers support short definitions (inside #. comments) + and long definitions (tagged with #@ comments), however only short + ones may be overriden by instance definitions + . long message handlers are stored, but not used yet + . .wid file header may include requirements (base widget definitions) + . fixed: patch's directory handling in 'redefine' + alpha16 * widget: . editor for options, handlers and arguments made more or less functional diff --git a/toxy/widget.c b/toxy/widget.c index da4a78f..ce6916b 100644 --- a/toxy/widget.c +++ b/toxy/widget.c @@ -14,14 +14,14 @@ #include "hammer/file.h" #include "common/props.h" #include "toxy/scriptlet.h" -#include "widgettype.h" +#include "widget.h" #include "build_counter" /* our proxy of the text_class (not in the API), LATER do not cheat */ static t_class *makeshift_class; #ifdef KRZYSZCZ -//#define WIDGET_DEBUG +#define WIDGET_DEBUG //#define TOW_DEBUG //#define WIDGET_PROFILE #endif @@ -40,18 +40,6 @@ typedef struct _widgetentry struct _widgetentry *we_next; } t_widgetentry; -/* move to widgettype.c&h */ -typedef struct _widgethandlers -{ - t_scriptlet *wh_initializer; - t_scriptlet *wh_new; - t_scriptlet *wh_free; - t_scriptlet *wh_bang; - t_scriptlet *wh_float; - t_scriptlet *wh_symbol; - /* ... (varsized vector) */ -} t_widgethandlers; - typedef struct _widget { t_object x_ob; @@ -72,8 +60,7 @@ typedef struct _widget t_props *x_diffoptions; /* type options minus instance options */ t_props *x_diffhandlers; /* same for handlers */ t_props *x_diffarguments; /* same for arguments */ - t_widgethandlers x_cache; /* actual handlers */ - t_scriptlet *x_iniscript; /* instance initializer */ + t_widgethandlers *x_hooks; /* actual handlers (short definitions) */ t_scriptlet *x_optscript; /* option scriptlet */ t_scriptlet *x_auxscript; /* auxiliary scriptlet */ t_scriptlet *x_transient; /* output buffer */ @@ -86,6 +73,7 @@ typedef struct _widget int x_selected; int x_update; /* see widget_update() */ int x_vised; + int x_constructed; t_clock *x_transclock; t_towentry *x_towlist; } t_widget; @@ -112,11 +100,14 @@ static t_tow *widget_towlist = 0; static t_symbol *widgetps_mouse; static t_symbol *widgetps_motion; -static t_symbol *widgetps_atbang; -static t_symbol *widgetps_atfloat; -static t_symbol *widgetps_atsymbol; -static t_symbol *widgetps_atstore; -static t_symbol *widgetps_atrestore; +static t_symbol *widgetps_vis; +static t_symbol *widgetps_new; +static t_symbol *widgetps_free; +static t_symbol *widgetps_data; +static t_symbol *widgetps_add; +static t_symbol *widgetps_delete; +static t_symbol *widgetps_set; +static t_symbol *widgetps_get; #ifdef WIDGET_PROFILE static double widgetprofile_lasttime; @@ -361,49 +352,68 @@ static void widget_pushoptions(t_widget *x, int doit) loudbug_bug("widget_pushoptions"); } -static void widget_pushinits(t_widget *x) +static void widget_pushonehook(t_widget *x, t_scriptlet *sp, char *vname) +{ + if (scriptlet_evaluate(sp, x->x_transient, 0, 0, 0, x->x_xargs)) + scriptlet_vpush(x->x_transient, vname); + else if (!scriptlet_isempty(sp)) + loudbug_bug("widget_pushonehook (%s)", vname); +} + +static void widget_pushvishooks(t_widget *x) { if (widgettype_isdefined(x->x_typedef)) { - int sz; - if (widgettype_ievaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_xargs)) - scriptlet_vpush(x->x_transient, "typeinit"); - else if (*widgettype_getinitializer(x->x_typedef, &sz) && sz > 0) - loudbug_bug("widget_pushinits (type)"); + t_widgethandlers *wh = widgettype_getscripts(x->x_typedef); + widget_pushonehook(x, widgethandlers_getvis(wh), "longvishook"); } - if (scriptlet_evaluate(x->x_iniscript, x->x_transient, 0, 0, 0, x->x_xargs)) - scriptlet_vpush(x->x_transient, "iteminit"); - else if (!scriptlet_isempty(x->x_iniscript)) - loudbug_bug("widget_pushinits (instance)"); + widget_pushonehook(x, widgethandlers_getvis(x->x_hooks), "shortvishook"); } -static void widget_pushconstructors(t_widget *x) +static void widget_pushnewhooks(t_widget *x) { /* LATER master constructor */ if (widgettype_isdefined(x->x_typedef)) { - int sz; - if (widgettype_cevaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_xargs)) - scriptlet_push(x->x_transient); - else if (*widgettype_getconstructor(x->x_typedef, &sz) && sz > 0) - loudbug_bug("widget_pushconstructors (type)"); + t_widgethandlers *wh = widgettype_getscripts(x->x_typedef); + widget_pushonehook(x, widgethandlers_getnew(wh), "longnewhook"); } + widget_pushonehook(x, widgethandlers_getnew(x->x_hooks), "shortnewhook"); } -static void widget_pushdestructors(t_widget *x) +static void widget_pushfreehooks(t_widget *x) { /* LATER master destructor */ if (widgettype_isdefined(x->x_typedef)) { - int sz; - if (widgettype_devaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_xargs)) + t_widgethandlers *wh = widgettype_getscripts(x->x_typedef); + widget_pushonehook(x, widgethandlers_getfree(wh), "longfreehook"); + } + widget_pushonehook(x, widgethandlers_getfree(x->x_hooks), "shortfreehook"); +} + +static void widget_pushdatahooks(t_widget *x, int ac, t_atom *av) +{ + t_scriptlet *sp; + WIDGETPROFILE_HANDLER_ENTER; + if (!widgettype_isdefined(x->x_typedef) + || !(sp = widgethandlers_getdata(widgettype_getscripts(x->x_typedef))) + || scriptlet_isempty(sp)) + sp = widgethandlers_getdata(x->x_hooks); + if (sp) + { + WIDGETPROFILE_HANDLER_EVAL; + if (scriptlet_evaluate(sp, x->x_transient, 0, ac, av, x->x_xargs)) + { + WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); - else if (*widgettype_getdestructor(x->x_typedef, &sz) && sz > 0) - loudbug_bug("widget_pushdestructors (type)"); + } + else if (!scriptlet_isempty(sp)) + loudbug_bug("widget_pushdatahooks (%s)", + (sp == widgethandlers_getdata(x->x_hooks) ? + "short" : "long")); } + WIDGETPROFILE_HANDLER_QUIT; } static void widget_getconfig(t_widget *x) @@ -428,7 +438,12 @@ static void widget_vis(t_gobj *z, t_glist *glist, int vis) rtext_new(glist, t, glist->gl_editor->e_rtext, 0); #endif widget_pushoptions(x, 0); - widget_pushinits(x); + widget_pushvishooks(x); + if (!x->x_constructed) + { + widget_pushnewhooks(x); + x->x_constructed = 1; + } sys_vgui("::toxy::item_vis %s %s %s %s %s %s %g %g\n", x->x_tkclass->s_name, mypathname, x->x_cbtarget->s_name, x->x_name->s_name, @@ -566,9 +581,12 @@ static void widget_update(t_widget *x, t_props *op) { props_diff(x->x_diffhandlers, widgettype_gethandlers(x->x_typedef), x->x_handlers); - /* LATER cache handlers. + /* This is the only point where mirroring of handlers is performed. We get here both during construction, and after any change - in our handlers -- the cache never stales. */ + in our handlers -- the mirror never stales. */ + widgethandlers_reset(x->x_hooks); + widgethandlers_fill(x->x_hooks, x->x_diffhandlers); + widgethandlers_fill(x->x_hooks, x->x_handlers); } else if (op == x->x_arguments) { @@ -646,128 +664,88 @@ static void widget_anything(t_widget *x, t_symbol *s, int ac, t_atom *av) } else { - /* LATER cache this */ - int hlen; - t_atom *hp; - t_symbol *sel; - char buf[MAXPDSTRING]; + /* FIXME use long defs too, cf widget_pushdatahooks() */ + t_scriptlet *sp; WIDGETPROFILE_HANDLER_ENTER; - buf[0] = '@'; - strcpy(buf + 1, s->s_name); - sel = gensym(buf); - if (((hp = props_getone(x->x_handlers, sel, &hlen)) || - (hp = props_getone(widgettype_gethandlers(x->x_typedef), - sel, &hlen))) - && hlen > 1) + if (sp = widgethandlers_getother(x->x_hooks, s)) { WIDGETPROFILE_HANDLER_EVAL; - scriptlet_reset(x->x_auxscript); - scriptlet_add(x->x_auxscript, 0, 0, hlen - 1, hp + 1); - if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - ac, av, x->x_xargs)) + if (scriptlet_evaluate(sp, x->x_transient, + 1, ac, av, x->x_xargs)) { WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); } + else if (!scriptlet_isempty(sp)) + loudbug_bug("widget_anything"); } - else loud_nomethod((t_pd *)x, s); + else if (s == widgetps_vis || s == widgetps_new || + s == widgetps_free || s == widgetps_data) + loud_error((t_pd *)x, + "explicit call of the special handler \"%s\"", + s->s_name); + else + loud_nomethod((t_pd *)x, s); WIDGETPROFILE_HANDLER_QUIT; } } } -/* LATER cache this */ +/* FIXME use long defs too, cf widget_pushdatahooks() */ static void widget_bang(t_widget *x) { - int ac; - t_atom *av; + t_scriptlet *sp; WIDGETPROFILE_HANDLER_ENTER; - if ((av = props_getone(x->x_handlers, widgetps_atbang, &ac)) || - (av = props_getone(widgettype_gethandlers(x->x_typedef), - widgetps_atbang, &ac))) + sp = widgethandlers_getbang(x->x_hooks); + WIDGETPROFILE_HANDLER_EVAL; + if (scriptlet_evaluate(sp, x->x_transient, 1, 0, 0, x->x_xargs)) { - if (ac > 1) - { - WIDGETPROFILE_HANDLER_EVAL; - scriptlet_reset(x->x_transient); - scriptlet_add(x->x_transient, 1, 1, ac - 1, av + 1); - WIDGETPROFILE_HANDLER_PUSH; - scriptlet_push(x->x_transient); - } + WIDGETPROFILE_HANDLER_PUSH; + scriptlet_push(x->x_transient); } + else if (!scriptlet_isempty(sp)) + loudbug_bug("widget_bang"); WIDGETPROFILE_HANDLER_QUIT; } -/* LATER cache this */ +/* FIXME use long defs too, cf widget_pushdatahooks() */ static void widget_float(t_widget *x, t_float f) { - int ac; - t_atom *av; + t_scriptlet *sp; + t_atom at; WIDGETPROFILE_HANDLER_ENTER; - if ((av = props_getone(x->x_handlers, widgetps_atfloat, &ac)) || - (av = props_getone(widgettype_gethandlers(x->x_typedef), - widgetps_atfloat, &ac))) + sp = widgethandlers_getfloat(x->x_hooks); + WIDGETPROFILE_HANDLER_EVAL; + SETFLOAT(&at, f); + if (scriptlet_evaluate(sp, x->x_transient, 1, 1, &at, x->x_xargs)) { - if (ac > 1) - { - t_atom at; - WIDGETPROFILE_HANDLER_EVAL; - SETFLOAT(&at, f); - scriptlet_reset(x->x_auxscript); - scriptlet_add(x->x_auxscript, 0, 0, ac - 1, av + 1); - if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - 1, &at, x->x_xargs)) - { - WIDGETPROFILE_HANDLER_PUSH; - scriptlet_push(x->x_transient); - } - } + WIDGETPROFILE_HANDLER_PUSH; + scriptlet_push(x->x_transient); } + else if (!scriptlet_isempty(sp)) + loudbug_bug("widget_float"); WIDGETPROFILE_HANDLER_QUIT; } -/* LATER cache this */ +/* FIXME use long defs too, cf widget_pushdatahooks() */ static void widget_symbol(t_widget *x, t_symbol *s) { - int ac; - t_atom *av; + t_scriptlet *sp; + t_atom at; WIDGETPROFILE_HANDLER_ENTER; - if ((av = props_getone(x->x_handlers, widgetps_atsymbol, &ac)) || - (av = props_getone(widgettype_gethandlers(x->x_typedef), - widgetps_atsymbol, &ac))) + sp = widgethandlers_getsymbol(x->x_hooks); + WIDGETPROFILE_HANDLER_EVAL; + SETSYMBOL(&at, s); + if (scriptlet_evaluate(sp, x->x_transient, 1, 1, &at, x->x_xargs)) { - if (ac > 1) - { - t_atom at; - WIDGETPROFILE_HANDLER_EVAL; - SETSYMBOL(&at, s); - scriptlet_reset(x->x_auxscript); - scriptlet_add(x->x_auxscript, 0, 0, ac - 1, av + 1); - if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - 1, &at, x->x_xargs)) - { - WIDGETPROFILE_HANDLER_PUSH; - scriptlet_push(x->x_transient); - } - } + WIDGETPROFILE_HANDLER_PUSH; + scriptlet_push(x->x_transient); } + else if (!scriptlet_isempty(sp)) + loudbug_bug("widget_symbol"); WIDGETPROFILE_HANDLER_QUIT; } -static void widget_store(t_widget *x, t_symbol *s) -{ - if (s == &s_) - s = x->x_varname; - /* FIXME */ -} - -static void widget_restore(t_widget *x, t_symbol *s) -{ - if (s == &s_) - s = x->x_varname; - /* FIXME */ -} - static void widget_set(t_widget *x, t_symbol *s, int ac, t_atom *av) { t_symbol *prp; @@ -816,14 +794,6 @@ static void widget_remove(t_widget *x, t_symbol *s) } } -static void widget_ini(t_widget *x, t_symbol *s, int ac, t_atom *av) -{ - if (ac) - { - scriptlet_reset(x->x_iniscript); - scriptlet_add(x->x_iniscript, 0, 0, ac, av); - } -} static void widget_tot(t_widget *x, t_symbol *s, int ac, t_atom *av) { if (ac) @@ -849,11 +819,12 @@ static int widget_resettype(t_widget *x, t_widgettype *wt) if (!wt || /* LATER rethink, cf widgettype_reload() */ wt == x->x_typedef) { + widget_pushfreehooks(x); if (!(x->x_tkclass = widgettype_tkclass(x->x_typedef))) x->x_tkclass = x->x_type; x->x_update = WIDGET_REVIS; widget_update(x, x->x_arguments); - widget_pushconstructors(x); + widget_pushnewhooks(x); widget_update(x, x->x_handlers); widget_update(x, x->x_options); return (1); @@ -867,7 +838,7 @@ static int widget_resettype(t_widget *x, t_widgettype *wt) static void widget_redefine(t_widget *x) { - widget_resettype(x, widgettype_reload(x->x_type)); + widget_resettype(x, widgettype_reload(x->x_type, x->x_glist)); } static void widget_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) @@ -903,14 +874,37 @@ static void widget__config(t_widget *x, t_symbol *target, t_symbol *bg, canvas_fixlinesfor(glist_getcanvas(x->x_glist), (t_text *)x); /* FIXME */ } -static void widget__value(t_widget *x, t_symbol *s, int ac, t_atom *av) +/* FIXME this is only a template */ +static void widget__data(t_widget *x, t_symbol *s, int ac, t_atom *av) { #ifdef WIDGET_DEBUG - loudbug_startpost("value:"); + loudbug_startpost("_data:"); loudbug_postatom(ac, av); loudbug_endpost(); #endif - /* FIXME */ + if (ac && av->a_type == A_SYMBOL) + { + s = av->a_w.w_symbol; + if (s == widgetps_add) + { + widget_pushdatahooks(x, ac, av); + } + else if (s == widgetps_delete) + { + widget_pushdatahooks(x, ac, av); + } + else if (s == widgetps_set) + { + widget_pushdatahooks(x, ac, av); + } + else if (s == widgetps_get) + { + widget_pushdatahooks(x, ac, av); + } + else loud_error((t_pd *)x, + "invalid \"_data\" subcommand \"%s\"", s->s_name); + } + else loud_error((t_pd *)x, "missing \"_data\" subcommand"); } static void widget__callback(t_widget *x, t_symbol *s, int ac, t_atom *av) @@ -1026,6 +1020,7 @@ static void widgetbug_postprops(char *msg, t_props *pp) static void widget_debug(t_widget *x) { + t_widgethandlers *wh = widgettype_getscripts(x->x_typedef); t_symbol *pn = widget_getcvpathname(x, 0); t_symbol *mn = widget_getmypathname(x, 0); int sz, i, nopt; @@ -1060,15 +1055,20 @@ static void widget_debug(t_widget *x) loudbug_post("transient buffer (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); bp = scriptlet_getcontents(x->x_optscript, &sz); loudbug_post("option buffer (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); - bp = widgettype_getconstructor(x->x_typedef, &sz); - loudbug_post("type constructor (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); - bp = widgettype_getdestructor(x->x_typedef, &sz); - loudbug_post("type destructor (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); - bp = widgettype_getinitializer(x->x_typedef, &sz); - loudbug_post("type initializer (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); - bp = scriptlet_getcontents(x->x_iniscript, &sz); - loudbug_post("instance initializer (size %d):\n\"%s\"", + + bp = scriptlet_getcontents(widgethandlers_getnew(wh), &sz); + loudbug_post("long newhook (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); + bp = scriptlet_getcontents(widgethandlers_getfree(wh), &sz); + loudbug_post("long freehook (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); + bp = scriptlet_getcontents(widgethandlers_getdata(wh), &sz); + loudbug_post("long datahook (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); + + bp = scriptlet_getcontents(widgethandlers_getvis(wh), &sz); + loudbug_post("long vishook (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); + bp = scriptlet_getcontents(widgethandlers_getvis(x->x_hooks), &sz); + loudbug_post("short vishook (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); + bp = masterwidget_getcontents(&sz); loudbug_post("setup definitions (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); @@ -1089,13 +1089,13 @@ static void gui_unbind(t_pd *x, t_symbol *s) static void widget_free(t_widget *x) { widget_novis(x); - widget_pushdestructors(x); + widget_pushfreehooks(x); gui_unbind((t_pd *)x, x->x_cbtarget); gui_unbind((t_pd *)x, x->x_rptarget); + widgethandlers_free(x->x_hooks); props_freeall(x->x_options); props_freeall(x->x_xargs); props_freeall(x->x_diffoptions); - scriptlet_free(x->x_iniscript); scriptlet_free(x->x_optscript); scriptlet_free(x->x_auxscript); scriptlet_free(x->x_transient); @@ -1140,7 +1140,7 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) pd_bind((t_pd *)x, x->x_rptarget = gensym(buf)); x->x_glist = canvas_getcurrent(); - x->x_typedef = widgettype_get(x->x_type); + x->x_typedef = widgettype_get(x->x_type, 0, 0, x->x_glist); if (!(x->x_tkclass = widgettype_tkclass(x->x_typedef))) x->x_tkclass = x->x_type; @@ -1151,14 +1151,10 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) sprintf(buf, "::toxy::v%x", (int)x); x->x_varname = gensym(buf); - x->x_iniscript = scriptlet_new((t_pd *)x, x->x_rptarget, x->x_cbtarget, - x->x_name, x->x_glist, widget_cvhook); - x->x_optscript = scriptlet_new((t_pd *)x, x->x_rptarget, x->x_cbtarget, - x->x_name, x->x_glist, widget_cvhook); x->x_auxscript = scriptlet_new((t_pd *)x, x->x_rptarget, x->x_cbtarget, x->x_name, x->x_glist, widget_cvhook); - x->x_transient = scriptlet_new((t_pd *)x, x->x_rptarget, x->x_cbtarget, - x->x_name, x->x_glist, widget_cvhook); + x->x_transient = scriptlet_newalike(x->x_auxscript); + x->x_optscript = scriptlet_newalike(x->x_auxscript); x->x_options = props_new((t_pd *)x, "option", "-", 0, 0); x->x_handlers = props_new((t_pd *)x, "handler", "@", x->x_options, 0); @@ -1170,6 +1166,8 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) x->x_diffarguments = props_new((t_pd *)x, "argument", "#", x->x_diffoptions, 0); + x->x_hooks = widgethandlers_new(x->x_auxscript); + outlet_new((t_object *)x, &s_anything); /* LATER consider estimating these, based on widget class and options. The default used to be 50x50, which confused people wanting widgets @@ -1186,7 +1184,7 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) x->x_vised = 0; widget_attach(x); widget_addmessage(x, 0, 0, ac, av); - widget_pushconstructors(x); + x->x_constructed = 0; return (x); } @@ -1349,7 +1347,7 @@ static void tow_anything(t_tow *x, t_symbol *s, int ac, t_atom *av) static void tow_redefine(t_tow *x) { - t_widgettype *wt = widgettype_reload(x->x_type); + t_widgettype *wt = widgettype_reload(x->x_type, x->x_glist); t_widgetentry *we; for (we = x->x_widgetlist; we; we = we->we_next) if (!widget_resettype(we->we_widget, wt)) @@ -1495,11 +1493,14 @@ void widget_setup(void) TOXY_VERSION, loud_ordinal(TOXY_BUILD), TOXY_RELEASE); widgetps_mouse = gensym("mouse"); widgetps_motion = gensym("motion"); - widgetps_atbang = gensym("@bang"); - widgetps_atfloat = gensym("@float"); - widgetps_atsymbol = gensym("@symbol"); - widgetps_atstore = gensym("@store"); - widgetps_atrestore = gensym("@restore"); + widgetps_vis = gensym("vis"); + widgetps_new = gensym("new"); + widgetps_free = gensym("free"); + widgetps_data = gensym("data"); + widgetps_add = gensym("add"); + widgetps_delete = gensym("delete"); + widgetps_set = gensym("set"); + widgetps_get = gensym("get"); widgettype_setup(); widget_class = class_new(gensym("widget"), (t_newmethod)widget_new, @@ -1512,16 +1513,10 @@ void widget_setup(void) class_addfloat(widget_class, widget_float); class_addsymbol(widget_class, widget_symbol); class_addanything(widget_class, widget_anything); - class_addmethod(widget_class, (t_method)widget_store, - gensym("store"), A_DEFSYMBOL, 0); - class_addmethod(widget_class, (t_method)widget_restore, - gensym("restore"), A_DEFSYMBOL, 0); class_addmethod(widget_class, (t_method)widget_set, gensym("set"), A_GIMME, 0); class_addmethod(widget_class, (t_method)widget_remove, gensym("remove"), A_SYMBOL, 0); - class_addmethod(widget_class, (t_method)widget_ini, - gensym("ini"), A_GIMME, 0); class_addmethod(widget_class, (t_method)widget_tot, gensym("tot"), A_GIMME, 0); class_addmethod(widget_class, (t_method)widget_refresh, @@ -1533,8 +1528,8 @@ void widget_setup(void) class_addmethod(widget_class, (t_method)widget__config, gensym("_config"), A_SYMBOL, A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, 0); - class_addmethod(widget_class, (t_method)widget__value, - gensym("_value"), A_GIMME, 0); + class_addmethod(widget_class, (t_method)widget__data, + gensym("_data"), A_GIMME, 0); class_addmethod(widget_class, (t_method)widget__callback, gensym("_cb"), A_GIMME, 0); class_addmethod(widget_class, (t_method)widget__inout, diff --git a/toxy/widget.h b/toxy/widget.h new file mode 100644 index 0000000..7481bbc --- /dev/null +++ b/toxy/widget.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2003-2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __WIDGET_H__ +#define __WIDGET_H__ + +EXTERN_STRUCT _widgettype; +#define t_widgettype struct _widgettype + +EXTERN_STRUCT _masterwidget; +#define t_masterwidget struct _masterwidget + +EXTERN_STRUCT _widgethandlers; +#define t_widgethandlers struct _widgethandlers + +t_widgettype *widgettype_find(t_symbol *s); +t_widgettype *widgettype_get(t_symbol *s, char *ver, char *opt, t_glist *glist); +t_widgettype *widgettype_reload(t_symbol *s, t_glist *glist); +int widgettype_isdefined(t_widgettype *wt); +t_symbol *widgettype_tkclass(t_widgettype *wt); +t_props *widgettype_getoptions(t_widgettype *wt); +t_props *widgettype_gethandlers(t_widgettype *wt); +t_props *widgettype_getarguments(t_widgettype *wt); +t_widgethandlers *widgettype_getscripts(t_widgettype *wt); +char *widgettype_propname(t_symbol *s); +void widgettype_setup(void); + +char *masterwidget_getcontents(int *szp); +void masterwidget_validate(void); + +t_widgethandlers *widgethandlers_new(t_scriptlet *generator); +void widgethandlers_free(t_widgethandlers *wh); +void widgethandlers_reset(t_widgethandlers *wh); +void widgethandlers_fill(t_widgethandlers *wh, t_props *pp); +t_scriptlet *widgethandlers_getvis(t_widgethandlers *wh); +t_scriptlet *widgethandlers_getnew(t_widgethandlers *wh); +t_scriptlet *widgethandlers_getfree(t_widgethandlers *wh); +t_scriptlet *widgethandlers_getdata(t_widgethandlers *wh); +t_scriptlet *widgethandlers_getbang(t_widgethandlers *wh); +t_scriptlet *widgethandlers_getfloat(t_widgethandlers *wh); +t_scriptlet *widgethandlers_getsymbol(t_widgethandlers *wh); +t_scriptlet *widgethandlers_getother(t_widgethandlers *wh, t_symbol *selector); +t_scriptlet *widgethandlers_takeany(t_widgethandlers *wh, t_symbol *selector); + +#endif diff --git a/toxy/widgethandlers.c b/toxy/widgethandlers.c new file mode 100644 index 0000000..f95ffba --- /dev/null +++ b/toxy/widgethandlers.c @@ -0,0 +1,211 @@ +/* Copyright (c) 2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include "m_pd.h" +#include "common/loud.h" +#include "common/props.h" +#include "toxy/scriptlet.h" +#include "widget.h" + +#ifdef KRZYSZCZ +//#define WIDGETHANDLERS_DEBUG +#endif + +typedef struct _widgetscript +{ + t_symbol *ws_selector; + t_scriptlet *ws_script; + struct _widgetscript *ws_next; +} t_widgetscript; + +struct _widgethandlers +{ + t_scriptlet *wh_vis; + t_scriptlet *wh_new; + t_scriptlet *wh_free; + t_scriptlet *wh_data; + t_scriptlet *wh_bang; + t_scriptlet *wh_float; + t_scriptlet *wh_symbol; + t_widgetscript *wh_others; +}; + +static t_symbol *widgetps_vis = 0; +static t_symbol *widgetps_new; +static t_symbol *widgetps_free; +static t_symbol *widgetps_data; + +t_widgethandlers *widgethandlers_new(t_scriptlet *generator) +{ + t_widgethandlers *wh = getbytes(sizeof(*wh)); + if (!widgetps_vis) + { + widgetps_vis = gensym("vis"); + widgetps_new = gensym("new"); + widgetps_free = gensym("free"); + widgetps_data = gensym("data"); + } + wh->wh_vis = scriptlet_newalike(generator); + wh->wh_new = scriptlet_newalike(generator); + wh->wh_free = scriptlet_newalike(generator); + wh->wh_data = scriptlet_newalike(generator); + wh->wh_bang = scriptlet_newalike(generator); + wh->wh_float = scriptlet_newalike(generator); + wh->wh_symbol = scriptlet_newalike(generator); + wh->wh_others = 0; + return (wh); +} + +void widgethandlers_free(t_widgethandlers *wh) +{ + t_widgetscript *ws, *wsnext = wh->wh_others; + scriptlet_free(wh->wh_vis); + scriptlet_free(wh->wh_new); + scriptlet_free(wh->wh_free); + scriptlet_free(wh->wh_data); + scriptlet_free(wh->wh_bang); + scriptlet_free(wh->wh_float); + scriptlet_free(wh->wh_symbol); + while (ws = wsnext) + { + wsnext = ws->ws_next; + scriptlet_free(ws->ws_script); + freebytes(ws, sizeof(*ws)); + } + freebytes(wh, sizeof(*wh)); +} + +void widgethandlers_reset(t_widgethandlers *wh) +{ + t_widgetscript *ws = wh->wh_others; + scriptlet_reset(wh->wh_vis); + scriptlet_reset(wh->wh_new); + scriptlet_reset(wh->wh_free); + scriptlet_reset(wh->wh_data); + scriptlet_reset(wh->wh_bang); + scriptlet_reset(wh->wh_float); + scriptlet_reset(wh->wh_symbol); + for (ws = wh->wh_others; ws; ws = ws->ws_next) + scriptlet_reset(ws->ws_script); +} + +static t_widgetscript *widgethandlers_takeotherscript(t_widgethandlers *wh, + t_symbol *selector) +{ + t_widgetscript *ws; + for (ws = wh->wh_others; ws; ws = ws->ws_next) + if (ws->ws_selector == selector) + break; + if (!ws) + { + ws = getbytes(sizeof(*ws)); + ws->ws_selector = selector; + ws->ws_script = scriptlet_newalike(wh->wh_vis); + ws->ws_next = wh->wh_others; + wh->wh_others = ws; + } + return (ws); +} + +t_scriptlet *widgethandlers_takeany(t_widgethandlers *wh, t_symbol *selector) +{ + t_scriptlet *sp; + if (selector == widgetps_vis) + sp = wh->wh_vis; + else if (selector == widgetps_new) + sp = wh->wh_new; + else if (selector == widgetps_free) + sp = wh->wh_free; + else if (selector == widgetps_data) + sp = wh->wh_data; + else if (selector == &s_bang) + sp = wh->wh_bang; + else if (selector == &s_float) + sp = wh->wh_float; + else if (selector == &s_symbol) + sp = wh->wh_symbol; + else + { + t_widgetscript *ws; + if (ws = widgethandlers_takeotherscript(wh, selector)) + sp = ws->ws_script; + else + { + loudbug_bug("widgethandlers_takeany"); + sp = 0; + } + } + return (sp); +} + +void widgethandlers_fill(t_widgethandlers *wh, t_props *pp) +{ + int ac; + t_atom *ap; + if (ap = props_getfirst(pp, &ac)) + { + do + { + if (ac > 1 && ap->a_type == A_SYMBOL && + ap->a_w.w_symbol->s_name[0] == '@' && + ap->a_w.w_symbol->s_name[1] != 0) + { + t_symbol *sel = gensym(ap->a_w.w_symbol->s_name + 1); + t_scriptlet *sp; + if (sp = widgethandlers_takeany(wh, sel)) + { + scriptlet_reset(sp); + scriptlet_add(sp, 0, 0, ac - 1, ap + 1); + } + } + else loudbug_bug("widgethandlers_fill"); + } + while (ap = props_getnext(pp, &ac)); + } +} + +t_scriptlet *widgethandlers_getvis(t_widgethandlers *wh) +{ + return (wh->wh_vis); +} + +t_scriptlet *widgethandlers_getnew(t_widgethandlers *wh) +{ + return (wh->wh_new); +} + +t_scriptlet *widgethandlers_getfree(t_widgethandlers *wh) +{ + return (wh->wh_free); +} + +t_scriptlet *widgethandlers_getdata(t_widgethandlers *wh) +{ + return (wh->wh_data); +} + +t_scriptlet *widgethandlers_getbang(t_widgethandlers *wh) +{ + return (wh->wh_bang); +} + +t_scriptlet *widgethandlers_getfloat(t_widgethandlers *wh) +{ + return (wh->wh_float); +} + +t_scriptlet *widgethandlers_getsymbol(t_widgethandlers *wh) +{ + return (wh->wh_symbol); +} + +t_scriptlet *widgethandlers_getother(t_widgethandlers *wh, t_symbol *selector) +{ + t_widgetscript *ws; + for (ws = wh->wh_others; ws; ws = ws->ws_next) + if (ws->ws_selector == selector) + return (ws->ws_script); + return (0); +} diff --git a/toxy/widgettype.c b/toxy/widgettype.c index 166a417..1cc102d 100644 --- a/toxy/widgettype.c +++ b/toxy/widgettype.c @@ -6,30 +6,34 @@ #include <string.h> #include "m_pd.h" #include "common/loud.h" +#include "common/grow.h" #include "common/dict.h" #include "common/props.h" #include "toxy/scriptlet.h" -#include "widgettype.h" +#include "widget.h" static char masterwidget_builtin[] = #include "setup.wiq" ; #define WIDGETTYPE_VERBOSE +#ifdef KRZYSZCZ +//#define WIDGETTYPE_DEBUG +#endif struct _widgettype { t_pd wt_pd; + t_glist *wt_glist; /* set by the loading widget */ t_symbol *wt_typekey; /* this is a typemap symbol */ t_symbol *wt_tkclass; /* also 'undefined' flag (gensym symbol) */ - t_symbol *wt_tkpackage; /* gensym symbol */ + char *wt_requirements; int wt_isinternal; /* true if built-in or defined in setup.wid */ - t_props *wt_options; - t_props *wt_handlers; - t_props *wt_arguments; - t_scriptlet *wt_iniscript; - t_scriptlet *wt_newscript; - t_scriptlet *wt_freescript; + t_props *wt_options; + t_props *wt_handlers; /* defined inside of #. comments */ + t_props *wt_arguments; + t_scriptlet *wt_auxscript; + t_widgethandlers *wt_scripts; /* multiliners tagged with #@ comments */ }; struct _masterwidget @@ -52,18 +56,65 @@ static t_canvas *widgettype_cvhook(t_pd *caller) return (0); } -static void widgettype_map(t_widgettype *wt, char *cls, char *pkg) +static void widgettype_map(t_widgettype *wt, char *cls, char *req) { wt->wt_tkclass = (cls ? gensym(cls) : 0); - wt->wt_tkpackage = (pkg ? gensym(pkg) : 0); + if (wt->wt_requirements) + freebytes(wt->wt_requirements, strlen(wt->wt_requirements) + 1); + if (req && *req) + { + char *opt = 0; + wt->wt_requirements = getbytes(strlen(req) + 1); + strcpy(wt->wt_requirements, req); + while (req) + { + char *w1 = scriptlet_nextword(req); + opt = (*req == '-' ? req : (w1 && *w1 == '-' ? w1 : 0)); + if (opt) + { + if (strcmp(opt + 1, "exact")) + { + loud_error + (0, "unknown option \"%s\" in widget type header", opt); + opt = 0; + } + if (*req == '-') + { + req = w1; + continue; + } + else w1 = scriptlet_nextword(w1); + } + if (*req >= '0' && *req <= '9') + { + loud_error + (0, "invalid base widget name \"%s\" in widget type header", + req); + req = w1; + } + else + { + t_widgettype *base; + char *ver = (w1 && *w1 >= '0' && *w1 <= '9' ? w1 : 0); + char *w2 = (ver ? scriptlet_nextword(ver) : w1); +#if 1 + loudbug_post("require %s (version %s %s)", + req, (opt ? opt : ">="), (ver ? ver : "any")); +#endif + base = widgettype_get(gensym(req), ver, opt, wt->wt_glist); + if (!base->wt_tkclass) + loud_error(0, "missing base widget file \"%s.wid\"", req); + req = w2; + } + } + } + else wt->wt_requirements = 0; } static void widgettype_clear(t_widgettype *wt) { props_clearall(wt->wt_options); - scriptlet_reset(wt->wt_iniscript); - scriptlet_reset(wt->wt_newscript); - scriptlet_reset(wt->wt_freescript); + widgethandlers_reset(wt->wt_scripts); } #if 0 @@ -71,32 +122,31 @@ static void widgettype_clear(t_widgettype *wt) static void widgettype_free(t_masterwidget *mw, t_widgettype *wt) { loudbug_startpost("widgettype free... "); + if (wt->wt_requirements) + freebytes(wt->wt_requirements, strlen(wt->wt_requirements) + 1); dict_unbind(mw->mw_typemap, (t_pd *)wt, wt->wt_typekey); props_freeall(wt->wt_options); - scriptlet_free(wt->wt_iniscript); - scriptlet_free(wt->wt_newscript); - scriptlet_free(wt->wt_freescript); + scriptlet_free(wt->wt_auxscript); + widgethandlers_free(wt->wt_scripts); pd_free((t_pd *)wt); loudbug_post("done"); } #endif -static t_widgettype *widgettype_new(t_masterwidget *mw, - char *typ, char *cls, char *pkg) +static t_widgettype *widgettype_new(t_masterwidget *mw, char *typ, char *cls, + char *req, t_glist *glist) { t_widgettype *wt = (t_widgettype *)pd_new(widgettype_class); + wt->wt_glist = glist; wt->wt_typekey = dict_key(mw->mw_typemap, typ); - widgettype_map(wt, cls, pkg); + widgettype_map(wt, cls, req); wt->wt_isinternal = 0; wt->wt_options = props_new(0, "option", "-", 0, 0); wt->wt_handlers = props_new(0, "handler", "@", wt->wt_options, 0); wt->wt_arguments = props_new(0, "argument", "#", wt->wt_options, 0); - wt->wt_iniscript = scriptlet_new((t_pd *)wt, mw->mw_target, mw->mw_target, + wt->wt_auxscript = scriptlet_new((t_pd *)wt, mw->mw_target, mw->mw_target, 0, 0, widgettype_cvhook); - wt->wt_newscript = scriptlet_new((t_pd *)wt, mw->mw_target, mw->mw_target, - 0, 0, widgettype_cvhook); - wt->wt_freescript = scriptlet_new((t_pd *)wt, mw->mw_target, mw->mw_target, - 0, 0, widgettype_cvhook); + wt->wt_scripts = widgethandlers_new(wt->wt_auxscript); dict_bind(mw->mw_typemap, (t_pd *)wt, wt->wt_typekey); return (wt); } @@ -117,7 +167,7 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, t_symbol *typekey; t_widgettype *typeval; char *cls = scriptlet_nextword(buf); - char *pkg = (cls ? scriptlet_nextword(cls) : 0); + char *req = (cls ? scriptlet_nextword(cls) : 0); mw->mw_parsedtype = 0; if (!cls) cls = buf; @@ -143,22 +193,27 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, return (SCRIPTLET_LOCK); } } - if (pkg) - /* carve out a single word as pkg, LATER rethink */ - scriptlet_nextword(pkg); if (typeval) - widgettype_map(typeval, cls, pkg); + widgettype_map(typeval, cls, req); else { - typeval = widgettype_new(mw, buf, cls, pkg); + typeval = widgettype_new(mw, buf, cls, req, 0); typeval->wt_isinternal = (caller == (t_pd *)mw); } mw->mw_parsedtype = typeval; #ifdef WIDGETTYPE_DEBUG loudbug_post("adding widget type '%s'", typeval->wt_typekey->s_name); #endif - scriptlet_reset(typeval->wt_iniscript); - return (typeval->wt_iniscript); + widgethandlers_reset(typeval->wt_scripts); + + /* What should follow after the header? In a cleaner layout, perhaps, + the header would be placed at the top, followed by setup. Any + handler would require an explicit #@ tag, and the next statement + would return SCRIPTLET_UNLOCK. LATER revisit -- the change breaks + old .wid files, so better wait for a more robust parsing, which + notices dot-sequences in the setup part and warns about them. + Setup before header will be valid after the change, anyway. */ + return (widgethandlers_getvis(typeval->wt_scripts)); } else if (sel == '.') { @@ -192,26 +247,8 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, { /* multiline definition of a handler */ scriptlet_nextword(buf); if (mw->mw_parsedtype) - { - if (!strcmp(buf, "vis") || !strcmp(buf, "ini")) - /* already reset */ - return (mw->mw_parsedtype->wt_iniscript); - else if (!strcmp(buf, "new")) - { - scriptlet_reset(mw->mw_parsedtype->wt_newscript); - return (mw->mw_parsedtype->wt_newscript); - } - else if (!strcmp(buf, "free")) - { - scriptlet_reset(mw->mw_parsedtype->wt_freescript); - return (mw->mw_parsedtype->wt_freescript); - } - else - { - /* LATER start parsing any method handler: search for it, - create if not found, return */ - } - } + return (widgethandlers_takeany(mw->mw_parsedtype->wt_scripts, + gensym(buf))); } return (SCRIPTLET_UNLOCK); } @@ -223,7 +260,7 @@ static int widgettype_doload(t_widgettype *wt, t_symbol *s) but not in `pwd` */ t_scriptlet *mwsp = scriptlet_new((t_pd *)masterwidget, masterwidget->mw_target, - masterwidget->mw_target, 0, canvas_getcurrent(), 0); + masterwidget->mw_target, 0, wt->wt_glist, 0); masterwidget->mw_parsedtype = wt; if (scriptlet_rcload(mwsp, (t_pd *)wt, @@ -259,7 +296,7 @@ t_widgettype *widgettype_find(t_symbol *s) s->s_name), 0)); } -t_widgettype *widgettype_get(t_symbol *s) +t_widgettype *widgettype_get(t_symbol *s, char *ver, char *opt, t_glist *glist) { t_widgettype *wt = widgettype_find(s); /* Design decision: default widget definitions are NOT implicitly @@ -268,21 +305,23 @@ t_widgettype *widgettype_get(t_symbol *s) if (!wt) { /* first instance of a type not defined in setup.wid */ - wt = widgettype_new(masterwidget, s->s_name, 0, 0); + wt = widgettype_new(masterwidget, s->s_name, 0, 0, glist); + /* LATER use version and option */ widgettype_doload(wt, s); } return (wt); } -t_widgettype *widgettype_reload(t_symbol *s) +t_widgettype *widgettype_reload(t_symbol *s, t_glist *glist) { t_widgettype *wt = widgettype_find(s); if (!wt) /* first instance of a type not defined in setup.wid */ - wt = widgettype_new(masterwidget, s->s_name, 0, 0); + wt = widgettype_new(masterwidget, s->s_name, 0, 0, glist); if (wt && !wt->wt_isinternal) { /* LATER consider safe-loading through a temporary type */ widgettype_clear(wt); + wt->wt_glist = glist; if (widgettype_doload(wt, s)) return (wt); } @@ -314,40 +353,9 @@ t_props *widgettype_getarguments(t_widgettype *wt) return (wt->wt_arguments); } -char *widgettype_getinitializer(t_widgettype *wt, int *szp) -{ - return (scriptlet_getcontents(wt->wt_iniscript, szp)); -} - -char *widgettype_getconstructor(t_widgettype *wt, int *szp) -{ - return (scriptlet_getcontents(wt->wt_newscript, szp)); -} - -char *widgettype_getdestructor(t_widgettype *wt, int *szp) -{ - return (scriptlet_getcontents(wt->wt_freescript, szp)); -} - -int widgettype_ievaluate(t_widgettype *wt, t_scriptlet *outsp, - int visedonly, int ac, t_atom *av, t_props *argprops) -{ - return (scriptlet_evaluate(wt->wt_iniscript, outsp, - visedonly, ac, av, argprops)); -} - -int widgettype_cevaluate(t_widgettype *wt, t_scriptlet *outsp, - int visedonly, int ac, t_atom *av, t_props *argprops) -{ - return (scriptlet_evaluate(wt->wt_newscript, outsp, - visedonly, ac, av, argprops)); -} - -int widgettype_devaluate(t_widgettype *wt, t_scriptlet *outsp, - int visedonly, int ac, t_atom *av, t_props *argprops) +t_widgethandlers *widgettype_getscripts(t_widgettype *wt) { - return (scriptlet_evaluate(wt->wt_freescript, outsp, - visedonly, ac, av, argprops)); + return (wt->wt_scripts); } void widgettype_setup(void) @@ -434,9 +442,7 @@ void masterwidget_validate(void) } if (rcresult == SCRIPTLET_OK) { - t_scriptlet *sp = - scriptlet_new((t_pd *)masterwidget, masterwidget->mw_target, - masterwidget->mw_target, 0, 0, 0); + t_scriptlet *sp = scriptlet_newalike(masterwidget->mw_setupscript); if (scriptlet_evaluate(masterwidget->mw_setupscript, sp, 0, 0, 0, 0)) scriptlet_push(sp); else diff --git a/toxy/widgettype.h b/toxy/widgettype.h deleted file mode 100644 index a35f114..0000000 --- a/toxy/widgettype.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2003-2004 krzYszcz and others. - * For information on usage and redistribution, and for a DISCLAIMER OF ALL - * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ - -#ifndef __WIDGETTYPE_H__ -#define __WIDGETTYPE_H__ - -#ifdef KRZYSZCZ -//#define WIDGETTYPE_DEBUG -#endif - -EXTERN_STRUCT _widgettype; -#define t_widgettype struct _widgettype - -EXTERN_STRUCT _masterwidget; -#define t_masterwidget struct _masterwidget - -t_widgettype *widgettype_find(t_symbol *s); -t_widgettype *widgettype_get(t_symbol *s); -t_widgettype *widgettype_reload(t_symbol *s); -int widgettype_isdefined(t_widgettype *wt); -t_symbol *widgettype_tkclass(t_widgettype *wt); -t_props *widgettype_getoptions(t_widgettype *wt); -t_props *widgettype_gethandlers(t_widgettype *wt); -t_props *widgettype_getarguments(t_widgettype *wt); -char *widgettype_propname(t_symbol *s); -char *widgettype_getinitializer(t_widgettype *wt, int *szp); -char *widgettype_getconstructor(t_widgettype *wt, int *szp); -char *widgettype_getdestructor(t_widgettype *wt, int *szp); -int widgettype_ievaluate(t_widgettype *wt, t_scriptlet *outsp, - int visedonly, int ac, t_atom *av, t_props *argprops); -int widgettype_cevaluate(t_widgettype *wt, t_scriptlet *outsp, - int visedonly, int ac, t_atom *av, t_props *argprops); -int widgettype_devaluate(t_widgettype *wt, t_scriptlet *outsp, - int visedonly, int ac, t_atom *av, t_props *argprops); -void widgettype_setup(void); - -char *masterwidget_getcontents(int *szp); -void masterwidget_validate(void); - -#endif |