aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared/common/Makefile.sources1
-rw-r--r--shared/common/patchvalue.c265
-rw-r--r--shared/common/patchvalue.h24
-rw-r--r--shared/notes.txt6
-rw-r--r--shared/toxy/scriptlet.c18
-rw-r--r--shared/toxy/scriptlet.h9
-rw-r--r--shared/unstable/fragile.c7
-rw-r--r--shared/unstable/fragile.h2
-rw-r--r--test/cyclone/speedlim-rescheduling.pd54
-rw-r--r--test/toxy/button-test.pd2
-rw-r--r--test/toxy/editors/bpf-test.pd13
-rw-r--r--test/toxy/editors/bpf.wid224
-rw-r--r--test/toxy/listbox-test.pd2
-rw-r--r--test/toxy/popcustom-test.pd2
-rw-r--r--test/toxy/setup.wid47
-rw-r--r--test/toxy/testmess.wid3
-rw-r--r--test/toxy/tow-test.pd2
-rw-r--r--toxy/Makefile.objects2
-rw-r--r--toxy/build_counter4
-rw-r--r--toxy/notes.txt26
-rw-r--r--toxy/widget.c351
-rw-r--r--toxy/widget.h46
-rw-r--r--toxy/widgethandlers.c211
-rw-r--r--toxy/widgettype.c192
-rw-r--r--toxy/widgettype.h41
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