Re: Interactive 2d zoom and some Dynamic questions
- To: mathgroup at smc.vnet.net
- Subject: [mg84588] Re: Interactive 2d zoom and some Dynamic questions
- From: m.r at inbox.ru
- Date: Sun, 6 Jan 2008 05:51:20 -0500 (EST)
- References: <flfaf0$a9e$1@smc.vnet.net>
On Jan 2, 12:20 am, Szabolcs Horv=E1t <szhor... at gmail.com> wrote: > 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_... > > 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 You can dynamically change Deployed: DynamicModule[{mp, pos = {.5, .5}, sz = {1, 1}, mpos, f = True}, mp[] := MousePosition["GraphicsScaled"]; EventHandler[ Style[Graphics[ Inset[GraphData["HundredTwentyCellGraph"], Center, Dynamic@Scaled@pos, Dynamic@Scaled@sz], ImageSize -> 500], Deployed -> Dynamic[f]], {"MouseDown" :> (If[f && CurrentValue["MouseButtonTest"] && CurrentValue["MouseClickCount"] == 2, pos = {.5, .5}; sz = {1, 1}, If[f && CurrentValue["ControlKey"], f = False, If[! f && CurrentValue["AltKey"], f = True]]]; mpos = mp[]), "MouseDragged" :> (If[f, If[CurrentValue["MouseButtonTest"], pos -= 2/sz[[1]] (mp[] - mpos), sz += 4 sz[[1]] (mp[][[2]] - mpos[[2]])]; mpos = mp[]])}, PassEventsDown -> True]] Here dragging the mouse with the left button pressed pans the graphic, dragging the mouse up/down with the right button pressed zooms in/out, left double click resets to defaults, but if you do Control-click, you switch to the standard interactive editing mode. Alt-click switches back to zoom mode. Maxim Rytin m.r at inbox.ru