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).