MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

Interactive 2d zoom and some Dynamic questions

  • To: mathgroup at smc.vnet.net
  • Subject: [mg84524] Interactive 2d zoom and some Dynamic questions
  • From: Szabolcs Horvát <szhorvat at gmail.com>
  • Date: Wed, 2 Jan 2008 01:17:54 -0500 (EST)

Happy new year, MathGroup!

And now, the question:

First of all, those people who haven't seen it yet should definitely 
check out Daniel Huber's very nice Zoom2D palette:
http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/58c77e4614440e57/5876f0611112765e

But I would like to have something simpler, a "quick and dirty" zoom 
that has the simplest possible UI, and keeps the graphic in the 
notebook.  So I came up with this:

zoomGraphics[graph_Graphics] :=
     With[
        {gr = First[graph],
         opt = DeleteCases[Options[graph], PlotRange -> _],
         plr = PlotRange /. Options[graph, PlotRange],
         rectangle = {Dashing[Small],
           Line[{#1, {First[#2], Last[#1]}, #2,
                 {First[#1], Last[#2]}, #1}]} & },
         DynamicModule[{dragging = False, first, second, range = plr},
             Panel@EventHandler[
                 Dynamic@Graphics[
                     If[dragging, {gr, rectangle[first, second]}, gr],
                     PlotRange -> range, Sequence @@ opt
                 ],
                {{"MouseDown", 1} :> (first = MousePosition["Graphics"]),
                 {"MouseDragged", 1} :>
                    (dragging = True;
                     second = MousePosition["Graphics"]),
                 {"MouseUp", 1} :>
                     If[dragging,
                        dragging = False;
                        range = Transpose@{first, second}, range = plr] }
                 ]
         ]]

Usage example:

Plot[1/x, {x, 0, 1}] // zoomGraphics

Drag to zoom, click to reset.  Remove Panel if you don't like it (or 
replace it with Framed).  It's there to show the active ("draggable") area.

I do not understand Dynamic things well, so comments, suggestions (e.g. 
for improving performance), problem cases where zoomGraphics fails are 
most welcome.

One of the biggest problems with this is that EvantHandler prevents 
resizing the graphic from working.  This is unacceptable because if we 
want to zoom, most likely we also want to keep the resize functionality.

It also prevents dynamic things, like Locators from working properly.  I 
could set PassEventsDown -> True in EventHandler, but zooming would 
still interfere with resizing or moving a Locator (and other strange 
behaviour appears too.)  One solution that I can imagine is to zoom only 
while CTRL (or some other modifier key) is pressed.  But I do not know 
how to implement this properly.  This is what I have so far:

zoomGraphics[graph_Graphics] :=
  With[
   {gr = First[graph],
    opt = DeleteCases[Options[graph], PlotRange -> _],
    plr = PlotRange /. Options[graph, PlotRange],
    rectangle = {Dashing[Small],
       Line[{#1, {First[#2], Last[#1]}, #2, {First[#1],
          Last[#2]}, #1}]} &,
    keyCheck =
     Function[{arg}, If[CurrentValue["ControlKey"], arg], HoldAll]},
   DynamicModule[{dragging = False, first, second, range = plr},
    Panel@EventHandler[
      Dynamic[
       Graphics[
        If[dragging, {gr, rectangle[first, second]}, gr],
        PlotRange -> range, Sequence @@ opt
        ]],
      {{"MouseDown", 1} :>
        keyCheck[first = MousePosition["Graphics"]],
       {"MouseDragged", 1} :>
        keyCheck[dragging = True; second = MousePosition["Graphics"]],
       {"MouseUp", 1} :>
        keyCheck@
         If[dragging, dragging = False;
          range = Transpose@{first, second}, range = plr]}]
    ]]

OK, now zooming only works while CTRL is pressed.  Now it is somewhat 
safer to set PassEventsDown -> True, and resizing works when CTRL is not 
pressed.  But resizing and selecting graphics interferes with zooming 
when CTRL is pressed.  The zoom level is also often reset unexpectedly 
if CTRL is not released (and pressed again), and the graphics are not 
deselected, between consecutive zoom attempts.  I don't completely 
understand what is happening here.  Is it possible to somehow set 
PassEventsDown -> True only when CTRL is not pressed?  As a desperate 
attempt, I tried PassEventsDown -> 
Dynamic@Not@CurrentValue["ControlKey"], but, unsurprisingly, it does not 
work.

As an alternative solution, I also tried using 
GraphicsGrid[{{zoomGraphics[someGraphic]}}] with the original version of 
zoomGraphics to enable resizing (not moving Locators), but now the 
events don't seem to reach the EventHandler.

Another question:  Could someone please explain, preferably with a 
working example, what PassEventsUp is for?

Szabolcs


  • Prev by Date: Re: A limit bug
  • Next by Date: Re: A limit bug
  • Previous by thread: Re: Re: Timing and Pi
  • Next by thread: Re: Interactive 2d zoom and some Dynamic questions