Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am wondering why the Enabled setting for the first locator (point1) overrides the Enabled setting for the second locator (point2). Any ideas?

Manipulate[
 Graphics[{ {{Arrow[{{0, 0}, point1}]}}, {{Arrow[{{0, 0}, 
   point2}]}}},
  Axes -> True, PlotRange -> {{-4, 8}, {-4, 8}}],
{{point1, {-1, 3}}, {-4, -4}, {8, 8}, {.1, .1}, Locator, Enabled -> False},
{{point2, {5, -2}}, {-3, -3}, {6, 6}, {.1, .1}, Locator, Enabled -> True}]

One of the locators should be enabled; the other should be disabled. However, as the picture shows, they are both disabled.

I realize I could work around this by using LocatorPane, but I'm curious why this doesn't work for individual locators. Am I overlooking something or is this a bug?

locators

share|improve this question
4  
I assume all locators are swept together internally and the first Enabled encountered determines the state of all. There is some hint (it's not precisely your situation) about the internal difficulties involved in combining multiple locators in the documentation: "Due to internal limitations, it is not possible to combine individual Locator variables with a variable that is a list of multiple Locator variables: you can have only one multipoint Locator variable in a Manipulate." –  Sjoerd C. de Vries Nov 4 '12 at 18:43
    
@SjoerdC.deVries Can you include a link? My last question would also benefit from it –  belisarius Nov 4 '12 at 18:47
    
@belisarius It's slightly below wolfram.com/xid/0fz3xp8d3e93ro (the Locator section, between In[36] and In[37]). –  Sjoerd C. de Vries Nov 4 '12 at 18:50
    
@SjoerdC.deVries Thanks, going to update my question –  belisarius Nov 4 '12 at 18:52
    
@Sjoerd: I see. But neither of the locators I'm using is multipoint. –  David Carraher Nov 4 '12 at 19:25
show 1 more comment

2 Answers

up vote 6 down vote accepted

As surmised by @Sjoerd in the question's comments, Manipulate combines all locators into a single LocatorPaneBox. We can see this if we inspect the boxes generated by the Manipulate expression:

PaneBox[PanelBox[DynamicWrapperBox[PaneSelectorBox[{True->GridBox[{{
...
LocatorPaneBox[
  Dynamic[{$CellContext`point1$$,$CellContext`point2$$}],
  ...
  Enabled->False,Enabled->True]
...
FrameMargins->{{5,5},{5,5}}],ImageMargins->0,BaselinePosition->Automatic]

This excerpted snippet shows us two things. First, we can see the single LocatorPaneBox that references both points. Second, we can see that the Enabled option is specified twice. As usual, the first instance takes precedence over the second with the result that both locators are disabled. This second point feels like a bug.

To work around this problem is tricky. We could try to use an explicit LocatorPane, but that does not allow us to specify independent regions or enablement states for each locator. If we try to use two LocatorPane expressions, we run into problems when the outer pane is disabled -- events do not get sent down to the inner pane. It is possible to work around this using elaborate EventHandler interactions, but it is not pretty. I suspect that these problems are what led to the present restrictions in the Manipulate implementation.

In this particular case, a simpler solution is to abandon LocatorPane altogether and to include explicit Locator directives instead:

clip[pt:{x_, y_}, {xMin_, yMin_}, {xMax_, yMax_}, {xStep_, yStep_}] :=
  {Round[Clip[x, {xMin, xMax}], xStep], Round[Clip[y, {yMin, yMax}], yStep]}

Manipulate[
  Graphics[
    { Arrow[{{0, 0}, point1}]
    , Arrow[{{0, 0}, point2}]
    , Locator[Dynamic[point1,(point1=clip[#, {-4, -4}, {8, 8}, {.1, .1}])&], Enabled->False]
    , Locator[Dynamic[point2,(point2=clip[#, {-3, -3}, {6, 6}, {.1, .1}])&], Enabled->True]
    }
  , Axes -> True, PlotRange -> {{-4, 8}, {-4, 8}}
  ]
, {{point1, {-1, 3}}, None}
, {{point2, {5, -2}}, None}
]

Unfortunately, this means that we must implement the locator region constraints ourselves since Locator does not offer that service (LocatorRegion only provides crude clipping). However, this is easier than the event-handling gymnastics that would otherwise be required for LocatorPane.

share|improve this answer
    
Very nice! Using this method, and checkboxes, it is also possible to control both the Enabled state and visibility (i.e Appearance) of each locator independently. –  David Carraher Nov 5 '12 at 17:17
add comment

This is just a possible workaround to overcome the issue (WReach has nicely debunked it) by simulating a Manipulate interface. As always, start by writing a DynamicModule object that is then wrapped in a dummy Manipulate wrapper:

Manipulate@DynamicModule[{point1 = {-1, 3}, point2 = {5, -2}},
  Graphics[{
    Dynamic@Arrow[{{0, 0}, point1}],
    Dynamic@Arrow[{{0, 0}, point2}],
    Locator[Dynamic[point1, (point1 = Clip[#, {-4, 8}]) &], Enabled -> False],
    Locator[Dynamic[point2, (point2 = Clip[#, {-3, 6}]) &], Enabled -> True]
    }, Axes -> True, PlotRange -> {{-4, 8}, {-4, 8}}]
  ]

Mathematica graphics

share|improve this answer
    
What advantages are gained by using Dynamic Module? Also, in what sense is Manipulate being used as a dummy wrapper. Do you mean that no interactive functionality is actually required? (Actually, in the full implementation, there are 8 or so controls that are needed. Most are checkboxes, including those to Enable/Disable the locators individually.) –  David Carraher Nov 5 '12 at 17:23
    
@David The DynamicModule works perfectly without the Manipulate. It is dynamic in itself and can hold any number of Locators or LocatorPanes, so the Manipulate is only there to provide 1) the familiar paneled look-and-feel (e.g. the + button in the top right), and 2) the somewhat necessary wrapper for deploying to CDF. –  István Zachar Nov 5 '12 at 17:59
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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