7
$\begingroup$

This follows up on another question about the sensitivity of Locators in a a LocatorPane.

I would like to be able to enable/disable individual locators in a LocatorPane. In the simplified version of the applet, pictured below, I would like to be able to disable the locators that set the slope of the red line, while allowing the locators that set the slope of the blue line to remain enabled.

locators

Using individual Locators, rather than a LocatorPane, is not an option. (There are some subtle issues that arise with individual locators. Essentially, multiple Locators can behave in a "flaky" fashion in complex applets, in ways that LocatorPane does not.)

Code below:

Manipulate[m = 15;
 LocatorPane[Dynamic[pts],
  Dynamic[ Module[{x = pts[[1, 1]], y = pts[[2, 2]], x2 = pts[[3, 1]], y2 = pts[[4, 2]]},
  Graphics[{
  {Blue, Line[{-m*{x2, y2}, m*{x2, y2}}]},
  Line[{{x2, 0}, {x2, y2}}], Line[{{x2, y2}, {0, y2}}],
  {Red, Line[{-m*{x, y}, m*{x, y}}]},
  Line[{{x, 0}, {x, y}}], Line[{{x, y}, {0, y}}]},
  PlotRange -> m, Axes -> True, ImageSize -> {300, 300}]]],
  {{{-m, 0}, {m, 0}, {1, 0}}, 
   {{0, -m}, {0, m}, {0, 1}}, 
   {{-m, 0}, {m, 0}, {1, 0}}, 
   {{0, -m}, {0, m}, {0, 1}}},
 Appearance -> {Automatic, Automatic, Automatic, Automatic}], 
 {{pts, {{6, 0}, {0, 9}, {3, 0}, {0, 7}}}, ControlType -> None}]

The visibility of the locators can be individually controlled by toggling the respective locator's Appearance between None and Automatic. But even when the locator is invisible (i.e. Appearance -> None) it continues enabled. For example, the red sliders will continue to set the slope of the red line.

A possible solution would be to obtain the Appearance setting of the red sliders and make the assignment of x and y contingent on the Appearance setting.

$\endgroup$
5
  • 2
    $\begingroup$ Could you describe briefly or link to a description of this unwanted "flaky" behavior of individual locators? $\endgroup$
    – jVincent
    Commented Aug 6, 2012 at 9:36
  • $\begingroup$ Ever time I tried to use individual locators (with out a LocatorPane I would run into a situation in which they would cease to be responsive after moving once. I take this to mean that some routines needed to be wrapped in Dynamic, but I could never figure out a solution, no matter how much I tried. So the flakiness may have been inherent to the Locators or a reflection of my inability to fully understand the use of Dynamic wrappers. $\endgroup$
    – DavidC
    Commented Aug 6, 2012 at 13:12
  • 1
    $\begingroup$ Sounds like an interesting problem, if you have code that exhibits this problem I think you should add it to your question or add a new question for it. $\endgroup$
    – jVincent
    Commented Aug 6, 2012 at 13:22
  • $\begingroup$ The problem rears its head in the context of a couple pages of code. Generally I avoid inflicting large amounts of code on others. $\endgroup$
    – DavidC
    Commented Aug 6, 2012 at 14:36
  • $\begingroup$ "Generally I avoid inflicting large amounts of code on others." -- Something I think we all appreciate. Nevertheless it might make in interesting question, and you certainly haven't made a pest of yourself with wall-of-code questions. $\endgroup$
    – Mr.Wizard
    Commented Aug 6, 2012 at 19:50

2 Answers 2

7
$\begingroup$

A simple way to do this is to change the Dynamic so that it updates only the points you want to be editable. Here is a very simple demonstration:

 pts = {{6, 0}, {0, 9}, {3, 0}, {0, 7}};
 updatable = Range@Length@pts;
 Button["Fixate point 3", (updatable = {1, 2, 4})]
 LocatorPane[Dynamic[pts, (pts[[updatable]] = #[[updatable]]) &], 
 Dynamic@Graphics[Point /@ pts, PlotRange -> {{-10, 10}, {-10, 10}}]]
$\endgroup$
2
  • $\begingroup$ Interesting. I'll need some time before I can fully examine it, but it looks promising. $\endgroup$
    – DavidC
    Commented Aug 6, 2012 at 13:14
  • 1
    $\begingroup$ +1 It works like a charm. Very clever suggestion. $\endgroup$
    – DavidC
    Commented Aug 6, 2012 at 14:51
4
$\begingroup$

I like @jVincent's approach.

Here is a different approach Overlaying LocatorPanes inside Manipulate :

locPane[Dynamic[pts_], shape_, color_] := 
 LocatorPane[Dynamic[pts], 
 Dynamic@Module[{x = pts[[1, 1]], y = pts[[2, 2]]}, 
 Graphics[{{color, Line[{-m*{x, y}, m*{x, y}}]}, 
  Line[{{x, 0}, {x, y}}], Line[{{x, y}, {0, y}}]}, PlotRange -> m,
  Axes -> True, ImageSize -> {300, 300}]],
 {{{-m, 0}, {m, 0}, {1, 0}}, {{0, -m}, {0, m}, {0, 1}}},
 Appearance -> {shape, shape}];
(* locator apperance graphics *)
redCircle = Graphics[{Red, Table[Circle[{0, 0}, i], {i, 2}]}, ImageSize -> 10];
blueCircle = Graphics[{Blue, Table[Circle[{0, 0}, i], {i, 2}]}, ImageSize -> 10];
grayDisk =  Graphics[{Lighter@Lighter@Gray, Disk[{0, 0}, 2], 
 Gray, Circle[{0, 0}, 3]},  ImageSize -> 10];

Method 1: Overlay two instances of locPane inside a Manipulate

Manipulate[m = 15; 
 Overlay[{
  locPane[Dynamic[pts], Dynamic@If[layer == 1, redCircle, grayDisk], Red], 
  locPane[Dynamic[pts2], Dynamic@If[layer == 2, blueCircle, grayDisk], Blue]},
  All, Dynamic[layer]], 
{{pts, {{6, 0}, {0, 9}}}, ControlType -> None}, 
{{pts2, {{7, 0}, {0, 7}}}, ControlType -> None}, 
{{layer, 1, "layer"}, {1, 2}}]

to get

enter image description here

Method 2: Overlay two instances of locPane inside an EventHandler and Manipulate:

Right-mouse-click toggles between two locator panes:

DynamicModule[{layer = 1}, EventHandler[Manipulate[m = 15;
 Overlay[
{locPane[Dynamic[pts], Dynamic@If[layer == 1, redCircle, grayDisk], Red], 
 locPane[Dynamic[pts2], Dynamic@If[layer == 2, blueCircle, grayDisk], Blue]},
 All, Dynamic[layer]],
{{pts, {{6, 0}, {0, 9}}}, ControlType -> None},
{{pts2, {{7, 0}, {0, 7}}}, ControlType -> None}],
{{"MouseClicked", 2} :> ((layer = layer /. {1 -> 2, 2 -> 1}))}, 
PassEventsDown -> True]]

enter image description here

$\endgroup$
2
  • $\begingroup$ When I run your solution after EDIT, each locator stops and freezes after moving one unit. (This is precisely the sort of trouble I run into when I attempt to use Locator instead of LocatorPane.) I suspect that some variable needs to be wrapped in Dynamic. $\endgroup$
    – DavidC
    Commented Aug 6, 2012 at 15:40
  • $\begingroup$ @DavidCarraher, I think the version you are using is not the last one - I added Dynamic before Module in both versions to fix that same issue. $\endgroup$
    – kglr
    Commented Aug 6, 2012 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.