8000 Improved selection widget by blink1073 · Pull Request #3502 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Improved selection widget #3502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Nov 13, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Improve handling of out-of-bounds releases
  • Loading branch information
blink1073 committed Nov 12, 2014
commit c25efbd54dd409ca5acae8b0fc5df010ecc20947
7 changes: 4 additions & 3 deletions lib/matplotlib/tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def onselect(epress, erelease):
ax._got_onselect = True
assert epress.xdata == 100
assert epress.ydata == 100
assert erelease.xdata == 150
assert erelease.ydata == 150
assert erelease.xdata == 200
assert erelease.ydata == 200

tool = widgets.RectangleSelector(ax, onselect, **kwargs)
event = get_event(ax, xdata=100, ydata=100, button=1)
Expand All @@ -82,7 +82,8 @@ def onselect(epress, erelease):
event = get_event(ax, xdata=125, ydata=125, button=1)
tool.onmove(event)

event = get_event(ax, xdata=150, ydata=150, button=1)
# purposely drag outside of axis for release
event = get_event(ax, xdata=250, ydata=250, button=1)
tool.release(event)

assert ax._got_onselect
Expand Down
60 changes: 34 additions & 26 deletions lib/matplotlib/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)

import copy
import six
from six.moves import zip

Expand Down Expand Up @@ -1163,19 +1164,8 @@ def ignore(self, event):
return event.inaxes != self.ax

# If a button was pressed, check if the release-button is the
# same. If event is out of axis, limit the data coordinates to axes
# boundaries.
if event.button == self.eventpress.button and event.inaxes != self.ax:
(xdata, ydata) = self.ax.transData.inverted().transform_point(
(event.x, event.y))
x0, x1 = self.ax.get_xbound()
y0, y1 = self.ax.get_ybound()
xdata = max(x0, xdata)
xdata = min(x1, xdata)
ydata = max(y0, ydata)
ydata = min(y1, ydata)
event.xdata = xdata
event.ydata = ydata
# same.
if event.button == self.eventpress.button:
return False

# If a button was pressed, check if the release-button is the
Expand Down Expand Up @@ -1206,17 +1196,31 @@ def update(self):
self.canvas.draw_idle()
return False

def _get_data(self, event):
"""Limit the xdata and ydata to the axes limits"""
x0, x1 = self.ax.get_xbound()
y0, y1 = self.ax.get_ybound()
xdata = max(x0, event.xdata)
xdata = min(x1, xdata)
ydata = max(y0, event.ydata)
ydata = min(y1, ydata)
return xdata, ydata

def press(self, event):
"""Button press handler"""
if not self.ignore(event):
self.eventpress = event
self.eventpress = copy.copy(event)
self.eventpress.xdata, self.eventpress.ydata = (
self._get_data(event))
return True
return False

def release(self, event):
"""Button release event"""
if not self.ignore(event) and not self.eventpress is None:
self.eventrelease = event
self.eventrelease = copy.copy(event)
self.eventrelease.xdata, self.eventrelease.ydata = (
self._get_data(event))
return True
else:
return False
Expand Down Expand Up @@ -1363,10 +1367,11 @@ def press(self, event):
if self.span_stays:
self.stay_rect.set_visible(False)

xdata, ydata = self._get_data(event)
if self.direction == 'horizontal':
self.pressv = event.xdata
self.pressv = xdata
else:
self.pressv = event.ydata
self.pressv = ydata
return False

def release(self, event):
Expand All @@ -1386,10 +1391,11 @@ def release(self, event):

self.canvas.draw()
vmin = self.pressv
xdata, ydata = self._get_data(event)
if self.direction == 'horizontal':
vmax = event.xdata or self.prev[0]
vmax = xdata or self.prev[0]
else:
vmax = event.ydata or self.prev[1]
vmax = ydata or self.prev[1]

if vmin > vmax:
vmin, vmax = vmax, vmin
Expand All @@ -1404,7 +1410,7 @@ def onmove(self, event):
"""on motion notify event"""
if self.pressv is None or self.ignore(event):
return
x, y = event.xdata, event.ydata
x, y = self._get_data(event)
self.prev = x, y
if self.direction == 'horizontal':
v = x
Expand All @@ -1423,10 +1429,11 @@ def onmove(self, event):

if self.onmove_callback is not None:
vmin = self.pressv
xdata, ydata = self._get_data(event)
if self.direction == 'horizontal':
vmax = event.xdata or self.prev[0]
vmax = xdata or self.prev[0]
else:
vmax = event.ydata or self.prev[1]
vmax = ydata or self.prev[1]

if vmin > vmax:
vmin, vmax = vmax, vmin
Expand Down Expand Up @@ -1609,7 +1616,8 @@ def onmove(self, event):
"""on motion notify event if box/line is wanted"""
if self.eventpress is None or self.ignore(event):
return
x, y = event.xdata, event.ydata # actual position (with

x, y = self._get_data(event) # actual position (with
# (button still pressed)
if self.drawtype == 'box':
minx, maxx = self.eventpress.xdata, x # click-x and actual mouse-x
Expand Down Expand Up @@ -1695,7 +1703,7 @@ def onpress(self, event):
def press(self, event):
if not _SelectorWidget.press(self, event):
return
self.verts = [(event.xdata, event.ydata)]
self.verts = [self._get_data(event)]
self.line.set_visible(True)

def onrelease(self, event):
Expand All @@ -1705,7 +1713,7 @@ def release(self, event):
if not _SelectorWidget.release(self, event):
return
if self.verts is not None:
self.verts.append((event.xdata, event.ydata))
self.verts.append(self._get_data(event))
self.onselect(self.verts)
self.line.set_data([[], []])
self.line.set_visible(False)
Expand All @@ -1714,7 +1722,7 @@ def release(self, event):
def onmove(self, event):
if self.ignore(event) or self.verts is None:
return
self.verts.append((event.xdata, event.ydata))
self.verts.append(self._get_data(event))

self.line.set_data(list(zip(*self.verts)))

Expand Down
0