Repository: bokeh/bokeh

Issue:
Add box zoom out tool
It is a common practice to have both zoom in and zoom out tools in various visualization applications, such as image preview, map, and PDF readers. However, current Bokeh (0.10.0) does not provide a box zoom out tool, which is sometimes inconvenient to users. It would be better to have this tool available.



Discussion:
Hi @liuyxpp, I don't think I've ever seen a **box** zoom out tool. What would you select (with the box) to zoom out?

Do you actually just mean zoom in and out buttons? e.g. http://leafletjs.com/examples/quick-start.html

I've just seen @bryevdv's comment on the mailing list 

> It's also possible to have "centered" box zoom tools that permit zooming out (the drag action defines a half diagonal instead of a full diagonal, so the first mouse point is where the zoom is centered), but Bokeh does not have this at the moment.

I actually don't get this - can someone point me to an example?

@birdsarah You can think of the box zoom in & out tool as a generalization of the zoom in & out button in the example you given. That is, the box zoom in & out tool allows user to select the zooming center while the zoom in & out button uses the view center as the default zooming center. 

For box zoom in tool, it is natural to have a zooming range (which is the box) as Bokeh currently provides. For box zoom out tool, there mainly have two choices. We can fix the zoom out ratio to some certain comfortable value (maybe 5/4?). In this way, the box zoom out tool will mimic the behavior of the zoom out button but with a user designated zooming center. Therefore, we can differentiate the zoom out tool from the zoom in tool by not drawing the dash line box. The user will select the zoom out tool and click one point in the plot and the plot will zoom out with a new view center which is the user clicked point.

Or we can further utilize the box range and set the zooming ratio to be the current view range over the user selected range. But I don't think this way is natural for everyone.

I think implementation of the first choice should be good enough. 

Can you point me to an example?

@birdsarah it was used extensively in a place I used to work but there is nothing public I can point to. It's actually eminently reasonable, though. It lets you use a box in a way that permits both zoom out, and also lets you specify the center (which is probably what you care about anyway).

I still don't understand exactly the mechanics. And I can't be against something that I can't imagine. 

I would like to argue that +/- buttons would be a superb feature addition that, to my understanding, achieves the same result (the center of your zoom out is the center of your plot)

I say superb because they are very familiar interaction, as @liuyxpp said standard in image previews, maps, pdf reader, the list goes on.

<img width="197" alt="screen shot 2015-11-14 at 10 07 54 pm" src="https://cloud.githubusercontent.com/assets/1796208/11167577/72e3c348-8b1c-11e5-91c4-d862577ed7b9.png">
<img width="87" alt="screen shot 2015-11-14 at 10 08 05 pm" src="https://cloud.githubusercontent.com/assets/1796208/11167566/5cd794bc-8b1c-11e5-9063-60d4e538a6f0.png">
<img width="190" alt="screen shot 2015-11-14 at 10 08 18 pm" src="https://cloud.githubusercontent.com/assets/1796208/11167568/5cdab37c-8b1c-11e5-8857-d228195d0e87.png">

In the current tool the drag start/end define two opposite corners of a box. In this other mode the drag start end define the _center_ and a corner of a box. So the maximum box size if you drag form one corner to the opposite corner of the plot, is four times bigger than the plot region. 

> On Nov 15, 2015, at 00:12, Sarah Bird notifications@github.com wrote:
> 
> I still don't understand exactly the mechanics. And I can't be against something that I can't imagine.
> 
> I would like to argue that +/- buttons would be a superb feature addition that, to my understanding, achieves the same result (the center of your zoom out is the center of your plot)
> 
> I say superb because they are very familiar interaction, as @liuyxpp said standard in image previews, maps, pdf reader, the list goes on.
> 
> —
> Reply to this email directly or view it on GitHub.

I'm not against +/- buttons too but the centered ® box can certainly be used more efficiently and precisely than panning the thing you want to the center of the plot are and clicking a bunch of times. You just click the thing to want to zoom on and drag away from it, and then you zoom right on the spot you clicked. 

> On Nov 15, 2015, at 00:12, Sarah Bird notifications@github.com wrote:
> 
> I still don't understand exactly the mechanics. And I can't be against something that I can't imagine.
> 
> I would like to argue that +/- buttons would be a superb feature addition that, to my understanding, achieves the same result (the center of your zoom out is the center of your plot)
> 
> I say superb because they are very familiar interaction, as @liuyxpp said standard in image previews, maps, pdf reader, the list goes on.
> 
> —
> Reply to this email directly or view it on GitHub.

This is the way that matplotlib works, at least when using the qt toolbar. The smaller the selected region the larger the zoom out, they use a right drag, but I think it makes sense to implement it as Shift+box_zoom. Matplotlib also give a way to scales axis which could be added as Shift+pan.

http://matplotlib.org/2.0.0rc1/users/navigation_toolbar.html?highlight=navigation

The way the math works is that it zooms out to the point that the old axis bound fit within the selection rectangle.

I still want to make a box-centered mode for the zoom tool.

Resolving patch:
diff --git a/bokeh/models/tools.py b/bokeh/models/tools.py
--- a/bokeh/models/tools.py
+++ b/bokeh/models/tools.py
@@ -373,7 +373,7 @@ class CrosshairTool(Inspection):
     line_color="black",
     line_alpha=1.0,
     line_width=2,
-    line_dash=[4, 4]
+    line_dash=[4, 4],
 )
 
 class BoxZoomTool(Drag):
@@ -413,6 +413,11 @@ class BoxZoomTool(Drag):
 
     """)
 
+    origin = Enum("corner", "center", default="corner", help="""
+    Indicates whether the rectangular zoom area should originate from a corner
+    (top-left or bottom-right depending on direction) or the center of the box.
+    """)
+
 class ZoomInTool(Action):
     ''' *toolbar icon*: |zoom_in_icon|
 
@@ -510,6 +515,11 @@ class BoxSelectTool(Drag):
     A shaded annotation drawn to indicate the selection region.
     """)
 
+    origin = Enum("corner", "center", default="corner", help="""
+    Indicates whether the rectangular selection area should originate from a corner
+    (top-left or bottom-right depending on direction) or the center of the box.
+    """)
+
 DEFAULT_POLY_OVERLAY = lambda: PolyAnnotation(
     level="overlay",
     xs_units="screen",


Test patch: