Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions src/LiveCards.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1025,20 +1025,25 @@ _selection_objects(s::_ShapeChange) = isnothing(s.old) ? Any[s.new] : Any[s.new,
_shape_changed!(gui, obj, old, new)

An input on the card of `obj` changed the code of its constructor from `old` to `new`: the code of
its `origin` becomes `new` (the autosave writes it to the line of `obj`, see `_project_parts`), the
handles of `obj` in the pool draw it again (`BeamletOptics.rerender!`), and the change is recorded
in the undo history, see `_ShapeChange`.
its `origin` becomes `new` in the `gui` and in every window linked with it that shows `obj` (see
`open_system`), such that the window of the project saves it (the autosave writes it to the line of
`obj`, see `_project_parts`); the handles of `obj` in the pools of these windows draw it again
(`BeamletOptics.rerender!`), and the change is recorded in the undo history of the `gui`, see
`_ShapeChange`.
"""
function _shape_changed!(gui::LiveView, @nospecialize(obj), old::String, new::String)
comp = gui.components
# e.g. removed by the input
haskey(comp.origin, obj) || return nothing
comp.origin[obj] = merge(comp.origin[obj], (; code = new))
for oh in _pool_handles(gui, obj)
Base.invokelatest(BMO.rerender!, oh)
haskey(gui.components.origin, obj) || return nothing
for v in unique(objectid, Any[gui, gui.links.views...])
origin = v.components.origin
haskey(origin, obj) || continue
origin[obj] = merge(origin[obj], (; code = new))
for oh in _pool_handles(v, obj)
Base.invokelatest(BMO.rerender!, oh)
end
_update_selection_box!(v.controls)
end
_update_selection_box!(gui.controls)
comp.recording && _record_shape!(gui, obj, old)
gui.components.recording && _record_shape!(gui, obj, old)
return nothing
end

Expand Down
5 changes: 5 additions & 0 deletions src/LiveLinks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ function _link!(gui::LiveView, new::LiveView, system)
to.system[obj] = system
to.origin[obj] = get(from.origin, obj, nothing)
end
# the code of the objects and sources that the view started with as well, e.g. of a project:
# a change of their shape in `new` reaches the code of every view, see `_shape_changed!`
for obj in Iterators.flatten((system.objects, _sources_of(gui, system)))
haskey(from.origin, obj) && !haskey(to.origin, obj) && (to.origin[obj] = from.origin[obj])
end
for obj in from.removed
if haskey(from.source_systems, obj)
_has(from.source_systems[obj], system) || continue
Expand Down
26 changes: 26 additions & 0 deletions test/TestLiveProjectOwnTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,32 @@ end
close(gui)
end

@testset "a change of the shape in a second window is saved (#88)" begin
dir = project()
gui = open_project(dir; display = false, const_kw...)
k1 = obj(gui, :K1)
second = open_system(gui, only(GUI._systems(gui)); display = false)
select!(second, k1)
Makie.set_close_to!(card_widget(second, k1, :width), 40.0)
@test k1.shape.diameter ≈ 0.04
# the code in both windows, saved by the window of the project
@test second.components.origin[k1].code == "Block(0.04, 0.005)"
@test gui.components.origin[k1].code == "Block(0.04, 0.005)"
@test GUI._autosave!(gui; force = true) === :saved
@test startswith(line(dir, :K1), "@component K1 = Block(0.04, 0.005)")
# undo in the second window: the old shape again, also in the files
@test GUI._undo!(second.controls)
old = obj(gui, :K1)
@test old !== k1 && old.shape.diameter == 0.025
@test GUI._autosave!(gui; force = true) === :saved
@test startswith(line(dir, :K1), "@component K1 = Block(0.025, 0.005)")
@test GUI._redo!(second.controls)
@test GUI._autosave!(gui; force = true) === :saved
@test startswith(line(dir, :K1), "@component K1 = Block(0.04, 0.005)")
close(second)
close(gui)
end

@testset "a type without constructor_code" begin
dir = project()
gui = open_project(dir; display = false, const_kw...)
Expand Down
Loading