Repository: bokeh/bokeh

Issue:
Remove the Resize Tool?! 
Speak now or forever hold you peace :D

The new layout work has some conflicts with the resize tool.

In the new layout work sizes are determined from the outside-in, rather than the inside-out. 

In the layout work, the resize tool will be removed from the set of default tools and it may be made no-op (at least for a while) to move things forward.

After some discussion with @bryevdv we thought it would be good to get some feedback on whether the resize tool is useful at all, and if so to describe the use cases so we can be thoughtful about adding it back in.

It may be, for example, that resize tool is useful on the outside layout box (which may contain one or many plots) so that everything inside resizes to fit that new user specified size.



Discussion:
We should ask for feedback in the mailing list as well...

That seems reasonable. 

If you have smarter layout in the pipe, then toss the resize.

Thanks for the feedback @crashMOGWAI. 

Message posted to mailing list: https://groups.google.com/a/continuum.io/forum/#!topic/bokeh/s7NdG10rY2o

changing this to `task` there are some +1's and no -1's I think we can proceed. All examples have already had resize tool removed. Just need to remove the tool itself in a deprecatable way that just omits the tool and doesnt break anything. 

@pzwang I think you have opinions here

Marking this for `0.12.7` to add a deprecation of some sort, and remove in `1.0` @pzwang last chance to voice a different opinion. 

Resolving patch:
diff --git a/bokeh/models/plots.py b/bokeh/models/plots.py
--- a/bokeh/models/plots.py
+++ b/bokeh/models/plots.py
@@ -23,7 +23,7 @@
 from .renderers import DataRenderer, DynamicImageRenderer, GlyphRenderer, Renderer, TileRenderer
 from .scales import Scale, CategoricalScale, LinearScale, LogScale
 from .sources import DataSource, ColumnDataSource
-from .tools import Tool, Toolbar
+from .tools import ResizeTool, Tool, Toolbar
 
 class Plot(LayoutDOM):
     ''' Model representing a plot, containing glyphs, guides, annotations.
@@ -239,12 +239,17 @@ def add_tools(self, *tools):
             None
 
         '''
-        if not all(isinstance(tool, Tool) for tool in tools):
-            raise ValueError("All arguments to add_tool must be Tool subclasses.")
-
         for tool in tools:
+            if isinstance(tool, ResizeTool):
+                deprecated("ResizeTool is removed in Bokeh 0.12.7, adding it is a no-op. In the future, accessing ResizeTool will be an error")
+                continue
+
+            if not isinstance(tool, Tool):
+                raise ValueError("All arguments to add_tool must be Tool subclasses.")
+
             if hasattr(tool, 'overlay'):
                 self.renderers.append(tool.overlay)
+
             self.toolbar.tools.append(tool)
 
     def add_glyph(self, source_or_glyph, glyph=None, **kw):
