diff --git a/pd/nw/css/default.css b/pd/nw/css/default.css index 5abd5f15e8170544e966dc688e68a73c4c922c38..396a40fad0236052e8921900568f94dde54995b8 100644 --- a/pd/nw/css/default.css +++ b/pd/nw/css/default.css @@ -401,6 +401,14 @@ text { stroke: #ccc; } +.obj .border.dirty { + stroke: #ff0000; +} + +.obj .border.subdirty { + stroke: #ff8800; +} + .comment .border { fill: none; } diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js index d172ee900234dc5778b1ac7590106589c139a152..465593cea83332f0d969b691971db5e85d1cc6fc 100644 --- a/pd/nw/pdgui.js +++ b/pd/nw/pdgui.js @@ -2659,6 +2659,16 @@ function gui_gobj_deselect(cid, tag) { }); } +function gui_gobj_dirty(cid, tag, state) { + gui(cid).get_gobj(tag, function(e) { + var border = e.querySelector(".border"); + border.classList.remove("dirty"); + border.classList.remove("subdirty"); + if(state === 1) border.classList.add("dirty"); + else if(state === 2) border.classList.add("subdirty"); + }); +} + function gui_canvas_emphasize(cid) { gui(cid).get_elem("patchsvg", function(e) { // raise the window diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c index e29d802d7a92cac7aa11515eabde57056edd7efd..f1a8279e26b01295693c5caef0a8f1242d1c2297 100644 --- a/pd/src/g_canvas.c +++ b/pd/src/g_canvas.c @@ -463,6 +463,8 @@ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv) } else x->gl_env = 0; + x->gl_subdirties = 0; + if (yloc < GLIST_DEFCANVASYLOC) yloc = GLIST_DEFCANVASYLOC; if (xloc < 0) @@ -757,6 +759,27 @@ void canvas_reflecttitle(t_canvas *x) namebuf, canvas_getdir(x)->s_name, x->gl_dirty); } +/* --------------------- */ + +/* climbs up to the root canvas while enabling or disabling visual markings for dirtiness + of traversed canvases */ +void canvas_dirtyclimb(t_canvas *x, int n) +{ + if (x->gl_owner) + { + gobj_dirty(&x->gl_gobj, x->gl_owner, + (n ? 1 : (x->gl_subdirties ? 2 : 0))); + x = x->gl_owner; + while(x->gl_owner) + { + x->gl_subdirties += ((unsigned)n ? 1 : -1); + if(!x->gl_dirty) + gobj_dirty(&x->gl_gobj, x->gl_owner, (x->gl_subdirties ? 2 : 0)); + x = x->gl_owner; + } + } +} + /* mark a glist dirty or clean */ void canvas_dirty(t_canvas *x, t_floatarg n) { @@ -768,6 +791,9 @@ void canvas_dirty(t_canvas *x, t_floatarg n) x2->gl_dirty = n; if (x2->gl_havewindow) canvas_reflecttitle(x2); + + /* set dirtiness visual markings */ + canvas_dirtyclimb(x2, (unsigned)n); } } diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h index 964d8fab820992ae09b20e49af661c5d8f472645..35669c27632de70e2f246415b102ade265c8451b 100644 --- a/pd/src/g_canvas.h +++ b/pd/src/g_canvas.h @@ -232,6 +232,8 @@ struct _glist t_symbol *gl_templatesym; /* for "canvas" data type */ t_word *gl_vec; /* for "canvas" data type */ t_gpointer gl_gp; /* parent for "canvas" data type */ + + int gl_subdirties; /* number of descending dirty abstractions */ }; #define gl_gobj gl_obj.te_g @@ -436,6 +438,7 @@ EXTERN void gobj_save(t_gobj *x, t_binbuf *b); EXTERN void gobj_properties(t_gobj *x, struct _glist *glist); EXTERN void gobj_save(t_gobj *x, t_binbuf *b); EXTERN int gobj_shouldvis(t_gobj *x, struct _glist *glist); +EXTERN void gobj_dirty(t_gobj *x, t_glist *g, int state); /* -------------------- functions on glists --------------------- */ EXTERN t_glist *glist_new( void); diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c index 15dfc84f01240e40f99a3d87cfda7f54eba0e0eb..088890360b2e136dcd538d2567aecb5734d634bc 100644 --- a/pd/src/g_editor.c +++ b/pd/src/g_editor.c @@ -1288,6 +1288,7 @@ void canvas_undo_paste(t_canvas *x, void *z, int action) } } +void canvas_dirtyclimb(t_canvas *x, int n); int clone_match(t_pd *z, t_symbol *name, t_symbol *dir); /* recursively check for abstractions to reload as result of a save. @@ -1313,6 +1314,11 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir, canvas_isabstraction((t_canvas *)g) && ((t_canvas *)g)->gl_name == name && canvas_getdir((t_canvas *)g) == dir); + + /* remove dirtiness visual markings */ + if(remakeit && ((t_canvas *)g)->gl_dirty) + canvas_dirtyclimb((t_canvas *)g, 0); + /* also remake it if it's a "clone" with that name */ if (pd_class(&g->g_pd) == clone_class && clone_match(&g->g_pd, name, dir)) @@ -5846,6 +5852,13 @@ static void gobj_emphasize(t_glist *g, t_gobj *x) gui_vmess("gui_gobj_emphasize", "xs", g, rtext_gettag(y)); } + /* tell the gui to mark a gobj as dirty (change border color) */ +void gobj_dirty(t_gobj *x, t_glist *g, int state) +{ + t_rtext *y = glist_findrtext(g, (t_text *)x); + gui_vmess("gui_gobj_dirty", "xsi", g, rtext_gettag(y), state); +} + static int glist_dofinderror(t_glist *gl, void *error_object) { t_gobj *g; diff --git a/pd/src/g_text.c b/pd/src/g_text.c index 2a1ef4879702c3c1e9827a7f05ebdf2e8e17111e..6c875164c9ca8ffcaa0423aa8571fc642f4f7a8e 100644 --- a/pd/src/g_text.c +++ b/pd/src/g_text.c @@ -2121,6 +2121,16 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis) text_drawborder(x, glist, rtext_gettag(y), rtext_width(y), rtext_height(y), 1); rtext_draw(y); + + /* check whether we have to tell the gui to mark + (border color) the gobj as dirty or not */ + if(pd_class(&x->te_pd) == canvas_class) + { + if (((t_canvas *)x)->gl_dirty) + gobj_dirty(x, glist, 1); + else if (((t_canvas *)x)->gl_subdirties) + gobj_dirty(x, glist, 2); + } } } else