Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Gabriela Bittencourt
purr-data
Commits
84c03a78
Commit
84c03a78
authored
Sep 20, 2020
by
Guillem Bartrina
Browse files
Merge branch 'feature_privateabstractions2' into feature_privateabstractions_test
parents
edb80827
da0b4fc7
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
pd-lua
@
8eaaaa3c
Compare
b767c65b
...
8eaaaa3c
Subproject commit
b767c65b6607a1b2b80798a5ff4fb3e3c1d752a5
Subproject commit
8eaaaa3c39af8968248fab5659d4a4d2da4f1ed7
pd/nw/dialog_abstractions.html
0 → 100644
View file @
84c03a78
<!DOCTYPE html>
<html>
<head>
<link
id=
"page_style"
rel=
"stylesheet"
type=
"text/css"
href=
"css/default.css"
>
</head>
<body
class=
"dialog_body"
>
<div
class=
"container"
>
<form>
<fieldset
style=
"width: 90%; border: 2px solid grey"
>
<legend
data-i18n=
"abstractions.private"
></legend>
<strong
data-i18n=
"abstractions.global"
></strong>
<hr>
<table
style=
"width: 90%; table-layout: fixed;"
>
</table>
<br>
<strong
data-i18n=
"abstractions.local"
></strong>
<hr>
<table
style=
"width: 90%; table-layout: fixed;"
>
</table>
<br>
<button
id=
"selectall_button"
type=
"button"
onClick=
"selectall()"
data-i18n=
"[title]abstractions.selectall_tt"
style=
"float: right;"
>
<span
data-i18n=
"abstractions.selectall"
></span>
</button>
</fieldset>
<div
class=
"submit_buttons"
>
<button
id=
"delete_button"
type=
"button"
onClick=
"deleteselected()"
data-i18n=
"[title]abstractions.delete_tt"
>
<span
data-i18n=
"abstractions.delete"
></span>
</button>
</div>
<hr>
<fieldset
style=
"width: 90%; border: 2px solid grey"
>
<legend
data-i18n=
"abstractions.filebased"
></legend>
<i>
NOT IMPLEMENTED
</i>
<table
style=
"width: 90%; table-layout: fixed;"
>
</table>
</fieldset>
<hr>
<div
class=
"submit_buttons"
>
<button
type=
"button"
onClick=
"cancel()"
data-i18n=
"[title]abstractions.close_tt"
>
<span
data-i18n=
"abstractions.close"
></span>
</button>
</div>
</form>
</div>
<script>
"
use strict
"
;
var
gui
=
require
(
"
nw.gui
"
);
var
pdgui
=
require
(
"
./pdgui.js
"
);
// For translations
var
l
=
pdgui
.
get_local_string
;
pdgui
.
skin
.
apply
(
window
);
var
pd_object_callback
;
var
canvas
;
var
deletequeue
;
function
selectall
()
{
var
checkboxes
=
document
.
querySelectorAll
(
'
input[type="checkbox"]:not(:checked)
'
);
for
(
var
i
=
0
,
n
=
checkboxes
.
length
;
i
<
n
;
i
++
)
{
if
(
!
checkboxes
[
i
].
checked
)
{
checkboxes
[
i
].
click
();
}
}
}
function
deleteselected
()
{
pdgui
.
pdsend
(
pd_object_callback
,
"
delabstractions
"
,
Array
.
from
(
deletequeue
).
join
(
"
"
));
cancel
();
}
function
cancel
()
{
pdgui
.
pdsend
(
pd_object_callback
,
"
cancel
"
);
}
function
populate_form
(
attrs
)
{
var
filebased_abs
=
attrs
.
filebased_abs
,
private_abs
=
attrs
.
private_abs
,
i
,
zero
=
0
;
canvas
=
attrs
.
canvas
;
deletequeue
=
new
Set
();
var
tables
=
document
.
querySelectorAll
(
"
table
"
),
filebased_table
=
tables
[
2
],
privateglobal_table
=
tables
[
0
],
privatelocal_table
=
tables
[
1
];
for
(
i
=
0
;
i
<
filebased_abs
.
length
;
i
+=
2
)
{
var
row
=
document
.
createElement
(
"
tr
"
);
cell1
=
document
.
createElement
(
"
td
"
),
cell2
=
document
.
createElement
(
"
td
"
),
cell3
=
document
.
createElement
(
"
td
"
);
cell1
.
textContent
=
filebased_abs
[
i
];
cell1
.
style
.
setProperty
(
"
width
"
,
"
70%
"
);
cell2
.
textContent
=
filebased_abs
[
i
+
1
];
cell2
.
style
.
setProperty
(
"
width
"
,
"
20%
"
);
row
.
appendChild
(
cell1
);
row
.
appendChild
(
cell2
);
row
.
appendChild
(
cell3
);
filebased_table
.
appendChild
(
row
);
}
for
(
i
=
0
;
i
<
private_abs
.
length
;
i
+=
2
)
{
var
row
=
document
.
createElement
(
"
tr
"
),
cell1
=
document
.
createElement
(
"
td
"
),
cell2
=
document
.
createElement
(
"
td
"
),
cell3
=
document
.
createElement
(
"
td
"
);
cell1
.
textContent
=
private_abs
[
i
];
cell1
.
style
.
setProperty
(
"
width
"
,
"
70%
"
);
cell2
.
textContent
=
private_abs
[
i
+
1
];
cell2
.
style
.
setProperty
(
"
width
"
,
"
20%
"
);
if
(
private_abs
[
i
+
1
]
===
0
)
{
let
input_elem
=
document
.
createElement
(
"
input
"
),
j
=
i
;
input_elem
.
type
=
"
checkbox
"
;
input_elem
.
onchange
=
function
()
{
if
(
input_elem
.
checked
)
{
deletequeue
.
add
(
private_abs
[
j
]);
}
else
{
deletequeue
.
delete
(
private_abs
[
j
]);
}
get_elem
(
"
delete_button
"
).
disabled
=
(
deletequeue
.
size
===
0
);
console
.
log
(
deletequeue
.
size
);
};
cell3
.
appendChild
(
input_elem
);
zero
++
;
}
row
.
appendChild
(
cell1
);
row
.
appendChild
(
cell2
);
row
.
appendChild
(
cell3
);
if
(
private_abs
[
i
][
0
]
===
'
@
'
)
{
privatelocal_table
.
appendChild
(
row
);
}
else
{
privateglobal_table
.
appendChild
(
row
);
}
}
get_elem
(
"
selectall_button
"
).
disabled
=
(
zero
===
0
);
get_elem
(
"
delete_button
"
).
disabled
=
true
;
}
// This gets called from the nw_create_window function in index.html
// It provides us with our window id from the C side. Once we have it
// we can create the menu and register event callbacks
function
register_window_id
(
gfxstub
,
attrs
)
{
pd_object_callback
=
gfxstub
;
add_events
(
gfxstub
);
// not sure that we need this for properties windows
//pdgui.canvas_map(gfxstub);
translate_form
();
populate_form
(
attrs
);
// We don't turn on rendering of the "container" div until
// We've finished displaying all the spans and populating the
// labels and form elements. That makes it more efficient and
// snappier, at least on older machines.
document
.
getElementsByClassName
(
"
container
"
)[
0
].
style
.
setProperty
(
"
display
"
,
"
inline
"
);
gui
.
Window
.
get
().
setResizable
(
false
);
}
function
get_elem
(
name
)
{
return
document
.
getElementById
(
name
);
}
// Stop-gap translator
function
translate_form
()
{
var
elements
=
document
.
querySelectorAll
(
"
[data-i18n]
"
),
data
,
i
;
for
(
i
=
0
;
i
<
elements
.
length
;
i
++
)
{
data
=
elements
[
i
].
dataset
.
i18n
;
if
(
data
.
slice
(
0
,
7
)
===
"
[title]
"
)
{
elements
[
i
].
title
=
l
(
data
.
slice
(
7
));
}
else
{
elements
[
i
].
textContent
=
l
(
data
);
}
}
}
function
add_events
(
name
)
{
gui
.
Window
.
get
().
on
(
"
close
"
,
function
()
{
cancel
();
});
pdgui
.
dialog_bindings
(
name
);
}
</script>
</body>
</html>
pd/nw/dialog_external.html
View file @
84c03a78
...
...
@@ -149,7 +149,8 @@ function parse_attrs(attrs) {
if
(
token
.
length
>
1
)
{
elem
.
type
=
token
[
token
.
length
-
1
];
if
(
elem
.
type
!==
"
symbol
"
&&
elem
.
type
!==
"
toggle
"
)
{
elem
.
type
!==
"
toggle
"
&&
elem
.
type
!==
"
hidden
"
)
{
// no suffix defaults to "number"
elem
.
type
=
"
number
"
;
}
else
{
...
...
@@ -218,6 +219,7 @@ function get_input_type(t) {
return
t
===
"
symbol
"
?
"
text
"
:
t
===
"
number
"
?
"
text
"
:
t
===
"
toggle
"
?
"
checkbox
"
:
t
===
"
hidden
"
?
"
hidden
"
:
"
text
"
;
}
...
...
pd/nw/locales/en/translation.json
View file @
84c03a78
...
...
@@ -237,6 +237,8 @@
"visible_ancestor_tt"
:
"give focus to the closest ancestor of this window that is currently visible"
,
"pdwin"
:
"Pd Window"
,
"pdwin_tt"
:
"Give focus to the main Pd window"
,
"abstractions"
:
"Abstractions"
,
"abstractions_tt"
:
"Consult and handle abstractions"
,
"media"
:
"Media"
,
...
...
@@ -504,5 +506,17 @@
"building_index"
:
"Building index..."
,
"no_results"
:
"No results found."
,
"search_placeholder"
:
"Search Pd Docs"
},
"abstractions"
:
{
"filebased"
:
"File-based abstractions"
,
"private"
:
"Private abstractions"
,
"global"
:
"Global scope"
,
"local"
:
"Local scope"
,
"selectall"
:
"Select all"
,
"selectall_tt"
:
"Select all definitions with zero instances"
,
"delete"
:
"Delete"
,
"delete_tt"
:
"Delete all selected definitions"
,
"close"
:
"Close"
,
"close_tt"
:
"Close the dialog window"
}
}
pd/nw/pd_canvas.js
View file @
84c03a78
...
...
@@ -1417,6 +1417,41 @@ function nw_undo_menu(undo_text, redo_text) {
}
}
function
ab_callback
(
cid
,
name
)
{
return
function
()
{
pdgui
.
pdsend
(
cid
,
"
delab
"
,
name
);
}
}
function
nw_ab_menu
(
cid
,
definitions
)
{
while
(
canvas_menu
.
ab
.
this
.
items
.
length
>
2
)
canvas_menu
.
ab
.
this
.
removeAt
(
2
);
if
(
definitions
.
length
===
0
)
{
var
item
=
new
nw
.
MenuItem
({
label
:
"
Ø
"
,
enabled
:
false
});
canvas_menu
.
ab
.
this
.
append
(
item
);
canvas_menu
.
ab
.
clean
.
enabled
=
0
;
}
else
{
var
i
,
del
=
0
;
for
(
i
=
0
;
i
<
definitions
.
length
;
i
+=
2
)
{
var
item
=
new
nw
.
MenuItem
({
label
:
definitions
[
i
]
+
"
(
"
+
definitions
[
i
+
1
]
+
"
)
"
,
click
:
ab_callback
(
cid
,
definitions
[
i
]),
enabled
:
(
definitions
[
i
+
1
]
===
0
)
});
canvas_menu
.
ab
.
this
.
append
(
item
);
if
(
definitions
[
i
+
1
]
===
0
)
del
++
;
}
canvas_menu
.
ab
.
clean
.
enabled
=
(
del
>
0
);
}
}
function
have_live_box
()
{
var
state
=
canvas_events
.
get_state
();
if
(
state
===
"
text
"
||
state
===
"
floating_text
"
)
{
...
...
@@ -2008,6 +2043,12 @@ function nw_create_patch_window_menus(gui, w, name) {
pdgui
.
raise_pd_window
();
}
});
minit
(
m
.
win
.
abstractions
,
{
enabled
:
true
,
click
:
function
()
{
pdgui
.
pdsend
(
name
,
"
getabstractions
"
);
}
});
// Media menu
minit
(
m
.
media
.
audio_on
,
{
...
...
pd/nw/pd_menus.js
View file @
84c03a78
...
...
@@ -579,6 +579,11 @@ function create_menu(gui, type) {
key
:
shortcuts
.
menu
.
pdwin
.
key
,
modifiers
:
shortcuts
.
menu
.
pdwin
.
modifiers
}));
winman_menu
.
append
(
new
gui
.
MenuItem
({
type
:
"
separator
"
}));
winman_menu
.
append
(
m
.
win
.
abstractions
=
new
gui
.
MenuItem
({
label
:
l
(
"
menu.abstractions
"
),
tooltip
:
l
(
"
menu.abstractions_tt
"
)
}));
}
// Media menu
...
...
pd/nw/pdgui.js
View file @
84c03a78
...
...
@@ -6015,6 +6015,13 @@ function gui_external_dialog(did, external_name, attr_array) {
});
}
function
gui_abstractions_dialog
(
cid
,
gfxstub
,
filebased_abs
,
private_abs
)
{
var
attrs
=
{
canvas
:
cid
,
filebased_abs
:
filebased_abs
,
private_abs
:
private_abs
};
dialogwin
[
gfxstub
]
=
create_window
(
gfxstub
,
"
abstractions
"
,
300
,
600
,
0
,
0
,
attrs
);
}
// Global settings
function
gui_pd_dsp
(
state
)
{
...
...
pd/src/g_canvas.c
View file @
84c03a78
This diff is collapsed.
Click to expand it.
pd/src/g_canvas.h
View file @
84c03a78
...
...
@@ -164,6 +164,24 @@ typedef struct _tick /* where to put ticks on x or y axes */
int
k_lperb
;
/* little ticks per big; 0 if no ticks to draw */
}
t_tick
;
/* the t_ab_definition structure holds an ab definiton and all the attributes we need
to handle it */
typedef
struct
_ab_definition
{
t_symbol
*
ad_name
;
/* id for the ab definition */
t_binbuf
*
ad_source
;
/* binbuf where the source is stored */
int
ad_numinstances
;
/* number of instances */
struct
_ab_definition
*
ad_next
;
/* next ab definition */
t_canvas
*
ad_owner
;
/* canvas that stores this definition */
/* dependency graph stuff */
int
ad_numdep
;
/* number of other ab definitions that it depends on */
struct
_ab_definition
**
ad_dep
;
/* the actual ab defintitions */
int
*
ad_deprefs
;
/* number of instances that define the dependency */
int
ad_visflag
;
/* visited flag for topological sort algorithm */
}
t_ab_definition
;
/* the t_glist structure, which describes a list of elements that live on an
area of a window.
...
...
@@ -236,6 +254,11 @@ struct _glist
int
gl_subdirties
;
/* number of descending dirty abstractions */
int
gl_dirties
;
/* number of diry instances, for multiple dirty warning */
unsigned
int
gl_isab
:
1
;
/* is an ab instance */
t_ab_definition
*
gl_absource
;
/* ab definition pointer,
in the case it is an ab instance */
t_ab_definition
*
gl_abdefs
;
/* stored ab definitions */
};
#define gl_gobj gl_obj.te_g
...
...
@@ -554,6 +577,7 @@ EXTERN void canvas_setcurrent(t_canvas *x);
EXTERN
void
canvas_unsetcurrent
(
t_canvas
*
x
);
EXTERN
t_symbol
*
canvas_realizedollar
(
t_canvas
*
x
,
t_symbol
*
s
);
EXTERN
t_canvas
*
canvas_getrootfor
(
t_canvas
*
x
);
EXTERN
t_canvas
*
canvas_getrootfor_ab
(
t_canvas
*
x
);
EXTERN
void
canvas_dirty
(
t_canvas
*
x
,
t_floatarg
n
);
EXTERN
int
canvas_getfont
(
t_canvas
*
x
);
typedef
int
(
*
t_canvasapply
)(
t_canvas
*
x
,
t_int
x1
,
t_int
x2
,
t_int
x3
);
...
...
pd/src/g_clone.c
View file @
84c03a78
...
...
@@ -63,6 +63,7 @@ typedef struct _clone
int
x_phase
;
int
x_startvoice
;
/* number of first voice, 0 by default */
int
x_suppressvoice
;
/* suppress voice number as $1 arg */
t_canvas
*
x_owner
;
/* clone owner */
}
t_clone
;
/* the given 'it' function is executed over each of the underlying canvases
...
...
@@ -80,8 +81,23 @@ int clone_match(t_pd *z, t_symbol *name, t_symbol *dir)
t_clone
*
x
=
(
t_clone
*
)
z
;
if
(
!
x
->
x_n
)
return
(
0
);
return
(
x
->
x_vec
[
0
].
c_gl
->
gl_name
==
name
&&
canvas_getdir
(
x
->
x_vec
[
0
].
c_gl
)
==
dir
);
return
(
!
x
->
x_vec
[
0
].
c_gl
->
gl_isab
&&
x
->
x_vec
[
0
].
c_gl
->
gl_name
==
name
&&
canvas_getdir
(
x
->
x_vec
[
0
].
c_gl
)
==
dir
);
}
int
clone_isab
(
t_pd
*
z
)
{
t_clone
*
x
=
(
t_clone
*
)
z
;
if
(
!
x
->
x_n
)
return
(
0
);
return
(
x
->
x_vec
[
0
].
c_gl
->
gl_isab
);
}
int
clone_matchab
(
t_pd
*
z
,
t_ab_definition
*
source
)
{
t_clone
*
x
=
(
t_clone
*
)
z
;
return
(
clone_isab
(
z
)
&&
x
->
x_vec
[
0
].
c_gl
->
gl_absource
==
source
);
}
void
obj_sendinlet
(
t_object
*
x
,
int
n
,
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
);
...
...
@@ -185,6 +201,13 @@ static void clone_free(t_clone *x)
for
(
i
=
0
;
i
<
x
->
x_n
;
i
++
)
{
canvas_closebang
(
x
->
x_vec
[
i
].
c_gl
);
if
(
x
->
x_vec
[
i
].
c_gl
->
gl_isab
)
{
/* crude hack. since clones don't have owner,
we set it manually to allow the clone to
deregister the dependencies */
x
->
x_vec
[
i
].
c_gl
->
gl_owner
=
x
->
x_owner
;
}
pd_free
(
&
x
->
x_vec
[
i
].
c_gl
->
gl_pd
);
t_freebytes
(
x
->
x_outvec
[
i
],
x
->
x_nout
*
sizeof
(
*
x
->
x_outvec
[
i
]));
...
...
@@ -238,7 +261,8 @@ void clone_setn(t_clone *x, t_floatarg f)
{
t_canvas
*
c
;
t_out
*
outvec
;
SETFLOAT
(
x
->
x_argv
,
x
->
x_startvoice
+
i
);
/* in the case they are [ab]s, the instance number is one atom beyond */
SETFLOAT
((
x
->
x_vec
[
0
].
c_gl
->
gl_isab
?
x
->
x_argv
+
1
:
x
->
x_argv
),
x
->
x_startvoice
+
i
);
if
(
!
(
c
=
clone_makeone
(
x
->
x_s
,
x
->
x_argc
-
x
->
x_suppressvoice
,
x
->
x_argv
+
x
->
x_suppressvoice
)))
{
...
...
@@ -364,6 +388,7 @@ static void clone_dsp(t_clone *x, t_signal **sp)
}
}
static
int
clone_newabclone
=
0
;
static
void
*
clone_new
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
)
{
t_clone
*
x
=
(
t_clone
*
)
pd_new
(
clone_class
);
...
...
@@ -403,10 +428,27 @@ static void *clone_new(t_symbol *s, int argc, t_atom *argv)
else
goto
usage
;
/* store a copy of the argmuents with an extra space (argc+1) for
supplying an instance number, which we'll bash as we go. */
x
->
x_argc
=
argc
-
1
;
x
->
x_argv
=
getbytes
(
x
->
x_argc
*
sizeof
(
*
x
->
x_argv
));
memcpy
(
x
->
x_argv
,
argv
+
1
,
x
->
x_argc
*
sizeof
(
*
x
->
x_argv
));
SETFLOAT
(
x
->
x_argv
,
x
->
x_startvoice
);
if
(
clone_newabclone
)
/* we are creating a clone from an [ab] definition, we use the same creation
method as for normal clones but the name we pass to objectmaker is
'ab <name>' instead of just '<name>' */
{
x
->
x_argc
=
argc
;
x
->
x_argv
=
getbytes
(
x
->
x_argc
*
sizeof
(
*
x
->
x_argv
));
memcpy
(
x
->
x_argv
,
argv
,
x
->
x_argc
*
sizeof
(
*
x
->
x_argv
));
SETSYMBOL
(
x
->
x_argv
,
x
->
x_s
);
SETFLOAT
(
x
->
x_argv
+
1
,
x
->
x_startvoice
);
x
->
x_s
=
gensym
(
"ab"
);
x
->
x_owner
=
canvas_getcurrent
();
clone_newabclone
=
0
;
}
else
{
x
->
x_argc
=
argc
-
1
;
x
->
x_argv
=
getbytes
(
x
->
x_argc
*
sizeof
(
*
x
->
x_argv
));
memcpy
(
x
->
x_argv
,
argv
+
1
,
x
->
x_argc
*
sizeof
(
*
x
->
x_argv
));
SETFLOAT
(
x
->
x_argv
,
x
->
x_startvoice
);
}
if
(
!
(
c
=
clone_makeone
(
x
->
x_s
,
x
->
x_argc
-
x
->
x_suppressvoice
,
x
->
x_argv
+
x
->
x_suppressvoice
)))
goto
fail
;
...
...
@@ -454,10 +496,20 @@ fail:
return
(
0
);
}
/* creator for [ab]-based clones */
static
void
*
abclone_new
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
)
{
clone_newabclone
=
1
;
return
clone_new
(
s
,
argc
,
argv
);
}
void
clone_setup
(
void
)
{
clone_class
=
class_new
(
gensym
(
"clone"
),
(
t_newmethod
)
clone_new
,
(
t_method
)
clone_free
,
sizeof
(
t_clone
),
CLASS_NOINLET
,
A_GIMME
,
0
);
class_addcreator
((
t_newmethod
)
abclone_new
,
gensym
(
"abclone"
),
A_GIMME
,
0
);
class_addmethod
(
clone_class
,
(
t_method
)
clone_click
,
gensym
(
"click"
),
A_FLOAT
,
A_FLOAT
,
A_FLOAT
,
A_FLOAT
,
A_FLOAT
,
0
);
class_addmethod
(
clone_class
,
(
t_method
)
clone_loadbang
,
gensym
(
"loadbang"
),
...
...
pd/src/g_editor.c
View file @
84c03a78
...
...
@@ -1288,7 +1288,21 @@ void canvas_undo_paste(t_canvas *x, void *z, int action)
}
}
void
canvas_dirtyclimb
(
t_canvas
*
x
,
int
n
);
void
clone_iterate
(
t_pd
*
z
,
t_canvas_iterator
it
,
void
*
data
);
int
clone_match
(
t_pd
*
z
,
t_symbol
*
name
,
t_symbol
*
dir
);
int
clone_isab
(
t_pd
*
z
);
int
clone_matchab
(
t_pd
*
z
,
t_ab_definition
*
source
);
/* packed data passing structure for glist_doreload */
typedef
struct
_reload_data
{
t_symbol
*
n
;
t_symbol
*
d
;
t_gobj
*
e
;
}
t_reload_data
;
static
void
glist_doreload_packed
(
t_canvas
*
x
,
t_reload_data
*
data
);
/* recursively check for abstractions to reload as result of a save.
Don't reload the one we just saved ("except") though. */
...
...
@@ -1310,7 +1324,7 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
/* remake the object if it's an abstraction that appears to have
been loaded from the file we just saved */
remakeit
=
(
g
!=
except
&&
pd_class
(
&
g
->
g_pd
)
==
canvas_class
&&
canvas_isabstraction
((
t_canvas
*
)
g
)
&&
canvas_isabstraction
((
t_canvas
*
)
g
)
&&
!
((
t_canvas
*
)
g
)
->
gl_isab
&&
((
t_canvas
*
)
g
)
->
gl_name
==
name
&&
canvas_getdir
((
t_canvas
*
)
g
)
==
dir
);
...
...
@@ -1375,16 +1389,32 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
if
(
g
!=
except
&&
pd_class
(
&
g
->
g_pd
)
==
canvas_class
&&
(
!
canvas_isabstraction
((
t_canvas
*
)
g
)
||
((
t_canvas
*
)
g
)
->
gl_isab
||
((
t_canvas
*
)
g
)
->
gl_name
!=
name
||
canvas_getdir
((
t_canvas
*
)
g
)
!=
dir
)
)
glist_doreload
((
t_canvas
*
)
g
,
name
,
dir
,
except
);
/* also reload the instances within ab-based clone objects
*COMMENT: missing recursive case for abstraction-based clone
objects that don't match with the one we are reloading? */
if
(
pd_class
(
&
g
->
g_pd
)
==
clone_class
&&
clone_isab
(
&
g
->
g_pd
))
{
t_reload_data
d
;
d
.
n
=
name
;
d
.
d
=
dir
;
d
.
e
=
except
;
clone_iterate
(
&
g
->
g_pd
,
glist_doreload_packed
,
&
d
);
}
g
=
g
->
g_next
;
}
if
(
!
hadwindow
&&
gl
->
gl_havewindow
)
canvas_vis
(
glist_getcanvas
(
gl
),
0
);
}
static
void
glist_doreload_packed
(
t_canvas
*
x
,
t_reload_data
*
data
)
{
glist_doreload
(
x
,
data
->
n
,
data
->
d
,
data
->
e
);
}
/* this flag stops canvases from being marked "dirty" if we have to touch
them to reload an abstraction; also suppress window list update */
int
glist_amreloadingabstractions
=
0
;
...
...
@@ -1402,6 +1432,93 @@ void canvas_reload(t_symbol *name, t_symbol *dir, t_gobj *except)
canvas_resume_dsp
(
dspwas
);
}
/* packed data passing structure for glist_doreload_ab */
typedef
struct
_reload_ab_data
{
t_ab_definition
*
a
;
t_gobj
*
e
;
}
t_reload_ab_data
;
static
void
glist_doreload_ab_packed
(
t_canvas
*
x
,
t_reload_ab_data
*
data
);
/* recursive ab reload method */
static
void
glist_doreload_ab
(
t_canvas
*
x
,
t_ab_definition
*
a
,
t_gobj
*
e
)
{
t_gobj
*
g
;
int
i
,
nobj
=
glist_getindex
(
x
,
0
);
int
found
=
0
,
remakeit
=
0
;
for
(
g
=
x
->
gl_list
,
i
=
0
;
g
&&
i
<
nobj
;
i
++
)
{
remakeit
=
(
g
!=
e
&&
pd_class
(
&
g
->
g_pd
)
==
canvas_class
&&
canvas_isabstraction
((
t_canvas
*
)
g
)
&&
((
t_canvas
*
)
g
)
->
gl_isab
&&
((
t_canvas
*
)
g
)
->
gl_absource
==
a
);
/* remove dirtiness visual markings */
if
(
remakeit
&&
((
t_canvas
*
)
g
)
->
gl_dirty
)
canvas_dirtyclimb
((
t_canvas
*
)
g
,
0
);
remakeit
=
remakeit
||
(
pd_class
(
&
g
->
g_pd
)
==
clone_class
&&
clone_matchab
(
&
g
->
g_pd
,
a
));
if
(
remakeit
)
{
canvas_create_editor
(
x
);
if
(
!
found
)
{
glist_noselect
(
x
);
found
=
1
;
}
glist_select
(
x
,
g
);
}
/* since this one won't be reloaded, we need to trigger initbang manually */
else
if
(
g
==
e
)
canvas_initbang
((
t_canvas
*
)
g
);
g
=
g
->
g_next
;
}
if
(
found
)