Repository: enthought/chaco

Issue:
Demo financial_plot_dates.py break when zooming out
**Problem Description**
financial_plot_dates.py break when zooming out
**Reproduction Steps:**
Run the file and keep zooming out.
**Expected behavior:**
Plot disappear and raise the error
```
/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/scales/safetime.py:37: UserWarning: Timestamp out of range.  Returning safe default value.
  warnings.warn("Timestamp out of range.  Returning safe default value.")
Traceback (most recent call last):
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/qt4/base_window.py", line 202, in paintEvent
    self.handler.paintEvent(event)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/qt4/base_window.py", line 54, in paintEvent
    self._enable_window._paint(event)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/abstract_window.py", line 468, in _paint
    self.component.draw(gc, view_bounds=(0, 0, size[0], size[1]))
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/component.py", line 427, in draw
    self._draw(gc, view_bounds, mode)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/component.py", line 779, in _draw
    self._dispatch_draw(layer, gc, view_bounds, mode)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/container.py", line 272, in _dispatch_draw
    component._dispatch_draw(layer, gc, new_bounds, mode)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/component.py", line 799, in _dispatch_draw
    handler(gc, view_bounds, mode)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/enable/component.py", line 887, in _draw_underlay
    underlay.overlay(self, gc, view_bounds, mode)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/grid.py", line 307, in overlay
    self._compute_ticks(other_component)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/grid.py", line 255, in _compute_ticks
    scale=scale)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/scales_tick_generator.py", line 31, in get_ticks
    ticks = self.scale.ticks(data_low, data_high)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/scales/scales.py", line 446, in ticks
    ticks = scale.ticks(start, end, numticks)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/scales/time_scale.py", line 291, in ticks
    return trange(start, end, **{self.unit: self.val})
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/scales/time_scale.py", line 179, in trange
    return trange_years(start, end, value)
  File "/Users/ktakami/.edm/envs/chaco-dev/lib/python2.7/site-packages/chaco/scales/time_scale.py", line 137, in trange_years
    dt = datetime(dt_start.year-dyears, 1, 1, 0, 0, 0, 0)
ValueError: year is out of range
```

**OS, Python version:** 
OSX, Python 2.7

splits from #385 


Discussion:
The following demos also break when the user zooms out too much
* `shell/dates.py`
* `financial/correlations.py`
* `financial/stock_prices.py`
PR #500 Fixes the original issue. 
Following bugs remain.
> The following demos also break when the user zooms out too much
> 
>     * `shell/dates.py`
> 
>     * `financial/correlations.py`
> 
>     * `financial/stock_prices.py`



Resolving patch:
diff --git a/examples/demo/financial/correlations.py b/examples/demo/financial/correlations.py
--- a/examples/demo/financial/correlations.py
+++ b/examples/demo/financial/correlations.py
@@ -96,8 +96,8 @@ def _create_returns_plot(self):
         renderer.tools.append(RangeSelection(renderer, left_button_selects = False,
             auto_handle_event = False))
         plot.tools.append(PanTool(plot, drag_button="left", constrain=True,
-            constrain_direction="x"))
-        plot.overlays.append(ZoomTool(plot, tool_mode="range", max_zoom_out=1.0))
+            constrain_direction="x", restrict_to_data=True))
+        plot.overlays.append(ZoomTool(plot, tool_mode="range", max_zoom_out=1.0, x_min_zoom_factor=float(1e-3)))
         # Attach the range selection to the last renderer; any one will do
         self._range_selection_overlay = RangeSelectionOverlay(renderer,
                                     metadata_name="selections")
diff --git a/examples/demo/financial/stock_prices.py b/examples/demo/financial/stock_prices.py
--- a/examples/demo/financial/stock_prices.py
+++ b/examples/demo/financial/stock_prices.py
@@ -67,12 +67,14 @@ def _create_price_plots(self, times, prices, mini_height=75):
 
         # Add pan and zoom
         price_plot.tools.append(PanTool(price_plot, constrain=True,
-                                        constrain_direction="x"))
+                                        constrain_direction="x",
+                                        restrict_to_data=True))
         price_plot.overlays.append(ZoomTool(price_plot, drag_button="right",
                                               always_on=True,
                                               tool_mode="range",
                                               axis="index",
                                               max_zoom_out_factor=1.0,
+                                              x_min_zoom_factor=float(1e-3)
                                              ))
 
         # Create the miniplot
diff --git a/examples/demo/shell/dates.py b/examples/demo/shell/dates.py
--- a/examples/demo/shell/dates.py
+++ b/examples/demo/shell/dates.py
@@ -30,8 +30,14 @@
 # Add some titles
 title("Plotting Dates")
 
+current_plot = curplot()
 # Set the plot's horizontal axis to be a time scale
-curplot().x_axis.tick_generator.scale = CalendarScaleSystem()
+current_plot.x_axis.tick_generator.scale = CalendarScaleSystem()
+zoom_tool = current_plot.overlays[2]
+pan_tool = current_plot.tools[0]
+zoom_tool.x_min_zoom_factor = float(1e-3)
+pan_tool.restrict_to_data = True
+
 
 # This command is only necessary if running from command line
 show()


Test patch: