Consider the following example:
DynamicModule[{foo = {Red, Green}, switchColor},
Attributes[switchColor] = {HoldAll};
switchColor[c_] := If[c === Red, c = Green, c = Red];
{
Dynamic[Print["redrawing first"]; foo[[1]]],
Dynamic[Print["redrawing Second"]; foo[[2]]],
Button["Switch first", switchColor[foo[[1]]]],
Button["Switch second", switchColor[foo[[2]]]]
}
]
(in the gif for some reason it appears that the first color is updated incorrectly, while this is not the case)
This works totally fine, but a quick look to the messages reveals that even when changing only a single element of the list, both of the Dynamic
are updated.
Now, this is not really surprising: there is just one variable to be tracked. However, I was wondering if there was a way to go around this, as it can be handy to be able to track independently single elements of a list.
One way around it is to fine foo
as a list of held variables, and wire Dynamic
to those variables directly. This works, as can be seen in the following:
DynamicModule[{
foo = Table[Hold@Evaluate@Unique["color$"], {2}],
switchColor
},
Scan[# /. Hold[s_] :> Set[s, Red] &, foo];
switchColor[c_Hold] := If[
ReleaseHold@c === Red,
c /. Hold[s_] :> Set[s, Green],
c /. Hold[s_] :> Set[s, Red]
];
{
Dynamic[Print["redrawing first"];
ReleaseHold@foo[[1]]
],
Dynamic[Print["redrawing second"];
ReleaseHold@foo[[2]]
],
Button["Switch first", switchColor[foo[[1]]]],
Button["Switch second", switchColor[foo[[2]]]]
}
]
My problem with this approach is that I suspect that this makes the variables that are actually being used, that is, color$xxxx
, not being defined in front end, as would be the case for variables localised inside a DynamicModule
.
Is there a way around this? Or can I somehow force the variables to be defined in the front end like they would be in a DynamicModule
?
Bonus question:
Why does the above code work? Having Dynamic
the HoldFirst
attribute I would have expected it not to be able to understand that the variable to be tracked is the one inside the hold in the first element of foo
. How does it do that?
Answer
I think I got it. Again using bump
from Elegant manipulation of the variables list
func_[a___, bump[lst_, idx___], b___] ^:=
func[a, #, b] & @ Part[List @@@ Unevaluated @@ {lst}, {1}, idx]
Unique @ Table["color$", {2}] /. _[x__] :>
DynamicModule[{foo, switchColor, x},
foo = Hold[x];
switchColor[c_] := c = If[c === Red, Green, Red];
switchColor /@ bump[foo];
{
Dynamic[ Context @ bump[foo, 1] ],
Dynamic[ Print["redrawing first"]; foo[[1]] ],
Dynamic[ Print["redrawing second"]; foo[[2]] ],
Button["Switch first", switchColor @ bump[foo, 1]],
Button["Switch second", switchColor @ bump[foo, 2]]
}
]
Comments
Post a Comment