I am looking for a solution to selectively update a dynamic expression expr which is dependent on multiple control variables {x, y, ...}. I need to update expr differently (using xUpdate and yUpdate) according to which controller is manipulated, i.e. which control variable triggers an update, but without including update code in any of the controllers! That is, Dynamic[expr] itself has to include the different update modes.
Question: Is there a method to update a dynamic expression differently depending on which parent-variable triggers an update?
1. Include update in controller
The easy way would be to simply include the different update codes in the controllers, but as I said, this is not the desired way. The code is included here only for reference:
xUpdate[xin_, yin_] := {"x-trigger", yin + xin, yin};
yUpdate[xin_, yin_] := {"y-trigger", yin*10, yin};
x = y = 0; expr = yUpdate[x, y];
{Row@{"update x: ",
Slider[Dynamic[x, (x = #; expr = xUpdate[x, y]) &]]},
Button["Update y", y = RandomReal[]; expr = yUpdate[x, y]]}
Dynamic[expr]
This works as expected, but in my use case I cannot update expr directly from the controllers. I have to do it in a way that is restricted to the last line, i.e. the expr itself has to do the updating according to which controller was manipulated.
2. Using $ControlActiveSetting
An alternative method is to rely on the global value of $ControlActiveSetting:
xUpdate[xin_, yin_] := {"x-trigger", yin + xin, yin};
yUpdate[xin_, yin_] := {"y-trigger", yin*10, yin};
x = y = 0;
{Button["Update y", y = RandomReal[]],
Row@{"update x: ", Slider[Dynamic@x]}}
Dynamic[expr = If[$ControlActiveSetting, xUpdate[x, y], yUpdate[x, y]]; expr,
TrackedSymbols :> {x, y}]
This correctly differentiates between the two update modes, but it incorrectly reverts to y-trigger whenever the x-slider is released. This is unwanted behaviour. A second problem with this is that $ControlActiveSetting cannot differentiate between multiple sliders (i.e. imagine a third z controller).
3. Intermediate solution a'la $ControlActiveSetting
A global flag (trigger, substituting $ControlActiveSetting) is set to either "x", "y" or "z", depending on which controller is being manipulated. This works as expected and can be extended to any number of controllers, but has the problem that I still have to set trigger in each controller, which I want to avoid.
xUpdate[xin_, yin_, zin_] := {"x-trigger", yin + xin, yin, zin};
yUpdate[xin_, yin_, zin_] := {"y-trigger", yin*10, yin, zin};
zUpdate[xin_, yin_, zin_] := {"z-trigger", zin*20, yin - 1, zin};
x = y = z = 0;
trigger = "x";
{Button["Update y", trigger = "y"; y = RandomReal[]],
Row@{"update x: ", Slider[Dynamic[x, (trigger = "x"; x = #) &]]},
Row@{"update z: ", Slider[Dynamic[z, (trigger = "z"; z = #) &]]}}
Dynamic[Switch[trigger, "x", xUpdate[x, y, z], "y", yUpdate[x, y, z],
"z", zUpdate[x, y, z]], TrackedSymbols :> {x, y, z}]
But it brings me closer to my real question:
Question:
Is there a way to check globally which control variable is being actively manipulated/changed in the front-end? Surely Dynamic[expr] knows about it as it has the TrackedSymbols option, but I cannot access this information from inside the Dynamic. I think of something like CurrentValue["ManipulatedVariable"] or CurrentValue["ActualDynamicUpdatingTrigger"] (which are nonexistent).
/;checking for all three triggers at every update? – István Zachar Mar 18 '13 at 16:36