Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
blink1073 Dec 19, 2014
f8eefe6
Upgrade RectangleSelector with ToolHandles and add Ellipse
blink1073 Dec 19, 2014
7f044cf
Add toolhandles class
blink1073 Dec 19, 2014
f450df6
Add test using tool handles
blink1073 Dec 19, 2014
79294e0
Add a helper function to get axes
blink1073 Dec 19, 2014
fd264a2
Do not allow extents outside the image and add a path property
blink1073 Dec 19, 2014
438715f
Finish rectangle handle tests and add ellipse test with key modifiers
blink1073 Dec 19, 2014
e560713
Rename path property to geometry and return consistent results.
blink1073 Dec 20, 2014
5025ba2
Add geometry tests.
blink1073 Dec 20, 2014
b118294
Remove extra line.
blink1073 Dec 20, 2014
b15cf12
Refactor the event handling methods
blink1073 Dec 20, 2014
e96fe81
Update rectangle logic to include '_moving'
blink1073 Dec 20, 2014
240cfa2
Clean up event handling and add a state attribute
blink1073 Dec 20, 2014
7915db8
Add state handling to onmove
blink1073 Dec 20, 2014
f7a9222
More "state" refactoring
blink1073 Dec 20, 2014
7c04e25
Add key release and continue refactoring state handling
blink1073 Dec 20, 2014
cf491db
Recreate the _get_data method and more event refactoring
blink1073 Dec 20, 2014
7ece2fa
Refactor the event creator to call the private methods
blink1073 Dec 20, 2014
59ccd81
Preserve existing api for event handler functions
blink1073 Dec 21, 2014
a033e8e
Preserve event return values
blink1073 Dec 24, 2014
2923f97
Add cleanup to tests and fix default rect prop
blink1073 Dec 24, 2014
6549538
Pep8 fixes
blink1073 Dec 24, 2014
491276e
Fix bug in SpanSelector when blit=True
blink1073 Jan 17, 2015
744308c
Clear events after valid release
blink1073 Jan 18, 2015
a7518b3
Do not attempt to draw artists if ax is invisible
blink1073 Jan 18, 2015
77dc52b
Ignore events when axes are invisible
blink1073 Jan 18, 2015
48ebf30
Fix span selector onmove when we exit axes
blink1073 Feb 21, 2015
3ffd7c0
Restore previous behaviour and allow escape to clear the current sele…
blink1073 Aug 19, 2015
e802991
Fix failing tests
blink1073 Aug 19, 2015
af6e1b4
Fix handling of center handle
blink1073 Aug 20, 2015
f5666a4
Remove debug print
blink1073 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
blink1073 Aug 22, 2015
840a671
Revert to old draw types and add docs about key modifiers
blink1073 Aug 23, 2015
2a11f5f
Revert change to the example
blink1073 Aug 23, 2015
8da7985
Remove extra draw_idle trigger
blink1073 Aug 23, 2015
cfe4df1
Update the docstring
blink1073 Aug 23, 2015
bc225b6
Remove extraneous doc
blink1073 Aug 23, 2015
59145af
Fix failing test
blink1073 Aug 23, 2015
d491ac9
Update docstring, use self.useblit, use space for move
blink1073 Aug 25, 2015
8e8e473
Use new state_modifier_keys dictionary
blink1073 Aug 26, 2015
2ed0419
Clear the active handle when invisible
blink1073 Aug 26, 2015
d5b5d86
Collapse the shape on improper draw to prevent showing the previous s…
blink1073 Aug 26, 2015
87ab199
Fix test using 'alt' key
blink1073 Aug 26, 2015
9eaae32
Clean up and add more docs
blink1073 Sep 1, 2015
819804f
Make on_key_release use the state_modifier_keys
blink1073 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
Prev Previous commit
Next Next commit
Preserve existing api for event handler functions
  • Loading branch information
