diff --git a/src/GUI.jl b/src/GUI.jl index 60356902b0f016c4b95403b5a73f25406b0c657d..25aea7c645546f10219b644834dde59c5523295f 100644 --- a/src/GUI.jl +++ b/src/GUI.jl @@ -6,16 +6,17 @@ function loadsimulation(filename) global model - launching[] = true + @emit showSplash() fn = convert(filename, String) startswith(fn, "file://") && (fn = fn[8:end]) - model = loadmodelobject(fn) running[] = false + model = loadmodelobject(fn) landcovermap = rotr90(load(@param(world.landcovermap))) date[] = model.date progress[] = (date[]-@param(core.startdate)) / (@param(core.enddate)-@param(core.startdate)) - launching[] = false + @emit closeSplash() + @emit updateMakie() println("Loaded simulation.") end @@ -36,21 +37,6 @@ function Base.convert(s::QString, ::Type{<:AbstractString}) end #TODO saveoutput() - -function togglerunning() - global runsimulation, timer - if running[] - running[] = false - QML.stop(timer) - runbuttontext[] = ">>" - runbuttontip[] = "Run" - else - running[] = true - runbuttontext[] = "||" - runbuttontip[] = "Pause" - QML.start(timer) - end -end function render_map(screen) global model, mapimage, landcovermap @@ -108,22 +94,31 @@ end on(launching) do l if l @emit showSplash() + println("Showing splash screen.") #XXX DEBUG else @emit closeSplash() @emit updateMakie() end end +on(running) do r + if r + runbuttontext[] = "||" + runbuttontip[] = "Pause" + else + runbuttontext[] = ">>" + runbuttontip[] = "Run" + end +end + datestring = () -> Dates.format(date[], "dd U yyyy") -function activateqmlfunctions() - @qmlfunction newsimulation +function activateqmlfunctions() @qmlfunction configwindow @qmlfunction loadsimulation @qmlfunction savesimulation @qmlfunction nextstep @qmlfunction previousstep - @qmlfunction togglerunning @qmlfunction datestring @qmlfunction writeconfig end @@ -149,12 +144,7 @@ function launch() vars = JuliaPropertyMap(guiproperties...), render_map_callback = @safe_cfunction(render_map, Cvoid, (Any,)), render_plot_callback = @safe_cfunction(render_plot, Cvoid, (Any,))) - launching[] = true - if isnothing(model) - #QML.start(timer) - #newsimulation() - #QML.stop(timer) - end + isnothing(model) && (launching[] = true) # initiates model initialisation println("Launched Persefone Desktop.") - exec() #TODO how do I make this async? -> change to Threads.@spawn? + exec() end diff --git a/src/logic.jl b/src/logic.jl index 3ae716528f7e7e9019ecb1953cb79ddf73ba11bf..ddf660780fda8779c6e64745de909bcb9f4341e2 100644 --- a/src/logic.jl +++ b/src/logic.jl @@ -3,17 +3,18 @@ ### This file manages the model initialisation and run functions. ### - -function newsimulation() +@resumable function createlaunchfunction() global model, landcovermap - launching[] = true # trigger the launch screen + Ps = Persefone running[] = false progress[] = 0.0 + @yield 1 model = initialise(configfile[]) + @yield 1 landcovermap = rotr90(load(@param(world.landcovermap))) date[] = model.date launching[] = false - println("Model initialised.") + println("Model initialised (resumable).") end function nextstep() @@ -39,6 +40,23 @@ function nextstep() println("Updated model: $(date[]-Day(1))") end +#XXX This could also be done with Channels rather than ResumableFunctions, +# which would save us one dependency (Channels are inbuilt). However, the +# ResumableFunctions version seemed to work more smoothly. +@resumable function createrunfunction() + i = round(delay[]*20) + while running[] + i -= 1 + if i <= 0 + nextstep() + i = round(delay[]*20) + end + # to reduce interface lag, always only sleep for 50ms + sleep(0.05) + @yield 1 + end +end + function previousstep() # Since we store all model output in a dataframe, we can simply # "scroll back" in time and visualise the state of the model at @@ -52,31 +70,30 @@ function previousstep() println("Backtracked model: $(date[]-Day(1))") end -#XXX This could also be done with Channels rather than ResumableFunctions, -# which would save us one dependency (Channels are inbuilt). However, the -# ResumableFunctions version seemed to work more smoothly. -@resumable function createrunfunction() - i = round(delay[]*10) - while running[] - i -= 1 - if i <= 0 - nextstep() - i = round(delay[]*10) - end - # to reduce interface lag, always only sleep for 0.1s - sleep(0.1) - @yield 1 +on(launching; priority=10) do l + if l + QML.start(timer) + global newsimulation = createlaunchfunction() + println("Setting up model.") + else + QML.stop(timer) + println("Model setup complete.") end end - -on(running) do r - ticks = 0 #prevent overflows - runsimulation = createrunfunction() - r ? println("Simulation started.") : println("Simulation stopped.") #XXX DEBUG +on(running; priority=10) do r + if r + QML.start(timer) + global runsimulation = createrunfunction() + println("Simulation started.") + else + !launching[] && QML.stop(timer) + println("Simulation stopped.") + end end on(ticks) do t - #launching[] && #FIXME + launching[] && newsimulation() running[] && runsimulation() + t >= typemax(Int32) && (ticks[] = 0) #prevent overflow end diff --git a/src/main.qml b/src/main.qml index f06c1898ead9c393b55b4f0307d005df3566d8eb..28be96994a3e630496cc1a9196e6a958eb7d10ce 100644 --- a/src/main.qml +++ b/src/main.qml @@ -22,7 +22,7 @@ ApplicationWindow { title: "&Simulation" Action { text: "&New Simulation" - onTriggered: { Julia.newsimulation() } //TODO select config file + onTriggered: { vars.launching = true } //TODO select config file } Action { text: "&Configure Simulation" @@ -110,7 +110,7 @@ ApplicationWindow { text: vars.runbuttontext ToolTip.text: vars.runbuttontip ToolTip.visible: hovered - onClicked: { Julia.togglerunning() } + onClicked: { vars.running = !vars.running } } ProgressBar { id: progressBar diff --git a/src/variables.jl b/src/variables.jl index b2a6b85de9cb40e50a9964d743c2853ee3c50d55..01a87ef76ce703ca16ebb5a6767b366de4c1c855 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -8,7 +8,8 @@ global model = nothing global landcovermap = nothing -global runsimulation = nothing +global runsimulation = () -> nothing +#global newsimulation = () -> nothing global timer = nothing const configfile = Observable("guiparams.toml") @@ -47,7 +48,8 @@ const cropmodel = Observable("ALMaSS") #XXX alternatives not yet implemented ## the property list passed to QML global guiproperties = - ["running" => running, + ["launching" => launching, + "running" => running, "ticks" => ticks, "date" => date, "delay" => delay,