Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
2ed0d49
Store prev event to handle out of bounds selections
Dec 19, 2014
f8eefe6
Upgrade RectangleSelector with ToolHandles and add Ellipse
Dec 19, 2014
7f044cf
Add toolhandles class
Dec 19, 2014
f450df6
Add test using tool handles
Dec 19, 2014
79294e0
Add a helper function to get axes
Dec 19, 2014
fd264a2
Do not allow extents outside the image and add a path property
Dec 19, 2014
438715f
Finish rectangle handle tests and add ellipse test with key modifiers
Dec 19, 2014
e560713
Rename path property to geometry and return consistent results.
Dec 20, 2014
5025ba2
Add geometry tests.
Dec 20, 2014
b118294
Remove extra line.
Dec 20, 2014
b15cf12
Refactor the event handling methods
Dec 20, 2014
e96fe81
Update rectangle logic to include '_moving'
Dec 20, 2014
240cfa2
Clean up event handling and add a state attribute
Dec 20, 2014
7915db8
Add state handling to onmove
Dec 20, 2014
f7a9222
More "state" refactoring
Dec 20, 2014
7c04e25
Add key release and continue refactoring state handling
Dec 20, 2014
cf491db
Recreate the _get_data method and more event refactoring
Dec 20, 2014
7ece2fa
Refactor the event creator to call the private methods
Dec 20, 2014
59ccd81
Preserve existing api for event handler functions
Dec 21, 2014
a033e8e
Preserve event return values
Dec 24, 2014
2923f97
Add cleanup to tests and fix default rect prop
Dec 24, 2014
6549538
Pep8 fixes
Dec 24, 2014
491276e
Fix bug in SpanSelector when blit=True
Jan 17, 2015
744308c
Clear events after valid release
Jan 18, 2015
a7518b3
Do not attempt to draw artists if ax is invisible
Jan 18, 2015
77dc52b
Ignore events when axes are invisible
Jan 18, 2015
48ebf30
Fix span selector onmove when we exit axes
Feb 21, 2015
3ffd7c0
Restore previous behaviour and allow escape to clear the current sele…
Aug 19, 2015
e802991
Fix failing tests
Aug 19, 2015
af6e1b4
Fix handling of center handle
Aug 20, 2015
f5666a4
Remove debug print
Aug 20, 2015
545a727
STY: PEP8
tacaswell Aug 22, 2015
feb58fe
FIX: do not call draw_idle if blitting
tacaswell Aug 22, 2015
7bd67d2
DOC: make rectangle demo use handles
tacaswell Aug 22, 2015
b60a84d
Add docstring for EllipseSelector and use print() statements
Aug 22, 2015
840a671
Revert to old draw types and add docs about key modifiers
Aug 23, 2015
2a11f5f
Revert change to the example
Aug 23, 2015
8da7985
Remove extra draw_idle trigger
Aug 23, 2015
cfe4df1
Update the docstring
Aug 23, 2015
bc225b6
Remove extraneous doc
Aug 23, 2015
59145af
Fix failing test
Aug 23, 2015
d491ac9
Update docstring, use self.useblit, use space for move
Aug 25, 2015
8e8e473
Use new state_modifier_keys dictionary
Aug 26, 2015
2ed0419
Clear the active handle when invisible
Aug 26, 2015
d5b5d86
Collapse the shape on improper draw to prevent showing the previous s…
Aug 26, 2015
87ab199
Fix test using 'alt' key
Aug 26, 2015
9eaae32
Clean up and add more docs
Sep 1, 2015
819804f
Make on_key_release use the state_modifier_keys
Sep 1, 2015
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
3 changes: 2 additions & 1 deletion examples/widgets/rectangle_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def toggle_selector(event):
drawtype='box', useblit=True,
button=[1, 3], # don't use middle button
minspanx=5, minspany=5,
spancoords='pixels')
spancoords='pixels',
interactive=True)
plt.connect('key_press_event', toggle_selector)
plt.show()
163 changes: 126 additions & 37 deletions lib/matplotlib/tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,18 @@
import matplotlib.pyplot as plt
from matplotlib.testing.decorators import cleanup