diff --git a/bokeh/models/tools.py b/bokeh/models/tools.py
--- a/bokeh/models/tools.py
+++ b/bokeh/models/tools.py
@@ -270,14 +270,8 @@ class ResetTool(Action):
     """)
 
 
-class ResizeTool(Drag):
-    ''' *toolbar icon*: |resize_icon|
-
-    The resize tool allows the user to left-drag a mouse or drag a finger
-    to resize the entire plot area on the screen.
-
-    .. |resize_icon| image:: /_images/icons/Resize.png
-        :height: 18pt
+class ResizeTool(object):
+    ''' DEPRECATED in 0.12.7, attempting to use will be a NO-OP
 
     '''
 


Test patch:
diff --git a/bokeh/core/tests/test_query.py b/bokeh/core/tests/test_query.py
--- a/bokeh/core/tests/test_query.py
+++ b/bokeh/core/tests/test_query.py
@@ -6,7 +6,7 @@
 
 from bokeh.models import (
     Axis, BoxZoomTool, ColumnDataSource, DatetimeAxis, GlyphRenderer, Grid, LinearAxis,
-    LogAxis, PanTool, Plot, SaveTool, Range1d, ResetTool, ResizeTool, Tool, WheelZoomTool,
+    LogAxis, PanTool, Plot, SaveTool, Range1d, ResetTool, Tool, WheelZoomTool,
 )
 from bokeh.models.glyphs import Glyph, Circle, Line, Rect
 
@@ -43,7 +43,7 @@ def large_plot():
     plot.add_layout(Grid(dimension=1), 'left')
 
     plot.add_tools(
-        BoxZoomTool(), PanTool(), SaveTool(), ResetTool(), ResizeTool(), WheelZoomTool(),
+        BoxZoomTool(), PanTool(), SaveTool(), ResetTool(), WheelZoomTool(),
     )
 
     return plot
@@ -61,12 +61,11 @@ def large_plot():
 
     Grid: 2,
 
-    Tool: 6,
+    Tool: 5,
     BoxZoomTool: 1,
     PanTool: 1,
     SaveTool: 1,
     ResetTool: 1,
-    ResizeTool: 1,
     WheelZoomTool: 1,
 }
 
@@ -151,7 +150,7 @@ def test_in():
 
     # count adjusted by hand to account for duplicates/subclasses
     res = list(q.find(plot.references(), dict(type={q.IN: list(typcases.keys())})))
-    assert len(res) == 18
+    assert len(res) == 17
 
 def test_disjuction():
     res = list(
diff --git a/bokeh/plotting/tests/test_figure.py b/bokeh/plotting/tests/test_figure.py
--- a/bokeh/plotting/tests/test_figure.py
+++ b/bokeh/plotting/tests/test_figure.py
@@ -13,7 +13,6 @@
     LogScale,
     PanTool,
     ResetTool,
-    ResizeTool,
     Title,
 )
 
@@ -140,9 +139,9 @@ def test_grid(self):
         self.assertEqual(len(p.grid), 2)
 
     def test_tools(self):
-        TOOLS = "resize,pan,box_zoom,reset,lasso_select"
+        TOOLS = "pan,box_zoom,reset,lasso_select"
         fig = plt.figure(tools=TOOLS)
-        expected = [ResizeTool, PanTool, BoxZoomTool, ResetTool, LassoSelectTool]
+        expected = [PanTool, BoxZoomTool, ResetTool, LassoSelectTool]
 
         self.assertEqual(len(fig.tools), len(expected))
         for i, _type in enumerate(expected):
diff --git a/bokeh/tests/test_objects.py b/bokeh/tests/test_objects.py
--- a/bokeh/tests/test_objects.py
+++ b/bokeh/tests/test_objects.py
@@ -15,7 +15,7 @@ def large_plot(n):
     from bokeh.models import (
         Plot, LinearAxis, Grid, GlyphRenderer,
         ColumnDataSource, DataRange1d, PanTool, ZoomInTool, ZoomOutTool, WheelZoomTool, BoxZoomTool,
-        BoxSelectTool, ResizeTool, SaveTool, ResetTool
+        BoxSelectTool, SaveTool, ResetTool
     )
     from bokeh.models.layouts import Column
     from bokeh.models.glyphs import Line
@@ -42,10 +42,9 @@ def large_plot(n):
         wheel_zoom = WheelZoomTool()
         box_zoom = BoxZoomTool()
         box_select = BoxSelectTool()
-        resize = ResizeTool()
         save = SaveTool()
         reset = ResetTool()
-        tools = [pan, zoom_in, zoom_out, wheel_zoom, box_zoom, box_select, resize, save, reset]
+        tools = [pan, zoom_in, zoom_out, wheel_zoom, box_zoom, box_select, save, reset]
         plot.add_tools(*tools)
         col.children.append(plot)
         objects |= set([
diff --git a/bokehjs/test/models/tools/gestures/index.coffee b/bokehjs/test/models/tools/gestures/index.coffee
--- a/bokehjs/test/models/tools/gestures/index.coffee
+++ b/bokehjs/test/models/tools/gestures/index.coffee
@@ -1,3 +1,2 @@
-require "./resize_tool"
 require "./wheel_pan_tool"
 require "./wheel_zoom_tool"
diff --git a/bokehjs/test/models/tools/gestures/resize_tool.coffee b/bokehjs/test/models/tools/gestures/resize_tool.coffee
deleted file mode 100644
--- a/bokehjs/test/models/tools/gestures/resize_tool.coffee
+++ /dev/null
@@ -1,52 +0,0 @@
-{expect} = require "chai"
-utils = require "../../../utils"
-sinon = require 'sinon'
-
-{Document} = utils.require("document")
-{ResizeTool} = utils.require("models/tools/gestures/resize_tool")
-{ResizeToolView} = utils.require("models/tools/gestures/resize_tool")
-{Range1d} = utils.require("models/ranges/range1d")
-{Plot} = utils.require("models/plots/plot")
-{Toolbar} = utils.require("models/tools/toolbar")
-
-describe "ResizeTool", ->
-
-  describe "View", ->
-
-    afterEach ->
-      utils.unstub_canvas()
-      utils.unstub_solver()
-
-    beforeEach ->
-      utils.stub_canvas()
-      utils.stub_solver()
-
-      @x_range = new Range1d({start: 0, end:10})
-      @y_range = new Range1d({start: 0, end: 10})
-      toolbar = new Toolbar()
-      doc = new Document()
-
-      plot = new Plot({x_range: @x_range, y_range: @y_range, toolbar: toolbar})
-      plot_view = new plot.default_view({model: plot, parent: null})
-      doc.add_root(plot)
-      @plot_canvas_view = new plot.plot_canvas.default_view({model: plot.plot_canvas, parent: plot_view})
-      @resizetool = new ResizeTool()
-      @resizetool_view = new @resizetool.default_view({
-        model: @resizetool
-        plot_view: @plot_canvas_view
-        parent: null # wrong
-      })
-
-    it "_update should call plot_view update dimensions", ->
-      spy = sinon.spy(@plot_canvas_view, 'update_dimensions')
-      expect(spy.callCount).to.be.equal 0
-      @resizetool_view._update(100, 200)
-      expect(spy.callCount).to.be.equal 1
-
-    it "_update should not call plot_view update dimensions if too small", ->
-      spy = sinon.spy(@plot_canvas_view, 'update_dimensions')
-      expect(spy.callCount).to.be.equal 0
-      @resizetool_view.cw = 10
-      @resizetool_view.ch = 10
-      @resizetool_view._update(10, 10)
-      expect(spy.callCount).to.be.equal 0