3
Allows editing of a line plot.
5
Left-dragging a point will move its position.
7
Right-drag pans the plot.
9
Mousewheel up and down zooms the plot in and out.
11
Pressing "z" brings up the Zoom Box, and you can click-drag a rectangular region to
12
zoom. If you use a sequence of zoom boxes, pressing alt-left-arrow and
13
alt-right-arrow moves you forwards and backwards through the "zoom history".
16
# Major library imports
17
from numpy import linspace
18
from scipy.special import jn
20
from chaco.example_support import COLOR_PALETTE
22
# Enthought library imports
23
from enable.tools.api import DragTool
24
from enable.api import Component, ComponentEditor
25
from traits.api import HasTraits, Instance, Int, Tuple
26
from traitsui.api import Item, Group, View
29
from chaco.api import add_default_axes, add_default_grids, \
30
OverlayPlotContainer, PlotLabel, ScatterPlot, create_line_plot
31
from chaco.tools.api import PanTool, ZoomTool
35
class PointDraggingTool(DragTool):
37
component = Instance(Component)
39
# The pixel distance from a point that the cursor is still considered
40
# to be 'on' the point
43
# The index of the point being dragged
46
# The original dataspace values of the index and value datasources
47
# corresponding to _drag_index
50
def is_draggable(self, x, y):
51
# Check to see if (x,y) are over one of the points in self.component
52
if self._lookup_point(x, y) is not None:
57
def normal_mouse_move(self, event):
60
ndx = plot.map_index((event.x, event.y), self.threshold)
62
if plot.index.metadata.has_key('selections'):
63
del plot.index.metadata['selections']
65
plot.index.metadata['selections'] = [ndx]
67
plot.invalidate_draw()
71
def drag_start(self, event):
73
ndx = plot.map_index((event.x, event.y), self.threshold)
76
self._drag_index = ndx
77
self._orig_value = (plot.index.get_data()[ndx], plot.value.get_data()[ndx])
79
def dragging(self, event):
82
data_x, data_y = plot.map_data((event.x, event.y))
84
plot.index._data[self._drag_index] = data_x
85
plot.value._data[self._drag_index] = data_y
86
plot.index.data_changed = True
87
plot.value.data_changed = True
90
def drag_cancel(self, event):
92
plot.index._data[self._drag_index] = self._orig_value[0]
93
plot.value._data[self._drag_index] = self._orig_value[1]
94
plot.index.data_changed = True
95
plot.value.data_changed = True
98
def drag_end(self, event):
100
if plot.index.metadata.has_key('selections'):
101
del plot.index.metadata['selections']
102
plot.invalidate_draw()
103
plot.request_redraw()
105
def _lookup_point(self, x, y):
106
""" Finds the point closest to a screen point if it is within self.threshold
117
(screen_x, screen_y, distance) of datapoint nearest to the input *(x,y)*.
118
If no data points are within *self.threshold* of *(x,y)*, returns None.
121
if hasattr(self.component, 'get_closest_point'):
122
# This is on BaseXYPlots
123
return self.component.get_closest_point((x,y), threshold=self.threshold)
128
#===============================================================================
129
# # Create the Chaco plot.
130
#===============================================================================
131
def _create_plot_component():
133
container = OverlayPlotContainer(padding = 50, fill_padding = True,
134
bgcolor = "lightgray", use_backbuffer=True)
136
# Create the initial X-series of data
140
x = linspace(low, high, numpoints)
143
lineplot = create_line_plot((x,y), color=tuple(COLOR_PALETTE[0]), width=2.0)
144
lineplot.selected_color = "none"
145
scatter = ScatterPlot(index = lineplot.index,
146
value = lineplot.value,
147
index_mapper = lineplot.index_mapper,
148
value_mapper = lineplot.value_mapper,
149
color = tuple(COLOR_PALETTE[0]),
151
scatter.index.sort_order = "ascending"
153
scatter.bgcolor = "white"
154
scatter.border_visible = True
156
add_default_grids(scatter)
157
add_default_axes(scatter)
159
scatter.tools.append(PanTool(scatter, drag_button="right"))
161
# The ZoomTool tool is stateful and allows drawing a zoom
162
# box to select a zoom region.
163
zoom = ZoomTool(scatter, tool_mode="box", always_on=False, drag_button=None)
164
scatter.overlays.append(zoom)
166
scatter.tools.append(PointDraggingTool(scatter))
168
container.add(lineplot)
169
container.add(scatter)
171
# Add the title at the top
172
container.overlays.append(PlotLabel("Line Editor",
175
overlay_position="top"))
180
#===============================================================================
181
# Attributes to use for the plot view.
183
title="Simple line plot"
184
#===============================================================================
185
# # Demo class that is used by the demo.py application.
186
#===============================================================================
187
class Demo(HasTraits):
188
plot = Instance(Component)
192
Item('plot', editor=ComponentEditor(size=size),
194
orientation = "vertical"),
195
resizable=True, title=title
198
def _plot_default(self):
199
return _create_plot_component()
203
if __name__ == "__main__":
204
demo.configure_traits()