from numpy.testing import assert_allclose

def get_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):

def get_ax():
fig, ax = plt.subplots(1, 1)
ax.plot([0, 200], [0, 200])
ax.set_aspect(1.0)
ax.figure.canvas.draw()
return ax


def do_event(tool, etype, button=1, xdata=0, ydata=0, key=None, step=1):
"""
*name*
the event name
Expand Down Expand Up @@ -51,6 +61,7 @@ def get_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
"""
event = mock.Mock()
event.button = button
ax = tool.ax
event.x, event.y = ax.transData.transform([(xdata, ydata),
(xdata, ydata)])[00]
event.xdata, event.ydata = xdata, ydata
Expand All @@ -60,32 +71,33 @@ def get_event(ax, button=1, xdata=0, ydata=0, key=None, step=1):
event.step = step
event.guiEvent = None
event.name = 'Custom'
return event

func = getattr(tool, etype)
func(event)


@cleanup
def check_rectangle(**kwargs):
fig, ax = plt.subplots(1, 1)
ax.plot([0, 200], [0, 200])
ax.figure.canvas.draw()
ax = get_ax()

def onselect(epress, erelease):
ax._got_onselect = True
assert epress.xdata == 100
assert epress.ydata == 100
assert erelease.xdata == 200
assert erelease.ydata == 200
assert erelease.xdata == 199
assert erelease.ydata == 199

tool = widgets.RectangleSelector(ax, onselect, **kwargs)
event = get_event(ax, xdata=100, ydata=100, button=1)
tool.press(event)

event = get_event(ax, xdata=125, ydata=125, button=1)
tool.onmove(event)
do_event(tool, 'press', xdata=100, ydata=100, button=1)
do_event(tool, 'onmove', xdata=199, ydata=199, button=1)

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

if kwargs.get('drawtype', None) not in ['line', 'none']:
assert_allclose(tool.geometry,
[[100., 100, 199, 199, 100], [100, 199, 199, 100, 100]],
err_msg=tool.geometry)

assert ax._got_onselect

Expand All @@ -99,11 +111,101 @@ def test_rectangle_selector():
check_rectangle(rectprops=dict(fill=True))


@cleanup
def test_ellipse():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These need @cleanup decorators, I suspect that is related to the seemingly un-related failures as the global state of pyplot leaks across tests.

"""For ellipse, test out the key modifiers"""
ax = get_ax()

def onselect(epress, erelease):
pass

tool = widgets.EllipseSelector(ax, onselect=onselect,
maxdist=10, interactive=True)
tool.extents = (100, 150, 100, 150)

# drag the rectangle
do_event(tool, 'press', xdata=10, ydata=10, button=1,
key=' ')
do_event(tool, 'onmove', xdata=30, ydata=30, button=1)
do_event(tool, 'release', xdata=30, ydata=30, button=1)
assert tool.extents == (120, 170, 120, 170), tool.extents

# create from center
do_event(tool, 'on_key_press', xdata=100, ydata=100, button=1,
key='control')
do_event(tool, 'press', xdata=100, ydata=100, button=1)
do_event(tool, 'onmove', xdata=125, ydata=125, button=1)
do_event(tool, 'release', xdata=125, ydata=125, button=1)
do_event(tool, 'on_key_release', xdata=100, ydata=100, button=1,
key='control')
assert tool.extents == (75, 125, 75, 125), tool.extents

# create a square
do_event(tool, 'on_key_press', xdata=10, ydata=10, button=1,
key='shift')
do_event(tool, 'press', xdata=10, ydata=10, button=1)
do_event(tool, 'onmove', xdata=35, ydata=30, button=1)
do_event(tool, 'release', xdata=35, ydata=30, button=1)
do_event(tool, 'on_key_release', xdata=10, ydata=10, button=1,
key='shift')
extents = [int(e) for e in tool.extents]
assert extents == [10, 35, 10, 34]

