# Activity indicators for slow Dynamic expressions?

With Dynamic and gui-constructs like Popup I always have a problem: when an expression takes a while to evaluate the Dynamic parts look bad and usually breaks. For example, imagine a PopupMenu showing choices whose data has yet to be downloaded. I tried using things like PrintTemporary but they didn't achieve the in-place effect I'm looking for.

So, for an arbitrarily long running dynamic, inserting Activity Indicators (looped animations) seamlessly is what I'm after.

Here's my first attempt:

and the code:

assnMenu[f_,a_Association, title_:"Choose"] := Module[
{am,b,r,g},
blup=Style[Pane[Magnify[ProgressIndicator[Appearance->"Percolate"],2]
,Alignment->Center],Background->Transparent];
r=blup;
g:=(r=blup;r=f[#])&;
onValueChange[b, g];
am = Table[With[{i=i}, a[i]:>(b=i)], {i, Keys@a}];
b = First @ Keys[a];
Panel @ Grid[
Dynamic[Style[a[b],FontFamily->"Arial Black",FontSize->14],UpdateInterval->1]},
{Dynamic[r, TrackedSymbols:>{r}],SpanFromLeft}},
Alignment->{Center,Center}
]
]

onValueChange[a_,f_] := Module[{},
a/:Set[a,x_]:=((OwnValues[a]={HoldPattern[a]:>x}; f[x]);a)
]


This almost achieves what I want, but has a few glitches:

• This seems too complicated to be the right way to do this.
• In the current form assnMenu[slowFunc, <|10 -> "A", 5 -> "B"|>] takes 10 seconds to evaluate, so there is leakage.
• I couldn't get it to work with a DynamicModule, (which has the nice option DynamicEvaluationTimeouts), which would help a lot.
• I probably overlooked some part of the docs, I feel like there should already be high level functionalities handling this sort of stuff.

An adaption of this answer for an ActionMenu and to your styling:

assnMenuK[slowF_, a_Association, title_: "Choose"] :=
DynamicModule[{done = False, lastSelection = ""},
Grid[{{
KeyValueMap[#2 :> (lastSelection = #2; done = "working";
slowF[#1]; done = True) &, a], Method -> "Queued"],
Dynamic@Style[lastSelection, FontFamily -> "Arial Black", FontSize -> 14]},
{Dynamic@Switch[done, False, "",
True, "done",
"working", ProgressIndicator[Appearance -> "Percolate"]],
SpanFromLeft}}]]


Example:

assnMenuK[Pause, <|1 -> "A", 2 -> "B"|>]


The "in-place effect" can be improved even further, e.g., by using Invisible["A"] instead of "" and PaneSelector instead of Switch.

assnMenuK2[slowF_, a_Association, title_: "Choose"] := DynamicModule[
{done = False, lastSelection = Invisible["A"]},
Panel@Grid[{
KeyValueMap[#2 :> (lastSelection = #2; done = "working";
slowF[#1]; done = True) &, a]
, Method -> "Queued"],
Dynamic@Style[lastSelection, FontFamily -> "Arial Black", FontSize -> 14]},
{PaneSelector[
{False -> "",
True -> "done",
"working" -> ProgressIndicator[Appearance -> "Percolate"]},
Dynamic@Setting@done
, Alignment -> Center],
SpanFromLeft}}]]

assnMenuK2[Pause, <|1 -> "A", 2 -> "B"|>]


• The Dynamic in Dynamic[ProgressIndicator[...]] is not needed. – Ariel Sepulveda Sep 30 '15 at 9:55
• @ArielSepulveda Thanks for pointing that out. – Karsten 7. Oct 5 '15 at 11:30
• Interesting use of "Setting" in Dynamic@Setting@done . Any comments on why it is needed? I tried replacing it with a FinishDynamic[] after done = "working" and didn't work. – Gustavo Delfino Mar 1 '17 at 20:29
• @GustavoDelfino Dynamic@Setting@done is just a workaround for a bug. I simply prefer it over using Dynamic@First@{done}. – Karsten 7. Mar 2 '17 at 0:23
• @GustavoDelfino the second argument for Setting is undocumented and is even highlighted as a syntax error in the notebook, but it is a level specification. – Karsten 7. Mar 2 '17 at 0:30