blink1073 committed Aug 22, 2015
commit 59ccd8170b0fc23fb94dfc47621c15109a2cfc9b
2 changes: 1 addition & 1 deletion lib/matplotlib/tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def do_event(tool, etype, button=1, xdata=0, ydata=0, key=None, step=1):
event.guiEvent = None
event.name = 'Custom'

func = getattr(tool, '_%s' % etype)
func = getattr(tool, etype)
func(event)


Expand Down
68 changes: 34 additions & 34 deletions lib/matplotlib/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1140,11 +1140,11 @@ def __init__(self, ax, onselect, useblit=False, button=None):

self.visible = True
self.onselect = onselect
self.useblit = useblit and self.canvas.supports_blit
self.connect_default_events()

self.background = None
self.artists = []
self.useblit = useblit and self.canvas.supports_blit

if isinstance(button, int):
self.validButtons = [button]
Expand Down Expand Up @@ -1172,13 +1172,13 @@ def update_background(self, event):

def connect_default_events(self):
"""Connect the major canvas events to methods."""
self.connect_event('motion_notify_event', self._onmove)
self.connect_event('button_press_event', self._press)
self.connect_event('button_release_event', self._release)
self.connect_event('motion_notify_event', self.onmove)
self.connect_event('button_press_event', self.press)
self.connect_event('button_release_event', self.release)
self.connect_event('draw_event', self.update_background)
self.connect_event('key_press_event', self._on_key_press)
self.connect_event('key_release_event', self._on_key_release)
self.connect_event('scroll_event', self._on_scroll)
self.connect_event('key_press_event', self.on_key_press)
self.connect_event('key_release_event', self.on_key_release)
self.connect_event('scroll_event', self.on_scroll)

def ignore(self, event):
"""return *True* if *event* should be ignored"""
Expand Down Expand Up @@ -1258,7 +1258,7 @@ def _clean_event(self, event):
self._prev_event = event
return event

def _press(self, event):
def press(self, event):
"""Button press handler and validator"""
if not self.ignore(event):
event = self._clean_event(event)
Expand All @@ -1267,68 +1267,68 @@ def _press(self, event):
key = event.key or ''
if 'alt' in key or key == ' ':
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.

Any reason for allowing two keys here? I'd just pick the space character and go with it.

Tangentially, I am not a fan of these hard-coded special keys. While they are fine as defaults, an application developer may already have these keys mapped to something and would want something different. So, it might be a good idea to have them able to be defined in the constructor.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I had originally used Alt, since it is used by Gimp, but it did not work on Windows IIRC. I'll add these to the constructor.

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.

In my Gnome desktop, Alt and holding down the mouse button will result in moving the entire figure window.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, we'll default to space.

self.state.add('move')
self.press(event)
self._press(event)

def press(self, event):
def _press(self, event):
"""Button press handler"""
pass

def _release(self, event):
def release(self, event):
"""Button release event handler and validator"""
if not self.ignore(event) and self.eventpress:
event = self._clean_event(event)
self.eventrelease = event
self.release(event)
self._release(event)
self.state.discard('move')

def release(self, event):
def _release(self, event):
"""Button release event handler"""
pass

def _onmove(self, event):
def onmove(self, event):
"""Cursor move event handler and validator"""
if not self.ignore(event) and self.eventpress:
event = self._clean_event(event)
self.onmove(event)
self._onmove(event)

def onmove(self, event):
def _onmove(self, event):
"""Cursor move event handler"""
pass

def _on_scroll(self, event):
def on_scroll(self, event):
"""Mouse scroll event handler and validator"""
if not self.ignore(event):
self.on_scroll(event)
self._on_scroll(event)

def on_scroll(self, event):
def _on_scroll(self, event):
"""Mouse scroll event handler"""
pass

def _on_key_press(self, event):
def on_key_press(self, event):
"""Key press event handler and validator"""
if self.active:
key = event.key or ''
if 'shift' in key:
self.state.add('square')
if 'ctrl' in key or 'control' in key:
self.state.add('center')
self.on_key_press(event)
self._on_key_press(event)
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.

I am a bit confused here. Shouldn't the 'clear' action be in _on_key_press? Shouldn't the 'clear' state get implemented through the state handling mechanism you set up here?

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.

At the very least, an explanation in comments should be given to explain what should go into on_key_press and _on_key_press and other pairs of methods like it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I added some docs here. Essentially the _ methods are for Widget-specific things, and the top level is meant for all Selection widgets. Clear is not so much as state as an action - clear the current selection.


def on_key_press(self, event):
def _on_key_press(self, event):
"""Key press event handler"""
pass

def _on_key_release(self, event):
def on_key_release(self, event):
"""Key release event handler and validator"""
if self.active:
key = event.key or ''
if 'shift' in key:
self.state.discard('square')
if 'ctrl' in key or 'control' in key:
self.state.discard('center')
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 if-statements should be using the state_modifiier_keys dictionary.

self.on_key_release(event)
self._on_key_release(event)

def on_key_release(self, event):
def _on_key_release(self, event):
"""Key release event handler"""
pass

Expand Down Expand Up @@ -1458,7 +1458,7 @@ def ignore(self, event):
"""return *True* if *event* should be ignored"""
return _SelectorWidget.ignore(self, event) or not self.visible

def press(self, event):
def _press(self, event):
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.

What's the reason for this API change? While I doubt anyone is directly using these, could it mess up people would might be subclassing this Widget?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

They are welcome to override press and call super(). The intent was to factor out the basic behavior (ignore, etc.) have have the widgets provide a specific implementation.

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.

Ah, I missed that this class already has those methods inherited already. Yeah, this is probably the better design.

"""on button press event"""
self.rect.set_visible(self.visible)
if self.span_stays:
Expand All @@ -1471,7 +1471,7 @@ def press(self, event):
self.pressv = ydata
return False

def release(self, event):
def _release(self, event):
"""on button release event"""
if self.pressv is None:
return
Expand Down Expand Up @@ -1503,7 +1503,7 @@ def release(self, event):
self.pressv = None
return False

def onmove(self, event):
def _onmove(self, event):
"""on motion notify event"""
if self.pressv is None:
return
Expand Down Expand Up @@ -1752,7 +1752,7 @@ def __init__(self, ax, onselect, drawtype='patch',
self._corner_handles.artist,
self._edge_handles.artist]

def press(self, event):
def _press(self, event):
"""on button press event"""
# make the drawed box/line visible get the click-coordinates,
# button, ...
Expand All @@ -1765,7 +1765,7 @@ def press(self, event):

self.set_visible(self.visible)

def release(self, event):
def _release(self, event):
"""on button release event"""
if self.spancoords == 'data':
xmin, ymin = self.eventpress.xdata, self.eventpress.ydata
Expand Down Expand Up @@ -1812,7 +1812,7 @@ def release(self, event):

return False

def onmove(self, event):
def _onmove(self, event):
"""on motion notify event if box/line is wanted"""
# resize an existing shape
if self.active_handle and not self.active_handle == 'C':
Expand Down Expand Up @@ -2084,22 +2084,22 @@ def __init__(self, ax, onselect=None, useblit=True, lineprops=None,
def onpress(self, event):
self.press(event)

def press(self, event):
def _press(self, event):
self.verts = [self._get_data(event)]
self.line.set_visible(True)

def onrelease(self, event):
self.release(event)

def release(self, event):
def _release(self, event):
if self.verts is not None:
self.verts.append(self._get_data(event))
self.onselect(self.verts)
self.line.set_data([[], []])
self.line.set_visible(False)
self.verts = None

def onmove(self, event):
def _onmove(self, event):
if self.verts is None:
return
self.verts.append(self._get_data(event))
Expand Down