# create a square from center
do_event(tool, 'on_key_press', xdata=100, ydata=100, button=1,
key='ctrl+shift')
do_event(tool, 'press', xdata=100, ydata=100, button=1)
do_event(tool, 'onmove', xdata=125, ydata=130, button=1)
do_event(tool, 'release', xdata=125, ydata=130, button=1)
do_event(tool, 'on_key_release', xdata=100, ydata=100, button=1,
key='ctrl+shift')
extents = [int(e) for e in tool.extents]
assert extents == [70, 129, 70, 130], extents

assert tool.geometry.shape == (2, 74)
assert_allclose(tool.geometry[:, 0], [70., 100])


@cleanup
def test_rectangle_handles():
ax = get_ax()

def onselect(epress, erelease):
pass

tool = widgets.RectangleSelector(ax, onselect=onselect,
maxdist=10, interactive=True)
tool.extents = (100, 150, 100, 150)

assert tool.corners == (
(100, 150, 150, 100), (100, 100, 150, 150))
assert tool.extents == (100, 150, 100, 150)
assert tool.edge_centers == (
(100, 125.0, 150, 125.0), (125.0, 100, 125.0, 150))
assert tool.extents == (100, 150, 100, 150)

# grab a corner and move it
do_event(tool, 'press', xdata=100, ydata=100)
do_event(tool, 'onmove', xdata=120, ydata=120)
do_event(tool, 'release', xdata=120, ydata=120)
assert tool.extents == (120, 150, 120, 150)

# grab the center and move it
do_event(tool, 'press', xdata=132, ydata=132)
do_event(tool, 'onmove', xdata=120, ydata=120)
do_event(tool, 'release', xdata=120, ydata=120)
assert tool.extents == (108, 138, 108, 138)

# create a new rectangle
do_event(tool, 'press', xdata=10, ydata=10)
do_event(tool, 'onmove', xdata=100, ydata=100)
do_event(tool, 'release', xdata=100, ydata=100)
assert tool.extents == (10, 100, 10, 100)


@cleanup
def check_span(*args, **kwargs):
fig, ax = plt.subplots(1, 1)
ax.plot([0, 200], [0, 200])
ax.figure.canvas.draw()
ax = get_ax()

def onselect(vmin, vmax):
ax._got_onselect = True
Expand All @@ -119,14 +221,9 @@ def onmove(vmin, vmax):
kwargs['onmove_callback'] = onmove

tool = widgets.SpanSelector(ax, onselect, *args, **kwargs)
event = get_event(ax, xdata=100, ydata=100, button=1)
tool.press(event)

event = get_event(ax, xdata=125, ydata=125, button=1)
tool.onmove(event)

event = get_event(ax, xdata=150, ydata=150, button=1)
tool.release(event)
do_event(tool, 'press', xdata=100, ydata=100, button=1)
do_event(tool, 'onmove', xdata=125, ydata=125, button=1)
do_event(tool, 'release', xdata=150, ydata=150, button=1)

assert ax._got_onselect

Expand All @@ -142,24 +239,16 @@ def test_span_selector():

@cleanup
def check_lasso_selector(**kwargs):
fig, ax = plt.subplots(1, 1)
ax = plt.gca()
ax.plot([0, 200], [0, 200])
ax.figure.canvas.draw()
ax = get_ax()

def onselect(verts):
ax._got_onselect = True
assert verts == [(100, 100), (125, 125), (150, 150)]

tool = widgets.LassoSelector(ax, onselect, **kwargs)
event = get_event(ax, xdata=100, ydata=100, button=1)
tool.press(event)

event = get_event(ax, xdata=125, ydata=125, button=1)
tool.onmove(event)

event = get_event(ax, xdata=150, ydata=150, button=1)
tool.release(event)
do_event(tool, 'press', xdata=100, ydata=100, button=1)
do_event(tool, 'onmove', xdata=125, ydata=125, button=1)
do_event(tool, 'release', xdata=150, ydata=150, button=1)

assert ax._got_onselect

Expand Down
Loading