/usr/lib/python2.7/dist-packages/chaco/tools/range_selection_overlay.py is in python-chaco 4.4.1-1.2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | """ Defines the RangeSelectionOverlay class.
"""
from __future__ import with_statement
# Major library imports
from numpy import arange, array
# Enthought library imports
from enable.api import ColorTrait, LineStyle
from traits.api import Enum, Float, Property, Str, Instance, \
cached_property
from chaco.api import AbstractOverlay, arg_find_runs, GridMapper, AbstractMapper
class RangeSelectionOverlay(AbstractOverlay):
""" Highlights the selection region on a component.
Looks at a given metadata field of self.component for regions to draw as
selected.
"""
# The axis to which this tool is perpendicular.
axis = Enum("index", "value")
# Mapping from screen space to data space. By default, it is just
# self.component.
plot = Property(depends_on='component')
# The mapper (and associated range) that drive this RangeSelectionOverlay.
# By default, this is the mapper on self.plot that corresponds to self.axis.
mapper = Instance(AbstractMapper)
# The element of an (x,y) tuple that corresponds to the axis index.
# By default, this is set based on self.asix and self.plot.orientation,
# but it can be overriden and set to 0 or 1.
axis_index = Property
# The name of the metadata to look at for dataspace bounds. The metadata
# can be either a tuple (dataspace_start, dataspace_end) in "selections" or
# a boolean array mask of seleted dataspace points with any other name
metadata_name = Str("selections")
#------------------------------------------------------------------------
# Appearance traits
#------------------------------------------------------------------------
# The color of the selection border line.
border_color = ColorTrait("dodgerblue")
# The width, in pixels, of the selection border line.
border_width = Float(1.0)
# The line style of the selection border line.
border_style = LineStyle("solid")
# The color to fill the selection region.
fill_color = ColorTrait("lightskyblue")
# The transparency of the fill color.
alpha = Float(0.3)
#------------------------------------------------------------------------
# AbstractOverlay interface
#------------------------------------------------------------------------
def overlay(self, component, gc, view_bounds=None, mode="normal"):
""" Draws this component overlaid on another component.
Overrides AbstractOverlay.
"""
axis_ndx = self.axis_index
lower_left = [0,0]
upper_right = [0,0]
# Draw the selection
coords = self._get_selection_screencoords()
for coord in coords:
start, end = coord
lower_left[axis_ndx] = start
lower_left[1-axis_ndx] = component.position[1-axis_ndx]
upper_right[axis_ndx] = end - start
upper_right[1-axis_ndx] = component.bounds[1-axis_ndx]
with gc:
gc.clip_to_rect(component.x, component.y, component.width, component.height)
gc.set_alpha(self.alpha)
gc.set_fill_color(self.fill_color_)
gc.set_stroke_color(self.border_color_)
gc.set_line_width(self.border_width)
gc.set_line_dash(self.border_style_)
gc.draw_rect((lower_left[0], lower_left[1],
upper_right[0], upper_right[1]))
#------------------------------------------------------------------------
# Private methods
#------------------------------------------------------------------------
def _get_selection_screencoords(self):
""" Returns a tuple of (x1, x2) screen space coordinates of the start
and end selection points.
If there is no current selection, then returns an empty list.
"""
ds = getattr(self.plot, self.axis)
selection = ds.metadata.get(self.metadata_name, None)
if selection is None:
return []
# "selections" metadata must be a tuple
if self.metadata_name == "selections" or \
(selection is not None and isinstance(selection, tuple)):
if selection is not None and len(selection) == 2:
return [self.mapper.map_screen(array(selection))]
else:
return []
# All other metadata is interpreted as a mask on dataspace
else:
ar = arange(0,len(selection), 1)
runs = arg_find_runs(ar[selection])
coords = []
for inds in runs:
start = ds._data[ar[selection][inds[0]]]
end = ds._data[ar[selection][inds[1]-1]]
coords.append(self.mapper.map_screen(array((start, end))))
return coords
def _determine_axis(self):
""" Determines which element of an (x,y) coordinate tuple corresponds
to the tool's axis of interest.
This method is only called if self._axis_index hasn't been set (or is
None).
"""
if self.axis == "index":
if self.plot.orientation == "h":
return 0
else:
return 1
else: # self.axis == "value"
if self.plot.orientation == "h":
return 1
else:
return 0
#------------------------------------------------------------------------
# Trait event handlers
#------------------------------------------------------------------------
def _component_changed(self, old, new):
self._attach_metadata_handler(old, new)
return
def _axis_changed(self, old, new):
self._attach_metadata_handler(old, new)
return
def _attach_metadata_handler(self, old, new):
# This is used to attach a listener to the datasource so that when
# its metadata has been updated, we catch the event and update properly
if not self.plot:
return
datasource = getattr(self.plot, self.axis)
if old:
datasource.on_trait_change(self._metadata_change_handler, "metadata_changed",
remove=True)
if new:
datasource.on_trait_change(self._metadata_change_handler, "metadata_changed")
return
def _metadata_change_handler(self, event):
self.component.request_redraw()
return
#------------------------------------------------------------------------
# Default initializers
#------------------------------------------------------------------------
def _mapper_default(self):
# If the plot's mapper is a GridMapper, return either its
# x mapper or y mapper
mapper = getattr(self.plot, self.axis + "_mapper")
if isinstance(mapper, GridMapper):
if self.axis == 'index':
return mapper._xmapper
else:
return mapper._ymapper
else:
return mapper
#------------------------------------------------------------------------
# Property getter/setters
#------------------------------------------------------------------------
@cached_property
def _get_plot(self):
return self.component
@cached_property
def _get_axis_index(self):
return self._determine_axis()
# EOF
|