Commit 7f0ae827 authored by Jonathan Wilkes's avatar Jonathan Wilkes
Browse files

Merge branch 'guillembartrina/purr-data-feature-dirtywarnings-rebased'

parents ffea3cd5 8bf3e10e
......@@ -297,6 +297,10 @@
"none": "Keinen",
"none_tt": "Ersetze keinen der Subpatches"
},
"warning": {
"unsaved_tt": "Es gibt ein ungesichertes Exemplar dieser Abstraktion",
"multipleunsaved_tt": "Es gibt ein weiteres ungesichertes Exemplar dieser Abstraktion"
},
"find": {
"placeholder": "Suche im Patch",
"search": "Suche",
......
......@@ -297,6 +297,10 @@
"none": "None",
"none_tt": "Do not replace any subpatch"
},
"warning": {
"unsaved_tt": "There is an unsaved edited instance of this abstraction",
"multipleunsaved_tt": "There is another unsaved edited instance of this abstraction"
},
"find": {
"placeholder": "Search in Canvas",
"search": "Search",
......
......@@ -297,6 +297,10 @@
"none": "Aucun",
"none_tt": "Ne remplacer aucun sous-patch"
},
"warning": {
"unsaved_tt": "Il existe une instance modifiée non enregistrée de cette abstraction",
"multipleunsaved_tt": "Il existe une autre instance modifiée non enregistrée de cette abstraction"
},
"find": {
"placeholder": "Chercher dans le Canevas",
"search": "Chercher",
......
......@@ -102,6 +102,9 @@
</button>
</div>
</dialog>
<div style="position: fixed; right: 2%; top: 2%; ">
<strong id="canvas_warning" style="display: none; text-align: right; -webkit-user-select: none; cursor: pointer;">!</strong>
</div>
<div id="hscroll" style="position: fixed; left: 0px; bottom: 0px; border-radius: 0px; width: 10px; height: 5px; visibility: hidden;"></div>
<div id="vscroll" style="position: fixed; right: 0px; top: 0px; border-radius: 0px; width: 5px; height: 10px; visibility: hidden;"></div>
<script type="text/javascript" src="./pd_canvas.js"></script>
......
......@@ -1336,6 +1336,9 @@ function register_window_id(cid, attr_array) {
// we check the title_queue to see if our title now contains an asterisk
// (which is the visual cue for "dirty")
// Enable/disable the warning for multiple dirty instances
pdgui.gui_canvas_warning(cid, attr_array.warid);
// Two possibilities for handling this better:
// have a representation of canvas attys in pdgui.js (editmode, dirty, etc.)
// or
......
......@@ -1760,7 +1760,7 @@ function create_window(cid, type, width, height, xpos, ypos, attr_array) {
}
// create a new canvas
function gui_canvas_new(cid, width, height, geometry, grid, zoom, editmode, name, dir, dirty_flag, hide_scroll, hide_menu, has_toplevel_scalars, cargs) {
function gui_canvas_new(cid, width, height, geometry, grid, zoom, editmode, name, dir, dirty_flag, warid, hide_scroll, hide_menu, has_toplevel_scalars, cargs) {
// hack for buggy tcl popups... should go away for node-webkit
//reset_ctrl_on_popup_window
......@@ -1817,6 +1817,7 @@ function gui_canvas_new(cid, width, height, geometry, grid, zoom, editmode, name
name: name,
dir: dir,
dirty: dirty_flag,
warid: warid,
args: cargs,
zoom: zoom,
editmode: editmode,
......@@ -2860,6 +2861,35 @@ function gui_gobj_dirty(cid, tag, state) {
});
}
function gui_canvas_warning(cid, warid) {
var warning = get_item(cid, "canvas_warning");
switch(warid)
{
case 0:
warning.style.setProperty("display", "none");
break;
case 1:
warning.title = lang.get_local_string("canvas.warning.unsaved_tt");
warning.onclick = function(){ pdsend(cid, "showdirty"); }
warning.style.setProperty("color", "coral");
warning.style.setProperty("font-size", "x-large");
warning.style.setProperty("display", "inline");
break;
case 2:
warning.title = lang.get_local_string("canvas.warning.multipleunsaved_tt");
warning.onclick = function(){ pdsend(cid, "showdirty"); }
warning.style.setProperty("color", "red");
warning.style.setProperty("font-size", "xx-large");
warning.style.setProperty("display", "inline");
break;
default:
break;
}
}
exports.gui_canvas_warning = gui_canvas_warning;
function gui_canvas_emphasize(cid) {
gui(cid).get_elem("patchsvg", function(e) {
// raise the window
......
......@@ -396,6 +396,8 @@ static int calculate_zoom(t_float zoom_hack)
return zoom;
}
int canvas_dirty_broadcast_all(t_symbol *name, t_symbol *dir, int mess);
/* make a new glist. It will either be a "root" canvas or else
it appears as a "text" object in another window (canvas_getcurrent()
tells us which.) */
......@@ -472,6 +474,7 @@ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv)
else x->gl_env = 0;
x->gl_subdirties = 0;
x->gl_dirties = 0;
if (yloc < GLIST_DEFCANVASYLOC)
yloc = GLIST_DEFCANVASYLOC;
......@@ -522,6 +525,14 @@ t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv)
canvas_field_vec = NULL;
canvas_field_gp = NULL;
/* in the case it is an abstraction (gl_env is not null)
get the number of dirty instances of this same abstraction */
if(x->gl_env)
{
x->gl_dirties = canvas_dirty_broadcast_all(x->gl_name,
canvas_getdir(x), 0);
}
return(x);
}
......@@ -792,6 +803,100 @@ void canvas_dirtyclimb(t_canvas *x, int n)
}
}
/* the following functions are used to broadcast messages to all instances of
a specific abstraction (either file-based or ab).
the state of these instances change accoring to the message sent. */
void clone_iterate(t_pd *z, t_canvas_iterator it, void* data);
int clone_match(t_pd *z, t_symbol *name, t_symbol *dir);
static void canvas_dirty_common(t_canvas *x, int mess)
{
if(mess == 2)
{
if(x->gl_dirty)
{
if(!x->gl_havewindow) canvas_vis(x, 1);
gui_vmess("gui_canvas_emphasize", "x", x);
}
}
else
{
x->gl_dirties += mess;
if(x->gl_havewindow)
canvas_warning(x, (x->gl_dirties > 1 ?
(x->gl_dirty ? 2 : 1)
: (x->gl_dirties ? !x->gl_dirty : 0)));
}
}
/* packed data passing structure for canvas_dirty_broadcast */
typedef struct _dirty_broadcast_data
{
t_symbol *name;
t_symbol *dir;
int mess;
int *res; /* return value */
} t_dirty_broadcast_data;
static void canvas_dirty_deliver_packed(t_canvas *x, t_dirty_broadcast_data *data)
{
*data->res += (x->gl_dirty > 0);
canvas_dirty_common(x, data->mess);
}
static int canvas_dirty_broadcast_packed(t_canvas *x, t_dirty_broadcast_data *data);
static int canvas_dirty_broadcast(t_canvas *x, t_symbol *name, t_symbol *dir, int mess)
{
int res = 0;
t_gobj *g;
for (g = x->gl_list; g; g = g->g_next)
{
if(pd_class(&g->g_pd) == canvas_class)
{
if(canvas_isabstraction((t_canvas *)g)
&& ((t_canvas *)g)->gl_name == name
&& canvas_getdir((t_canvas *)g) == dir)
{
res += (((t_canvas *)g)->gl_dirty > 0);
canvas_dirty_common((t_canvas *)g, mess);
}
else
res += canvas_dirty_broadcast((t_canvas *)g, name, dir, mess);
}
else if(pd_class(&g->g_pd) == clone_class)
{
int cres = 0;
t_dirty_broadcast_data data;
data.name = name; data.dir = dir; data.mess = mess; data.res = &cres;
if(clone_match(&g->g_pd, name, dir))
{
clone_iterate(&g->g_pd, canvas_dirty_deliver_packed, &data);
}
else
{
clone_iterate(&g->g_pd, canvas_dirty_broadcast_packed, &data);
}
res += cres;
}
}
return (res);
}
static int canvas_dirty_broadcast_packed(t_canvas *x, t_dirty_broadcast_data *data)
{
*data->res = canvas_dirty_broadcast(x, data->name, data->dir, data->mess);
}
int canvas_dirty_broadcast_all(t_symbol *name, t_symbol *dir, int mess)
{
int res = 0;
t_canvas *x;
for (x = pd_this->pd_canvaslist; x; x = x->gl_next)
res += canvas_dirty_broadcast(x, name, dir, mess);
return (res);
}
/* mark a glist dirty or clean */
void canvas_dirty(t_canvas *x, t_floatarg n)
{
......@@ -806,6 +911,15 @@ void canvas_dirty(t_canvas *x, t_floatarg n)
/* set dirtiness visual markings */
canvas_dirtyclimb(x2, (unsigned)n);
/* in the case it is an abstraction, we tell all other
instances that there is eiher one more dirty instance or
one less dirty instance */
if(canvas_isabstraction(x2)
&& (x2->gl_owner || x2->gl_isclone))
{
canvas_dirty_broadcast_all(x2->gl_name, canvas_getdir(x2),
(x2->gl_dirty ? 1 : -1));
}
}
}
......@@ -1034,6 +1148,15 @@ extern void canvas_group_free(t_pd *x);
void canvas_free(t_canvas *x)
{
//fprintf(stderr,"canvas_free %zx\n", (t_uint)x);
/* in the case it is a dirty abstraction, we tell all other
instances that there is one less dirty instance */
if(canvas_isabstraction(x) && x->gl_dirty
&& (x->gl_owner || x->gl_isclone))
{
canvas_dirty_broadcast_all(x->gl_name, canvas_getdir(x), -1);
}
t_gobj *y;
int dspstate = canvas_suspend_dsp();
......@@ -1893,6 +2016,13 @@ void canvas_redrawallfortemplatecanvas(t_canvas *x, int action)
canvas_redrawallfortemplate(0, action);
}
/* --------- */
static void canvas_showdirty(t_canvas *x)
{
canvas_dirty_broadcast_all(x->gl_name, canvas_getdir(x), 2);
}
/* ------------------------------- declare ------------------------ */
/* put "declare" objects in a patch to tell it about the environment in
......@@ -2765,6 +2895,8 @@ void g_canvas_setup(void)
class_addcreator((t_newmethod)table_new, gensym("table"),
A_DEFSYM, A_DEFFLOAT, 0);
class_addmethod(canvas_class, (t_method)canvas_showdirty,
gensym("showdirty"), 0);
/*---------------------------- declare ------------------- */
declare_class = class_new(gensym("declare"), (t_newmethod)declare_new,
(t_method)declare_free, sizeof(t_declare), CLASS_NOINLET, A_GIMME, 0);
......
......@@ -235,6 +235,7 @@ struct _glist
t_gpointer gl_gp; /* parent for "canvas" data type */
int gl_subdirties; /* number of descending dirty abstractions */
int gl_dirties; /* number of diry instances, for multiple dirty warning */
};
#define gl_gobj gl_obj.te_g
......@@ -581,6 +582,7 @@ EXTERN int canvas_setdeleting(t_canvas *x, int flag);
EXTERN int canvas_hasarray(t_canvas *x);
EXTERN int canvas_has_scalars_only(t_canvas *x);
EXTERN void canvas_warning(t_canvas *x, int warid);
#define LB_LOAD 0 /* "loadbang" actions - 0 for original meaning */
#define LB_INIT 1 /* loaded but not yet connected to parent patch */
......
......@@ -2752,7 +2752,7 @@ void canvas_vis(t_canvas *x, t_floatarg f)
We may need to expand this to include scalars, as well. */
canvas_create_editor(x);
canvas_args_to_string(argsbuf, x);
gui_vmess("gui_canvas_new", "xiisiiissiiiis",
gui_vmess("gui_canvas_new", "xiisiiissiiiiis",
x,
(int)(x->gl_screenx2 - x->gl_screenx1),
(int)(x->gl_screeny2 - x->gl_screeny1),
......@@ -2763,6 +2763,9 @@ void canvas_vis(t_canvas *x, t_floatarg f)
x->gl_name->s_name,
canvas_getdir(x)->s_name,
x->gl_dirty,
(x->gl_dirties > 1 ?
(x->gl_dirty ? 2 : 1)
: (x->gl_dirties ? !x->gl_dirty : 0)),
x->gl_noscroll,
x->gl_nomenu,
canvas_hasarray(x),
......@@ -6171,6 +6174,12 @@ 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);
}
/* tell the gui to display a specific message in the
top right corner */
void canvas_warning(t_canvas *x, int warid)
{
gui_vmess("gui_canvas_warning", "xi", x, warid);
}
static int glist_dofinderror(t_glist *gl, void *error_object)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment