From 7301e935c56ab1511c775ffd2dbbb8da3b6b3a44 Mon Sep 17 00:00:00 2001 From: Guillem <guillembartrina@gmail.com> Date: Fri, 4 Sep 2020 13:13:35 +0200 Subject: [PATCH] add mechanism that visually marks abstraction objects that are edited but unsaved, and all their ancestors --- pd/nw/css/default.css | 8 ++++++++ pd/nw/pdgui.js | 10 ++++++++++ pd/src/g_canvas.c | 26 ++++++++++++++++++++++++++ pd/src/g_canvas.h | 3 +++ pd/src/g_editor.c | 13 +++++++++++++ pd/src/g_text.c | 10 ++++++++++ 6 files changed, 70 insertions(+) diff --git a/pd/nw/css/default.css b/pd/nw/css/default.css index 5abd5f15e..396a40fad 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 d172ee900..465593cea 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 e29d802d7..f1a8279e2 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 964d8fab8..35669c276 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 15dfc84f0..088890360 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 2a1ef4879..6c875164c 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 -- GitLab