Intro
PaneSelector
looks like a pretty idiomatic way to toggle displayed content e.g.:
PaneSelector[
{True -> progressBar, False -> button}
, Dynamic @ processing
]
Analogous If
version:
Dynamic[ If[processing, progressBar, button] ]
The difference is that PaneSelector
content will be converted to boxes and each switch can be faster than Dynamic
which contents are sent for typesetting every time it is refreshed. Shortly, for PS
only the value of processing
does the round trip while for Dynamic[If[...]]
, full content.
Sounds good, does not work. I regret each time I use it.
Problem 1
DynamicModule[{processing = False, longProcedure},
longProcedure[] := Pause[2];
With[{
progressBar = ProgressIndicator[Appearance -> "Indeterminate"],
button = Button["Run", processing = True; longProcedure[]; processing = False, Method -> "Queued"],
buttonAsync = Button["Run async", processing = True; RunScheduledTask[longProcedure[], {.1}, "EpilogFunction" :> (processing = False)], Method -> "Queued"]
},
Grid[{
{"processing:", Style[Dynamic @ {processing}, Bold], SpanFromLeft},
{"PS:", PaneSelector[{True -> progressBar, False -> button}, Dynamic@processing, ImageSize -> All]},
{"If:", Dynamic[If[TrueQ@processing, progressBar, button]]},
{},
{"PS:", PaneSelector[{True -> progressBar, False -> buttonAsync}, Dynamic@processing, ImageSize -> All]},
{"If:", Dynamic[If[TrueQ@processing, progressBar, buttonAsync]]},
{},
{"Just toggle:", Button["toggle", processing = ! processing;, Method -> "Queued"]},
{"Toggle and pause:", Button["toggle2", processing = ! processing; Pause[2];, Method -> "Queued"]}
}, Alignment -> Left]
]
]
Pressing
Run
affects onlyIf
based solutions and notPS
.Pressing
Run async
shows both progress bars but when it is done only theIf
based solution shows the button back.Simple toggle
works as expectedToggle and pause
triggersPS
based solution only afterPause
is finished.
Using FinishDynamic
is an overkill here.
Problem 2
It does undocumented caching so you need to inject to your view stuff like random numbers:
Dynamic triggered but renders the same content
Why is PaneSelector caching nested Dynamics and how to switch it off?
Do you fancy debugging by inserting RandomReal[]
here and there? I do not.
Problem 3
Since it usually has PaneSelector[{__}, Dynamic[_Symbol]]
form, you don't know when this bug will hit you:
What is the difference between Dynamic[x] and Dynamic[ h[x] ] for DynamicModule variables?
Question
Did I miss the point of this function? What are the basic rules to follow to not face problems like this? Or is it better to just ignore this function which is what I would suggest to do.
PaneSelector[{True -> progressBar, False -> button}, Dynamic[processing+0], ImageSize -> All]
$\endgroup$Dynamic[ First @ {processing}]
but this does not help here while your+0
does. :D How ridiculous is this discussion now? XD $\endgroup$