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.

Consider the following piece of code from Heike as an ( accepted ) answer on LocatorPane, selecting multiple Locators - Basically the code implements dragging polygons on a LocatorPane.

 DynamicModule[{pts, range, gr, drag, pts0},
  pts = RandomReal[1, {7, 2}];
  range = {1 ;; 4, 5 ;; 7};
  gr = {{Red,  Polygon @ Dynamic @ pts[[ range[[1]] ]]},
        {Blue, Polygon @ Dynamic @ pts[[ range[[2]] ]]}};
  drag = 0;

  Panel[LocatorPane[Dynamic[pts],
    EventHandler[
     Graphics[
      EventHandler[gr[[#1]],
         {"MouseDown" :>
           (drag = #; pts0 = # - MousePosition["Graphics"] & /@ pts[[ range[[#]] ]])}
      ] & /@ {1, 2}, 
      PlotRange -> {{0, 2}, {0, 2}}],
     {"MouseDragged" :> 
       If[drag > 0, pts[[range[[drag]]]] = # + MousePosition["Graphics"] & /@ pts0],
      "MouseUp" :> (drag = 0)},
     PassEventsDown -> True
    ]
  ]]
 ]

If you run this code you'll notice that when a locator's position is on another polygon the locator does not work anymore.

Question: How can the code above be changed so that a click on a locator always works? Why was it necessary to use two two EventHandlers, and what is a good rule to decide on wether to use the PassEventsDown option?

share|improve this question
add comment

1 Answer 1

up vote 6 down vote accepted

The following code does what you want. It requires that you press shift to move a locator that is being overlapped by a polygon, instead of moving that polygon.

DynamicModule[{pts, range, gr, drag, pts0}, 
 pts = RandomReal[1, {7, 2}];
 range = {Span[1, 4], Span[5, 7]};
 gr = {{Red, Polygon[Dynamic[pts[[range[[1]]]]]]}, {Blue, 
    Polygon[Dynamic[pts[[range[[2]]]]]]}};
 drag = 0;
 Panel[
  LocatorPane[
   Dynamic[pts],
   EventHandler[
    Graphics[
     EventHandler[
        gr[[#]],
        {
         "MouseDown" :> (drag = # Boole[\[Not]CurrentValue["ShiftKey"]];
           pts0 = # - MousePosition["Graphics"] & /@ pts[[range[[#]]]])
         },
        PassEventsDown -> True
        ] & /@ {1, 2},
     PlotRange -> {{0, 2}, {0, 2}}
     ],
    {
     "MouseDragged" :> 
      If[drag > 0, 
       pts[[range[[drag]]]] = # + MousePosition["Graphics"] & /@ pts0],
     "MouseUp" :> (drag = 0)
     },
    PassEventsDown -> True
    ], Enabled -> Dynamic[drag == 0]
   ]
  ]
 ]

Mathematica graphics

I'll first explain the causes of the unwanted behavior and then explain my solution.

At the base of the problem lies the fact that LocatorPane needs to get its own events, the clicks on the pane that (re)set the position of the locators. The 3 (not 2, if you look closely) EventHandlers get priority above the LocatorPane when you click in their elements. If you don't do a PassEventsDown->True LocatorPane won't see the event at all. It'll be eaten up by the handler. However, if you would pass down the event to the LocatorPane it would set a new position for the locator while at the same time the polygon is being dragged. You get a very erratic result.

My solution consists of the following:

  1. Pass the events to LocatorPane by setting PassEventsDown->True in the deepest event handlers
  2. If we have a dragging event, disable the LocaterPane using the option setting Enabled -> Dynamic[drag == 0]
  3. Enable locator actions on overlapped locators by multiplying the drag variable with Boole[\[Not]CurrentValue["ShiftKey"]], which then disables the polygon dragging behavior if the shift key is pressed. Locator dragging can then proceed as normal.
share|improve this answer
    
Disabling, of course! - Thank you very much, Sjoerd for the excellent explanation. –  ndroock1 May 27 '12 at 17:44
    
What do I have to press to drag the polygon? –  Mr.Wizard May 27 '12 at 19:42
    
@Mr.Wizard Nothing. Just click-and-drag inside the polygon. –  Sjoerd C. de Vries May 27 '12 at 19:51
    
In that case this fails on v7, unlike Heike's answer referenced in the question. –  Mr.Wizard May 27 '12 at 19:53
    
Actually, for me the polygons move when using right-click-and-drag. Is this expected? –  Mr.Wizard May 27 '12 at 20:01
show 2 more comments

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.