A problem with Deploy and Locator in a Manipulate

I recently asked a question about Locators not behaving properly (see Locators and Table within a Manipulate are not behaving) and thought I had figured out the answer. However, as I played around to figure out why the problem existed in the first place I discovered that using Deploy caused the problem to return. Here is as simple of an example as I can come up with that reproduces the problem and maintains some of the features that I need in the Manipulate. Particularly, I need to link the two sliders with the Locator. The following works fine:

Manipulate[
vector = Graphics[{Green, Arrow[{{0, 0}, p}],
Locator[Dynamic[p, (p = #; x = p[[1]]; y = p[[2]]) &]]}];
Show[{vector}, PlotRange -> {{-2.1, 2.1}, {-2.1, 2.1}},
ImageSize -> 500],
Row[{"Ax", Manipulator[Dynamic[x, (x = #; p[[1]] = x) &], {-2, 2}],
Spacer[4], Dynamic[x]}],
Row[{"Ay", Manipulator[Dynamic[y, (y = #; p[[2]] = y) &], {-2, 2}],
Spacer[4], Dynamic[y]}],
{{p, {1, 1}}, None},
{{x, 1}, None},
{{y, 1}, None},
TrackedSymbols -> {x, y, p}]


You get a green arrow that you can move with either the Locator or the Sliders (one component at a time).

However, if the user clicks slightly off of the Locator they highlight the whole graphics image and go into an editing mode. Users unfamiliar with this may not know what to do so I want to prevent this by using Deploy.

Adding Deployed->True as an option to the Manipulate doesn't work. The documentation for Manipulate says that it should, but for some reason it does nothing here.

So instead I wrapped Deploy around Show:

 Deploy@Show[{vector}, PlotRange -> {{-2.1, 2.1}, {-2.1, 2.1}},
ImageSize -> 500],


Now the user doesn't accidentally go into editing mode, but the Locator doesn't work. The Sliders do move the vector around and the Locator moves with them, but I can't move the locator with the mouse except for a VERY small distance at a time.

I'm wondering if this might have something to do with how I have linked the various control variables using the second argument of Dynamic. Perhaps the solution to this is also ultimately the solution to the question I referenced above. Thanks!

-

This seems to work:

Manipulate[
DynamicModule[{vector},
vector =
Graphics[{Green, Arrow[{{0, 0}, Dynamic[p]}],
Locator[Dynamic[p, (p = #; x = p[[1]]; y = p[[2]]) &]]}];
Deploy@Show[vector,
PlotRange -> {{-2.1, 2.1}, {-2.1, 2.1}}, ImageSize -> 500]],

Row[{"Ax", Manipulator[Dynamic[x, (x = #; p[[1]] = x) &], {-2, 2}],
Spacer[4], Dynamic[x]}],
Row[{"Ay", Manipulator[Dynamic[y, (y = #; p[[2]] = y) &], {-2, 2}],
Spacer[4], Dynamic[y]}],
{{p, {1, 1}}, None},
{{x, 1}, None},
{{y, 1}, None}, TrackedSymbols -> {x, y, p}]


The only difference with the original code is that I've wrapped p with Dynamic in Arrow.

By the way, since p == {x,y}, you can actually replace p with {x, y} making the code a bit more elegant in this case:

Manipulate[
DynamicModule[{vector},
vector =
Graphics[{Green, Arrow[{{0, 0}, Dynamic[{x, y}]}],
Locator[Dynamic[{x, y}]]}];
Deploy@Show[vector,
PlotRange -> {{-2.1, 2.1}, {-2.1, 2.1}}, ImageSize -> 500]],
{{x, 1, "Ax"}, -2, 2, Appearance -> "Labeled"},
{{y, 1, "Ay"}, -2, 2, Appearance -> "Labeled"}]

-
Heike's answer is correct, but I'd like to comment about why it's correct. Locators work very well, unless the expression that created the Locator gets re-generated as part of a Dynamic update. M-- makes some attempt to track re-generated locators, but it's a pathological problem which can't be solved in the most general case, and M-- is not as good as it could be in some specific cases. What Heike does here is to prevent the outer Dynamic implied by the Manipulate from firing by confining all references to p in more tightly scoped Dynamic constructs. – John Fultz Mar 1 '12 at 11:19
@Heike, This is great! Thanks Heike! And I know I tried linking the controllers by simply equating the variables in some way, but whatever way I tried it didn't work and I can't remember what I tried, but clearly not what you have shown me. I'm always learning! – John Carzoli Mar 1 '12 at 19:01
@JohnFultz, Thank you for the explanation! I was going to ask the why question so thank you for reading my mind. So that I am clear on this, with Heike's correction of Dynamic[p] in Arrow rather than just p, that Dynamic gets refreshed first before the implicit dynamic created by the Manipulate thereby allowing the Arrow to be recreated. Without the Dynamic within Arrow the Locator and Arrow do move a very tiny amount, but then stop. Is this due to how Manipulate sequences its evaluations, the first evaluation allowing the arrow to move, but then ... ok, I should just stop – John Carzoli Mar 1 '12 at 19:18
One more thing, the DynamicModule that Heike added to the code isn't necessary to make this work (as I verified), just the Dynamic[p] within Arrow. Is the DynamicModule recommended though to localize the variable vector and/or are there other deeper reasons? As a physicist I am cursed by needing to know deeper reasons for things, but sometimes I just need to move on. Thank you all for putting up with my questions! – John Carzoli Mar 1 '12 at 19:24
@JohnCarzoli I used the DynamicModule mainly to localize vector. It's usually a good idea to localize variables anyway but especially so in dynamic environments like Manipulate. If you don't, there is a big chance that different versions of the same Manipulate will interfere with each other. – Heike Mar 1 '12 at 23:48

The answer of Heike fixes your problem. I want to add, that your use of Manipulate is rather unusual, because like you did it, it would be more appropriate to use DynamicModule. This is because the documentation an all tutorials suggest, that Manipulate is for not too complex situations. It can be used there, but the main area of Manipulate are situations where you display something and control it with Sliders,... which are give as separate argument to Manipulate.

As Heike showed, there is often a way to make it work too, but the mixture of display and control in your code, was what led to the error in the first place. Let me explain this in more detail and start with a very simple example. This

Manipulate[Deploy[Graphics[{Arrow[{{0, 0}, p}],
Locator[Dynamic[p]]}, PlotRange -> 2]],
{{p, {1, 1}}, None}]


shows the same behavior you described and I believe it is, because Manipulate cannot handle the control inside the Graphics when it is combined with Deploy and the controlled variable appears in the graphics without Dynamic. Usually, no explicit Dynamic is needed inside Manipulate for such a simple situation. If you remove the Deploy it works. Try this the far more simpler version

Manipulate[Deploy[Graphics[{Arrow[{{0, 0}, p}]},
PlotRange -> 2]], {{p, {1, 1}}, Locator}]


and you'll see, that it works without complaint, although we used p without Dynamic. Let's see whether we can adapt this to your piece of code. You will instantly object, that you need the special set-function inside your Locator to ensure, the sliders are moved with the locator. But look, you did the similar thing with vector: you just used = and it got dynamically updated:

Manipulate[
vector = Graphics[{Green, Arrow[{{0, 0}, p}]}];
{x, y} = p;
Deploy[Show[{vector}, PlotRange -> {{-2.1, 2.1}, {-2.1, 2.1}},
ImageSize -> 500]],
Row[{"Ax", Manipulator[Dynamic[x, (x = #1; p[[1]] = x) & ], {-2, 2}],
Spacer[4], Dynamic[x]}],
Row[{"Ay", Manipulator[Dynamic[y, (y = #1; p[[2]] = y) & ], {-2, 2}],
Spacer[4], Dynamic[y]}],
{{p, {1, 1}}, Locator},
{{x, 1}, None},
{{y, 1}, None}
]


This works as you would have expected it in the first place. Since you need an explicit Manipulator to make the x and y sliders work and since the {x,y}=p is not really nice, you should write a DynamicModule which is in my opinion the simpler version and clearer solution here:

DynamicModule[{p = {1, 1}, x = 1, y = 1},
Panel[Column[{
Row[{"Ax", Spacer[4],
Manipulator[Dynamic[x, (x = #1; p[[1]] = x) & ], {-2, 2}],
Spacer[4], Dynamic[x]}],
Row[{"Ay", Spacer[4],
Manipulator[Dynamic[y, (y = #1; p[[2]] = y) & ], {-2, 2}],
Spacer[4], Dynamic[y]}],
LocatorPane[Dynamic[p, (p = #; x = p[[1]]; y = p[[2]]) &],
Graphics[{Green, Arrow[{{0, 0}, Dynamic[p]}]},
PlotRange -> {{-2.1, 2.1}, {-2.1, 2.1}},
ImageSize -> 500, Background -> White]
]
}]
]
]


Note, that in all above examples I used the pieces of your code to make it more clear what I changed and what I put where. It is not necessary to use p and x,y and therefore a shorter version is

DynamicModule[{x = 1, y = 1},
Panel[Column[{
Row[{"Ax", Spacer[4], Manipulator[Dynamic[x], {-2, 2}],
Spacer[4], Dynamic[x]}],
Row[{"Ay", Spacer[4], Manipulator[Dynamic[y], {-2, 2}],
Spacer[4], Dynamic[y]}],
LocatorPane[Dynamic[{x, y}],
Graphics[{Green, Arrow[{{0, 0}, Dynamic[{x,y}]}]},
PlotRange -> {{-2.1, 2.1},{-2.1, 2.1}},
ImageSize -> 500, Background -> White]
]}]
]
]

-
thank you for the additional information. I understand there are some limitations to Manipulate and I am always learning of new ones it seems. I'm trying to work within these limitations so as to create CDF files to include on my webpage for my students to interact with. Interactivity through a CDF file can only be done using Manipulate at least as far as I have read in the CDF documentation. However, your examples are great because I could also have versions of my demos in standard notebooks using the less restrictive DynamicModule and give these to students who have MMA. Thanks! – John Carzoli Mar 1 '12 at 19:34
@JohnCarzoli, I never realized, that the CDF tutorial suggests, that only Manipulates can be used. I think this is just not true. I used DynamicModule in several CDFs and it alsways worked. You have to pay attention, that your dynamic content is really self-contained. To test this, you can copy the displayed manipulate into a new cdf, quit kernel or restart Mathematica and then it must still be usable. And, as Heike suggested, try to localize all variables you use. It's just clearer and less error prone. – halirutan Mar 2 '12 at 1:18