diff options
Diffstat (limited to 'toxy')
-rw-r--r-- | toxy/build_counter | 4 | ||||
-rw-r--r-- | toxy/notes.txt | 16 | ||||
-rw-r--r-- | toxy/tot.c | 148 | ||||
-rw-r--r-- | toxy/widget.c | 474 | ||||
-rw-r--r-- | toxy/widgettype.c | 39 |
5 files changed, 421 insertions, 260 deletions
diff --git a/toxy/build_counter b/toxy/build_counter index 3c2910e..8e0975b 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 15 +#define TOXY_BUILD 16 #if 0 -TOXY_SNAPSHOT = 0.1-alpha15 +TOXY_SNAPSHOT = 0.1-alpha16 #endif diff --git a/toxy/notes.txt b/toxy/notes.txt index aa5119a..775bbcd 100644 --- a/toxy/notes.txt +++ b/toxy/notes.txt @@ -1,7 +1,23 @@ TODO for toxy + * widget + . cached handlers + . better megawidgets + . editor: handle semicolons (need to revisit resolution rules) + . editor: differentiate argument keys from casual #strings (color-names) + * tow: canvas-wide and type-on-canvas-wide broadcasting DONE for toxy +alpha16 + * widget: + . editor for options, handlers and arguments made more or less functional + . better 'redefine' (although still only external types may be redefined) + * tow: + . fixed handling of gop-ed targets and missing windows + . new messages: 'retarget', 'pwd' + * tot: + . scriptlet editor improved a little bit (still unfinished) + alpha15 * fixes for megawidgets . setting sub-item bindings in ::toxy::subwidget @@ -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. */ @@ -9,6 +9,7 @@ #include "m_pd.h" #include "g_canvas.h" #include "common/loud.h" +#include "unstable/forky.h" #include "hammer/file.h" #include "hammer/gui.h" #include "common/props.h" @@ -251,31 +252,70 @@ static void tot__callback(t_tot *x, t_symbol *s, int ac, t_atom *av) tot_dooutput(x, x->x_out2, s, ac, av); } -/* LATER use properties in widgetbehavior (if gop visibility rules change) */ -static void tot_click(t_tot *x, t_floatarg xpos, t_floatarg ypos, - t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +static void tot_properties(t_gobj *z, t_glist *glist) { + t_tot *x = (t_tot *)z; int nleft; char *head = scriptlet_getcontents(x->x_persistent, &nleft); - char buf[MAXPDSTRING + 1]; - buf[MAXPDSTRING] = 0; hammereditor_open(x->x_filehandle, "scriptlet editor", 0); - while (nleft > 0) + if (nleft) { - if (nleft > MAXPDSTRING) + char buf[MAXPDSTRING + 1], *lastptr = buf + MAXPDSTRING; + *lastptr = 0; + while (nleft > 0) { - strncpy(buf, head, MAXPDSTRING); - head += MAXPDSTRING; - nleft -= MAXPDSTRING; - } - else - { - strncpy(buf, head, nleft); - buf[nleft] = 0; - nleft = 0; + if (nleft > MAXPDSTRING) + { + strncpy(buf, head, MAXPDSTRING); + head += MAXPDSTRING; + nleft -= MAXPDSTRING; + } + else + { + strncpy(buf, head, nleft); + lastptr = buf + nleft; + *lastptr = 0; + nleft = 0; + } + hammereditor_append(x->x_filehandle, buf); } - hammereditor_append(x->x_filehandle, buf); + hammereditor_append(x->x_filehandle, "\n"); } + hammereditor_setdirty(x->x_filehandle, 0); +} + +static void tot_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) +{ + t_tot *x = (t_tot *)z; + scriptlet_reset(x->x_persistent); + scriptlet_add(x->x_persistent, 0, 0, ac, av); +} + +static void tot_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + scriptlet_read(((t_tot *)z)->x_persistent, fn); +} + +static void tot_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + scriptlet_write(((t_tot *)z)->x_persistent, fn); +} + +static void tot_read(t_tot *x, t_symbol *s) +{ + if (s && s != &s_) + scriptlet_read(x->x_persistent, s); + else + hammerpanel_open(x->x_filehandle, 0); +} + +static void tot_write(t_tot *x, t_symbol *s) +{ + if (s && s != &s_) + scriptlet_write(x->x_persistent, s); + else + hammerpanel_save(x->x_filehandle, + canvas_getdir(x->x_glist), x->x_defname); } /* This is called for all Map (f==1) and all Destroy (f==0) events, @@ -305,6 +345,38 @@ static void tot__vised(t_tot *x, t_symbol *s, t_floatarg f) } #ifdef TOT_DEBUG +static void tot_postscriptlet(t_scriptlet *sp, char *message) +{ + int nleft; + char *head = scriptlet_getbuffer(sp, &nleft); + loudbug_startpost("*** %s (size %d)", message, nleft); + if (nleft) + { + char buf[MAXPDSTRING + 1], *lastptr = buf + MAXPDSTRING; + *lastptr = 0; + loudbug_stringpost(" ***\n\""); + while (nleft > 0) + { + if (nleft > MAXPDSTRING) + { + strncpy(buf, head, MAXPDSTRING); + head += MAXPDSTRING; + nleft -= MAXPDSTRING; + } + else + { + strncpy(buf, head, nleft); + lastptr = buf + nleft; + *lastptr = 0; + nleft = 0; + } + loudbug_stringpost(buf); + } + loudbug_stringpost("\"\n---------------\n"); + } + else loudbug_stringpost(": \"\" ***\n"); +} + static void tot_debug(t_tot *x) { t_symbol *pn = tot_getpathname(x, 0); @@ -314,40 +386,11 @@ static void tot_debug(t_tot *x) loudbug_post("destination: %s", tot_getcvname(x)->s_name); loudbug_post("pathname%s %s", (pn ? ":" : ""), (pn ? pn->s_name : "unknown")); - bp = scriptlet_getbuffer(x->x_transient, &sz); - loudbug_post("transient buffer (size %d):\n\"%s\"", sz, bp); - bp = scriptlet_getbuffer(x->x_persistent, &sz); - loudbug_post("persistent buffer (size %d):\n\"%s\"", sz, bp); + tot_postscriptlet(x->x_transient, "transient buffer"); + tot_postscriptlet(x->x_persistent, "persistent buffer"); } #endif -static void tot_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) -{ - scriptlet_read(((t_tot *)z)->x_persistent, fn); -} - -static void tot_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) -{ - scriptlet_write(((t_tot *)z)->x_persistent, fn); -} - -static void tot_read(t_tot *x, t_symbol *s) -{ - if (s && s != &s_) - scriptlet_read(x->x_persistent, s); - else - hammerpanel_open(x->x_filehandle, 0); -} - -static void tot_write(t_tot *x, t_symbol *s) -{ - if (s && s != &s_) - scriptlet_write(x->x_persistent, s); - else - hammerpanel_save(x->x_filehandle, - canvas_getdir(x->x_glist), x->x_defname); -} - static void tot_detach(t_tot *x) { t_canvas *cv = tot_getcanvas(x, 1); @@ -571,7 +614,8 @@ static void *tot_new(t_symbol *s1, t_symbol *s2) } else x->x_defname = &s_; x->x_filehandle = hammerfile_new((t_pd *)x, 0, - tot_readhook, tot_writehook, 0); + tot_readhook, tot_writehook, + tot_editorhook); hammergui_bindvised((t_pd *)x); x->x_visedpathname = tot_getvisedpathname(x, 0); x->x_guidetached = 0; @@ -626,15 +670,13 @@ void tot_setup(void) gensym("_rp"), A_GIMME, 0); class_addmethod(tot_class, (t_method)tot__callback, gensym("_cb"), A_GIMME, 0); - class_addmethod(tot_class, (t_method)tot_click, - gensym("click"), - A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); class_addmethod(tot_class, (t_method)tot__vised, gensym("_vised"), A_SYMBOL, A_FLOAT, 0); #ifdef TOT_DEBUG class_addmethod(tot_class, (t_method)tot_debug, gensym("debug"), 0); #endif + forky_setpropertiesfn(tot_class, tot_properties); hammerfile_setup(tot_class, 0); totspy_class = class_new(gensym("tot spy"), 0, 0, sizeof(t_totspy), CLASS_PD, 0); diff --git a/toxy/widget.c b/toxy/widget.c index c0bffd8..da4a78f 100644 --- a/toxy/widget.c +++ b/toxy/widget.c @@ -55,7 +55,7 @@ typedef struct _widgethandlers typedef struct _widget { t_object x_ob; - t_glist *x_glist; /* containing glist */ + t_glist *x_glist; /* containing glist */ t_widgettype *x_typedef; t_symbol *x_type; /* 1st creation arg: our type */ t_symbol *x_tkclass; /* Tk widget class */ @@ -68,6 +68,10 @@ typedef struct _widget t_props *x_options; /* instance options */ t_props *x_handlers; /* instance handlers */ t_props *x_arguments; /* instance arguments */ + t_props *x_xargs; /* type and instance arguments, resolved */ + 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_scriptlet *x_optscript; /* option scriptlet */ @@ -89,13 +93,14 @@ typedef struct _widget typedef struct _tow { t_object x_ob; - t_glist *x_glist; /* containing glist */ - t_symbol *x_cvremote; /* null if containing glist is our destination */ + t_glist *x_glist; /* containing glist */ + t_glist *x_targetglist; /* containing or parent glist */ + t_symbol *x_cvremote; /* null if targetglist is set */ t_symbol *x_cvname; - t_symbol *x_type; /* 2nd creation arg: widget's type */ - t_symbol *x_name; /* 3rd creation arg: widget's name */ + t_symbol *x_type; /* 2nd creation arg: widget's type */ + t_symbol *x_name; /* 3rd creation arg: widget's name */ t_widgetentry *x_widgetlist; - struct _tow *x_next; /* next in the global towlist */ + struct _tow *x_next; /* next in the global towlist */ } t_tow; static t_class *widget_class; @@ -103,7 +108,7 @@ static t_class *tow_class; /* Global towlist, searched in widget_attach(). There is no global widgetlist, because a destination glist is searched instead in tow_attach(). */ -static t_tow *towlist = 0; +static t_tow *widget_towlist = 0; static t_symbol *widgetps_mouse; static t_symbol *widgetps_motion; @@ -176,6 +181,7 @@ static void widget_profile(t_widget *x) #define WIDGETPROFILE_HANDLER_QUIT #endif +/* resolving type and instance arguments into x_xargs */ static char *widget_propsresolver(t_pd *owner, int ac, t_atom *av) { t_widget *x = (t_widget *)owner; @@ -256,7 +262,7 @@ static void widget_transtick(t_widget *x) newt->te_ypix = oldt->te_ypix; outlet_new(newt, &s_); inlet_new(newt, &newt->ob_pd, &s_, &s_); - /* FIXME preserve connections */ + /* LATER preserve connections (although connected widget is a bad thing) */ glist_add(x->x_glist, &newt->te_g); if (glist_isvisible(x->x_glist)) { @@ -337,8 +343,7 @@ static void widget_delete(t_gobj *z, t_glist *glist) static void widget_pushoptions(t_widget *x, int doit) { char *mypathname = widget_getmypathname(x, x->x_glist)->s_name; - if (scriptlet_evaluate(x->x_optscript, x->x_transient, 0, - 0, 0, x->x_arguments)) + if (scriptlet_evaluate(x->x_optscript, x->x_transient, 0, 0, 0, x->x_xargs)) { #ifdef WIDGET_DEBUG int sz; @@ -362,13 +367,12 @@ static void widget_pushinits(t_widget *x) { int sz; if (widgettype_ievaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_arguments)) + 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)"); } - if (scriptlet_evaluate(x->x_iniscript, x->x_transient, 0, - 0, 0, x->x_arguments)) + 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)"); @@ -381,7 +385,7 @@ static void widget_pushconstructors(t_widget *x) { int sz; if (widgettype_cevaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_arguments)) + 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)"); @@ -395,7 +399,7 @@ static void widget_pushdestructors(t_widget *x) { int sz; if (widgettype_devaluate(x->x_typedef, x->x_transient, 0, - 0, 0, x->x_arguments)) + 0, 0, x->x_xargs)) scriptlet_push(x->x_transient); else if (*widgettype_getdestructor(x->x_typedef, &sz) && sz > 0) loudbug_bug("widget_pushdestructors (type)"); @@ -458,56 +462,59 @@ static void widget_save(t_gobj *z, t_binbuf *bb) binbuf_addsemi(bb); } -/* FIXME */ -static void widget_properties(t_gobj *z, t_glist *glist) +static void widget_editorappend(t_widget *x, t_props *pp) { - t_widget *x = (t_widget *)z; + int ac; t_atom *ap; - int ac, nleft; - char *head = scriptlet_getcontents(x->x_optscript, &nleft); - char buf[MAXPDSTRING + 1]; - buf[MAXPDSTRING] = 0; - sprintf(buf, "%s %s", x->x_type->s_name, x->x_name->s_name); - hammereditor_open(x->x_filehandle, buf, 0); - while (nleft > 0) - { - if (nleft > MAXPDSTRING) - { - strncpy(buf, head, MAXPDSTRING); - head += MAXPDSTRING; - nleft -= MAXPDSTRING; - } - else - { - strncpy(buf, head, nleft); - buf[nleft] = 0; - nleft = 0; - } - hammereditor_append(x->x_filehandle, buf); - } - scriptlet_reset(x->x_auxscript); - ap = props_getall(x->x_handlers, &ac); - if (ac) scriptlet_add(x->x_auxscript, 0, 0, ac, ap); - head = scriptlet_getcontents(x->x_auxscript, &nleft); - hammereditor_append(x->x_filehandle, "\n"); - while (nleft > 0) + if (ap = props_getfirst(pp, &ac)) { - if (nleft > MAXPDSTRING) - { - strncpy(buf, head, MAXPDSTRING); - head += MAXPDSTRING; - nleft -= MAXPDSTRING; - } - else + if (pp != x->x_diffoptions) + hammereditor_append(x->x_filehandle, "\n"); + do { - strncpy(buf, head, nleft); - buf[nleft] = 0; - nleft = 0; + int nleft; + char buf[MAXPDSTRING + 1], *head; + buf[MAXPDSTRING] = 0; + scriptlet_reset(x->x_auxscript); + scriptlet_add(x->x_auxscript, 0, 0, ac, ap); + head = scriptlet_getcontents(x->x_auxscript, &nleft); + while (nleft > 0) + { + if (nleft > MAXPDSTRING) + { + strncpy(buf, head, MAXPDSTRING); + head += MAXPDSTRING; + nleft -= MAXPDSTRING; + } + else + { + strncpy(buf, head, nleft); + buf[nleft] = 0; + nleft = 0; + } + hammereditor_append(x->x_filehandle, buf); + } + hammereditor_append(x->x_filehandle, "\n"); } - hammereditor_append(x->x_filehandle, buf); + while (ap = props_getnext(pp, &ac)); } } +static void widget_properties(t_gobj *z, t_glist *glist) +{ + t_widget *x = (t_widget *)z; + char buf[MAXPDSTRING]; + sprintf(buf, "%s %s", x->x_type->s_name, x->x_name->s_name); + hammereditor_open(x->x_filehandle, buf, 0); + widget_editorappend(x, x->x_diffoptions); + widget_editorappend(x, x->x_options); + widget_editorappend(x, x->x_diffhandlers); + widget_editorappend(x, x->x_handlers); + widget_editorappend(x, x->x_diffarguments); + widget_editorappend(x, x->x_arguments); + hammereditor_setdirty(x->x_filehandle, 0); +} + static t_widgetbehavior widget_behavior = { widget_getrect, @@ -532,8 +539,10 @@ static void widget_update(t_widget *x, t_props *op) { t_atom *ap; int ac; + props_diff(x->x_diffoptions, + widgettype_getoptions(x->x_typedef), x->x_options); scriptlet_reset(x->x_optscript); - ap = props_getall(widgettype_getoptions(x->x_typedef), &ac); + ap = props_getall(x->x_diffoptions, &ac); if (ac) scriptlet_add(x->x_optscript, 0, 0, ac, ap); ap = props_getall(x->x_options, &ac); if (ac) scriptlet_add(x->x_optscript, 0, 0, ac, ap); @@ -553,21 +562,32 @@ static void widget_update(t_widget *x, t_props *op) x->x_update = WIDGET_NOVIS; } } - else + else if (op == x->x_handlers) { + props_diff(x->x_diffhandlers, + widgettype_gethandlers(x->x_typedef), x->x_handlers); /* LATER cache handlers. We get here both during construction, and after any change in our handlers -- the cache never stales. */ } + else if (op == x->x_arguments) + { + props_diff(x->x_diffarguments, + widgettype_getarguments(x->x_typedef), x->x_arguments); + props_clearvalues(x->x_xargs); + props_clonevalues(x->x_xargs, x->x_diffarguments); + props_clonevalues(x->x_xargs, x->x_arguments); + } } -static t_symbol *widget_addprops(t_widget *x, t_props *op, int single, +static t_symbol *widget_addprops(t_widget *x, t_props *op, + int single, t_props *filter, t_symbol *s, int ac, t_atom *av) { if (op) { t_symbol *empty; - empty = props_add(op, single, s, ac, av); + empty = props_add(op, single, filter, s, ac, av); if (empty) loud_error((t_pd *)x, "no value given for %s '%s'", props_getname(op), empty->s_name); @@ -581,12 +601,34 @@ static t_symbol *widget_addprops(t_widget *x, t_props *op, int single, } } -static t_symbol *widget_addmessage(t_widget *x, t_symbol *s, int ac, t_atom *av) +static t_symbol *widget_addmessage(t_widget *x, int unique, + t_symbol *s, int ac, t_atom *av) { t_symbol *empty; - if (!(empty = widget_addprops(x, x->x_arguments, 0, s, ac, av)) && - !(empty = widget_addprops(x, x->x_handlers, 0, s, ac, av))) - empty = widget_addprops(x, x->x_options, 0, s, ac, av); + if (s) + { + /* FIXME mixed messages */ + if (*s->s_name == '-') + x->x_update = WIDGET_PUSHVIS; + else if (*s->s_name == '#') + x->x_update = WIDGET_REVIS; + else + x->x_update = WIDGET_NOVIS; + } + /* Instance-type duplicates are not removed, unless 'unique' is set. + If it is set, we are called from editorhook, so we assume duplicates + were not specified explicitly. In other cases we keep duplicates, + because type may change until next time this widget is created or + refreshed. */ + if (!(empty = widget_addprops(x, x->x_arguments, 0, + (unique ? x->x_diffarguments : 0), + s, ac, av)) && + !(empty = widget_addprops(x, x->x_handlers, 0, + (unique ? x->x_diffhandlers : 0), + s, ac, av))) + empty = widget_addprops(x, x->x_options, 0, + (unique ? x->x_diffoptions : 0), + s, ac, av); return (empty); } @@ -597,14 +639,7 @@ static void widget_anything(t_widget *x, t_symbol *s, int ac, t_atom *av) if (*s->s_name == '-' || *s->s_name == '@' || *s->s_name == '#') { t_symbol *empty; - /* FIXME mixed messages */ - if (*s->s_name == '-') - x->x_update = WIDGET_PUSHVIS; - else if (*s->s_name == '#') - x->x_update = WIDGET_REVIS; - else - x->x_update = WIDGET_NOVIS; - if (empty = widget_addmessage(x, s, ac, av)) + if (empty = widget_addmessage(x, 0, s, ac, av)) loud_errand((t_pd *)x, "(use 'remove %s' if that is what you want).", empty->s_name); @@ -629,7 +664,7 @@ static void widget_anything(t_widget *x, t_symbol *s, int ac, t_atom *av) 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_arguments)) + ac, av, x->x_xargs)) { WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); @@ -681,7 +716,7 @@ static void widget_float(t_widget *x, t_float 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_arguments)) + 1, &at, x->x_xargs)) { WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); @@ -709,7 +744,7 @@ static void widget_symbol(t_widget *x, t_symbol *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_arguments)) + 1, &at, x->x_xargs)) { WIDGETPROFILE_HANDLER_PUSH; scriptlet_push(x->x_transient); @@ -743,12 +778,12 @@ static void widget_set(t_widget *x, t_symbol *s, int ac, t_atom *av) if (*prp->s_name == '-') { x->x_update = WIDGET_PUSHVIS; - empty = widget_addprops(x, x->x_options, 1, prp, ac, av); + empty = widget_addprops(x, x->x_options, 1, 0, prp, ac, av); } else if (*prp->s_name == '@') - empty = widget_addprops(x, x->x_handlers, 1, prp, ac, av); + empty = widget_addprops(x, x->x_handlers, 1, 0, prp, ac, av); else if (*prp->s_name == '#') - empty = widget_addprops(x, x->x_arguments, 1, prp, ac, av); + empty = widget_addprops(x, x->x_arguments, 1, 0, prp, ac, av); if (empty) loud_errand((t_pd *)x, "(use 'remove %s' if that is what you want).", @@ -772,7 +807,8 @@ static void widget_remove(t_widget *x, t_symbol *s) op = 0; if (op && props_remove(op, s)) { - if (op == x->x_options) x->x_update = WIDGET_REVIS; + if (op == x->x_options) /* LATER rethink */ + x->x_update = WIDGET_REVIS; widget_update(x, op); } else loud_warning((t_pd *)x, 0, "%s %s has not been specified", @@ -795,7 +831,7 @@ static void widget_tot(t_widget *x, t_symbol *s, int ac, t_atom *av) scriptlet_reset(x->x_auxscript); scriptlet_add(x->x_auxscript, 1, 1, ac, av); if (scriptlet_evaluate(x->x_auxscript, x->x_transient, 1, - 0, 0, x->x_arguments)) + 0, 0, x->x_xargs)) scriptlet_push(x->x_transient); } } @@ -803,21 +839,23 @@ static void widget_tot(t_widget *x, t_symbol *s, int ac, t_atom *av) static void widget_refresh(t_widget *x) { x->x_update = WIDGET_REVIS; - widget_update(x, x->x_options); - widget_update(x, x->x_handlers); widget_update(x, x->x_arguments); + widget_update(x, x->x_handlers); + widget_update(x, x->x_options); } static int widget_resettype(t_widget *x, t_widgettype *wt) { - if (wt == x->x_typedef) + if (!wt || /* LATER rethink, cf widgettype_reload() */ + wt == x->x_typedef) { if (!(x->x_tkclass = widgettype_tkclass(x->x_typedef))) x->x_tkclass = x->x_type; - props_clone(x->x_arguments, widgettype_getarguments(x->x_typedef)); - /* FIXME widget_addmessage(x, 0, ac, av); */ + x->x_update = WIDGET_REVIS; + widget_update(x, x->x_arguments); widget_pushconstructors(x); - widget_refresh(x); + widget_update(x, x->x_handlers); + widget_update(x, x->x_options); return (1); } else @@ -832,6 +870,14 @@ static void widget_redefine(t_widget *x) widget_resettype(x, widgettype_reload(x->x_type)); } +static void widget_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) +{ + t_widget *x = (t_widget *)z; + props_clearall(x->x_options); + widget_addmessage(x, 1, 0, ac, av); + widget_refresh(x); +} + static void widget__failure(t_widget *x) { loud_error((t_pd *)x, "creation failure"); @@ -994,18 +1040,21 @@ static void widget_debug(t_widget *x) widgetbug_postprops("default options:", widgettype_getoptions(x->x_typedef)); widgetbug_postprops("instance options:", x->x_options); + widgetbug_postprops("diff options:", x->x_diffoptions); widgetbug_postprops("default handlers:", widgettype_gethandlers(x->x_typedef)); widgetbug_postprops("instance handlers:", x->x_handlers); + widgetbug_postprops("diff handlers:", x->x_diffhandlers); widgetbug_postprops("default arguments:", widgettype_getarguments(x->x_typedef)); widgetbug_postprops("instance arguments:", x->x_arguments); + widgetbug_postprops("diff arguments:", x->x_diffarguments); loudbug_post("dictionary:"); - bp = props_firstvalue(x->x_arguments, &key); + bp = props_firstvalue(x->x_xargs, &key); while (bp) { loudbug_post("\t%s: \"%s\"", key, bp); - bp = props_nextvalue(x->x_arguments, &key); + bp = props_nextvalue(x->x_xargs, &key); } bp = scriptlet_getcontents(x->x_transient, &sz); loudbug_post("transient buffer (size %d):\n\"%s\"", sz, (bp ? bp : bempty)); @@ -1044,6 +1093,8 @@ static void widget_free(t_widget *x) gui_unbind((t_pd *)x, x->x_cbtarget); gui_unbind((t_pd *)x, x->x_rptarget); 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); @@ -1111,8 +1162,13 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) x->x_options = props_new((t_pd *)x, "option", "-", 0, 0); x->x_handlers = props_new((t_pd *)x, "handler", "@", x->x_options, 0); - x->x_arguments = props_new((t_pd *)x, "argument", "#", x->x_options, - widget_propsresolver); + x->x_arguments = props_new((t_pd *)x, "argument", "#", x->x_options, 0); + x->x_xargs = props_new((t_pd *)x, "argument", "#", 0, widget_propsresolver); + x->x_diffoptions = props_new((t_pd *)x, "option", "-", 0, 0); + x->x_diffhandlers = props_new((t_pd *)x, "handler", "@", + x->x_diffoptions, 0); + x->x_diffarguments = props_new((t_pd *)x, "argument", "#", + x->x_diffoptions, 0); outlet_new((t_object *)x, &s_anything); /* LATER consider estimating these, based on widget class and options. @@ -1121,9 +1177,7 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) but finding gops stretched, to accomodate the widget's default area. */ x->x_width = 5; x->x_height = 5; - props_clone(x->x_arguments, widgettype_getarguments(x->x_typedef)); - widget_addmessage(x, 0, ac, av); - x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, 0, 0); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, 0, widget_editorhook); x->x_transclock = clock_new(x, (t_method)widget_transtick); x->x_background = 0; x->x_hasstate = 0; @@ -1131,75 +1185,19 @@ static void *widget_new(t_symbol *s, int ac, t_atom *av) x->x_disabled = 0; x->x_vised = 0; widget_attach(x); + widget_addmessage(x, 0, 0, ac, av); widget_pushconstructors(x); return (x); } static t_glist *tow_getglist(t_tow *x, int complain) { - t_glist *glist = - (x->x_cvremote ? - (t_glist *)pd_findbyclass(x->x_cvremote, canvas_class) : x->x_glist); - if (!glist && complain) + t_glist *glist = (x->x_cvremote ? + (t_glist *)pd_findbyclass(x->x_cvremote, canvas_class) : + x->x_targetglist); + if (!glist && x->x_cvname && complain) loud_error((t_pd *)x, "bad canvas name '%s'", x->x_cvname->s_name); - return (glist_getcanvas(glist)); -} - -static void tow_bang(t_tow *x) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - widget_bang(we->we_widget); -} - -static void tow_float(t_tow *x, t_float f) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - widget_float(we->we_widget, f); -} - -static void tow_symbol(t_tow *x, t_symbol *s) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - widget_symbol(we->we_widget, s); -} - -static void tow_anything(t_tow *x, t_symbol *s, int ac, t_atom *av) -{ - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - typedmess((t_pd *)we->we_widget, s, ac, av); -} - -static void tow_redefine(t_tow *x) -{ - t_widgettype *wt = widgettype_reload(x->x_type); - t_widgetentry *we; - for (we = x->x_widgetlist; we; we = we->we_next) - if (!widget_resettype(we->we_widget, wt)) - break; -} - -static void tow__callback(t_tow *x, t_symbol *s, int ac, t_atom *av) -{ - if (ac == 1) - { - if (av->a_type == A_FLOAT) - outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); - else if (av->a_type == A_SYMBOL) - outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); - } - else if (ac) - { - if (av->a_type == A_FLOAT) - outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); - else if (av->a_type == A_SYMBOL) - outlet_anything(((t_object *)x)->ob_outlet, - av->a_w.w_symbol, ac - 1, av + 1); - } - else outlet_bang(((t_object *)x)->ob_outlet); + return (glist); } static void tow_widgetattach(t_tow *x, t_widget *w) @@ -1246,7 +1244,7 @@ static void tow_widgetdetach(t_tow *x, t_widget *w) static void widget_attach(t_widget *x) { t_tow *t; - for (t = towlist; t; t = t->x_next) + for (t = widget_towlist; t; t = t->x_next) if (x->x_glist == tow_getglist(t, 0) && t->x_type == x->x_type && t->x_name == x->x_name) tow_widgetattach(t, x); @@ -1285,7 +1283,8 @@ static void tow_attach(t_tow *x) #endif } #ifdef TOW_DEBUG - else loudbug_post("glist '%s' not found", x->x_cvname->s_name); + else if (x->x_cvname) + loudbug_post("glist '%s' not found", x->x_cvname->s_name); #endif } @@ -1320,6 +1319,116 @@ static void tow_detach(t_tow *x) } } +static void tow_bang(t_tow *x) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + widget_bang(we->we_widget); +} + +static void tow_float(t_tow *x, t_float f) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + widget_float(we->we_widget, f); +} + +static void tow_symbol(t_tow *x, t_symbol *s) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + widget_symbol(we->we_widget, s); +} + +static void tow_anything(t_tow *x, t_symbol *s, int ac, t_atom *av) +{ + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + typedmess((t_pd *)we->we_widget, s, ac, av); +} + +static void tow_redefine(t_tow *x) +{ + t_widgettype *wt = widgettype_reload(x->x_type); + t_widgetentry *we; + for (we = x->x_widgetlist; we; we = we->we_next) + if (!widget_resettype(we->we_widget, wt)) + break; +} + +/* LATER broadcasting: canvas-wide or type-on-canvas-wide */ +static void tow_settarget(t_tow *x, t_symbol *s1, t_symbol *s2, t_symbol *s3) +{ + char buf[64]; + if (s1 == &s_ || !strcmp(s1->s_name, ".")) + s1 = 0; + if (s1 && strcmp(s1->s_name, ".parent")) + { + x->x_cvremote = canvas_makebindsym(x->x_cvname = s1); + x->x_targetglist = 0; + } + else + { + x->x_cvremote = 0; + if (s1) + { + if (x->x_glist->gl_owner) + x->x_targetglist = x->x_glist->gl_owner; + else + { /* The case of a tow pointing out from an abstraction, + targeting its parent, is considered invalid (otherwise, + opening an abstraction as a top-level patch should not be + flagged as error). LATER rethink. */ + loud_error((t_pd *)x, "parent of a top level patch requested,"); + loud_errand((t_pd *)x, "this is a dangling tow..."); + x->x_cvname = 0; + x->x_targetglist = 0; + } + } + else x->x_targetglist = x->x_glist; + } + if (x->x_targetglist) + x->x_cvname = x->x_targetglist->gl_name; + x->x_type = s2; + x->x_name = s3; + tow_attach(x); +} + +static void tow_retarget(t_tow *x, t_symbol *s1, t_symbol *s2, t_symbol *s3) +{ + tow_detach(x); + tow_settarget(x, s1, s2, s3); +} + +static void tow_pwd(t_tow *x, t_symbol *s) +{ + t_glist *glist; + t_symbol *dir; + if (s && s->s_thing && (glist = tow_getglist(x, 1)) && + (dir = canvas_getdir(glist))) + pd_symbol(s->s_thing, dir); +} + +static void tow__callback(t_tow *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac == 1) + { + if (av->a_type == A_FLOAT) + outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); + else if (av->a_type == A_SYMBOL) + outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); + } + else if (ac) + { + if (av->a_type == A_FLOAT) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else if (av->a_type == A_SYMBOL) + outlet_anything(((t_object *)x)->ob_outlet, + av->a_w.w_symbol, ac - 1, av + 1); + } + else outlet_bang(((t_object *)x)->ob_outlet); +} + #ifdef TOW_DEBUG static void tow_debug(t_tow *x) { @@ -1349,14 +1458,14 @@ static void tow_free(t_tow *x) #ifdef TOW_DEBUG loudbug_startpost("updating towlist..."); #endif - for (t1 = 0, t2 = towlist; t2; t2 = t2->x_next) + for (t1 = 0, t2 = widget_towlist; t2; t2 = t2->x_next) { if (t2 == x) { if (t1) t1->x_next = t2->x_next; else - towlist = t2->x_next; + widget_towlist = t2->x_next; #ifdef TOW_DEBUG loudbug_post("ok"); #endif @@ -1370,42 +1479,13 @@ static void tow_free(t_tow *x) static void *tow_new(t_symbol *s1, t_symbol *s2, t_symbol *s3) { t_tow *x = (t_tow *)pd_new(tow_class); - char buf[64]; x->x_glist = canvas_getcurrent(); - if (s1 == &s_ || !strcmp(s1->s_name, ".")) - s1 = 0; - if (s1) - { - if (strcmp(s1->s_name, ".parent")) - x->x_cvremote = canvas_makebindsym(x->x_cvname = s1); - else - { - if (x->x_glist->gl_owner) - { - x->x_glist = x->x_glist->gl_owner; - x->x_cvremote = 0; - x->x_cvname = x->x_glist->gl_name; - } - else - { - /* FIXME */ - loud_error((t_pd *)x, "no parent patch"); - x->x_cvremote = canvas_makebindsym(x->x_cvname = s1); - } - } - } - else - { - x->x_cvremote = 0; - x->x_cvname = x->x_glist->gl_name; - } - x->x_type = s2; - x->x_name = s3; - outlet_new((t_object *)x, &s_anything); + x->x_targetglist = 0; x->x_widgetlist = 0; - x->x_next = towlist; - towlist = x; - tow_attach(x); + x->x_next = widget_towlist; + widget_towlist = x; + outlet_new((t_object *)x, &s_anything); + tow_settarget(x, s1, s2, s3); return (x); } @@ -1481,13 +1561,17 @@ void widget_setup(void) tow_class = class_new(gensym("tow"), (t_newmethod)tow_new, (t_method)tow_free, - sizeof(t_tow), 0, A_SYMBOL, A_SYMBOL, A_SYMBOL, 0); + sizeof(t_tow), 0, A_SYMBOL, A_DEFSYM, A_DEFSYM, 0); class_addbang(tow_class, tow_bang); class_addfloat(tow_class, tow_float); class_addsymbol(tow_class, tow_symbol); class_addanything(tow_class, tow_anything); class_addmethod(tow_class, (t_method)tow_redefine, gensym("redefine"), 0); + class_addmethod(tow_class, (t_method)tow_retarget, + gensym("retarget"), A_SYMBOL, A_SYMBOL, A_SYMBOL, 0); + class_addmethod(tow_class, (t_method)tow_pwd, + gensym("pwd"), A_SYMBOL, 0); class_addmethod(tow_class, (t_method)tow__callback, gensym("_cb"), A_GIMME, 0); #ifdef TOW_DEBUG diff --git a/toxy/widgettype.c b/toxy/widgettype.c index 0b993c1..166a417 100644 --- a/toxy/widgettype.c +++ b/toxy/widgettype.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. */ @@ -20,9 +20,10 @@ static char masterwidget_builtin[] = struct _widgettype { t_pd wt_pd; - t_symbol *wt_typekey; /* this is a typemap symbol */ - t_symbol *wt_tkclass; /* also 'undefined' flag (gensym symbol) */ - t_symbol *wt_tkpackage; /* gensym symbol */ + t_symbol *wt_typekey; /* this is a typemap symbol */ + t_symbol *wt_tkclass; /* also 'undefined' flag (gensym symbol) */ + t_symbol *wt_tkpackage; /* gensym symbol */ + int wt_isinternal; /* true if built-in or defined in setup.wid */ t_props *wt_options; t_props *wt_handlers; t_props *wt_arguments; @@ -57,6 +58,14 @@ static void widgettype_map(t_widgettype *wt, char *cls, char *pkg) wt->wt_tkpackage = (pkg ? gensym(pkg) : 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); +} + #if 0 /* only for debugging (never call, unless certain that nobody references wt) */ static void widgettype_free(t_masterwidget *mw, t_widgettype *wt) @@ -78,6 +87,7 @@ static t_widgettype *widgettype_new(t_masterwidget *mw, t_widgettype *wt = (t_widgettype *)pd_new(widgettype_class); wt->wt_typekey = dict_key(mw->mw_typemap, typ); widgettype_map(wt, cls, pkg); + 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); @@ -117,7 +127,8 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, { /* setup.wid or built-in defaults */ if (typeval) { - /* LATER rethink */ + /* LATER may need revisiting, when/if we accept explicit + 'redefine' requests for internal types */ loud_warning((t_pd *)mw, 0, "redefinition of '%s'\ in \"%s.wid\" file, ignored", buf, rc); return (SCRIPTLET_LOCK); @@ -138,7 +149,10 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, if (typeval) widgettype_map(typeval, cls, pkg); else + { typeval = widgettype_new(mw, buf, cls, pkg); + 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); @@ -160,11 +174,11 @@ static t_scriptlet *masterwidget_cmnthook(t_pd *caller, char *rc, t_atom *av = binbuf_getvec(mw->mw_bb); t_props *pp; if (!(empty = props_add(pp = mw->mw_parsedtype->wt_options, - 0, 0, ac, av)) && + 0, 0, 0, ac, av)) && !(empty = props_add(pp = mw->mw_parsedtype->wt_handlers, - 0, 0, ac, av))) + 0, 0, 0, ac, av))) empty = props_add(pp = mw->mw_parsedtype->wt_arguments, - 0, 0, ac, av); + 0, 0, 0, ac, av); if (empty) loud_warning((t_pd *)mw, 0, "no value given for %s '%s'\ @@ -266,8 +280,13 @@ t_widgettype *widgettype_reload(t_symbol *s) if (!wt) /* first instance of a type not defined in setup.wid */ wt = widgettype_new(masterwidget, s->s_name, 0, 0); - widgettype_doload(wt, s); - return (wt); + if (wt && !wt->wt_isinternal) + { /* LATER consider safe-loading through a temporary type */ + widgettype_clear(wt); + if (widgettype_doload(wt, s)) + return (wt); + } + return (0); } int widgettype_isdefined(t_widgettype *wt) |