Changeset 5251ec6 in sasview for src/sas/sasgui/guiframe/local_perspectives/plotting/binder.py
- Timestamp:
- Oct 11, 2018 12:20:56 PM (6 years ago)
- Branches:
- master, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1249
- Children:
- 98b9f32
- Parents:
- 67ed543
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sasgui/guiframe/local_perspectives/plotting/binder.py
r20fa5fe r5251ec6 2 2 Extension to MPL to support the binding of artists to key/mouse events. 3 3 """ 4 from __future__ import print_function 5 6 import sys 4 7 import logging 5 import sys6 8 7 9 logger = logging.getLogger(__name__) … … 16 18 artist = None 17 19 prop = {} 20 18 21 def __init__(self, artist=None, prop={}): 19 22 self.artist, self.prop = artist, self.prop … … 25 28 return self.artist is not other.artist 26 29 27 def __ nonzero__(self):30 def __bool__(self): 28 31 return self.artist is not None 32 33 __nonzero__ = __bool__ 34 29 35 30 36 class BindArtist(object): 31 37 """ 32 Track keyboard modifiers for events. 33 TODO: Move keyboard modifier support into the backend. We cannot 34 TODO: properly support it from outside the windowing system since there 35 TODO: is no way to recognized whether shift is held down when the mouse 36 TODO: first clicks on the the application window. 38 Track keyboard modifiers for events. 37 39 """ 40 # TODO: Move keyboard modifier support into the backend. We cannot 41 # TODO: properly support it from outside the windowing system since there 42 # TODO: is no way to recognized whether shift is held down when the mouse 43 # TODO: first clicks on the the application window. 38 44 control, shift, alt, meta = False, False, False, False 39 45 … … 46 52 'scroll', 'key', 'keyup'] 47 53 # TODO: Need our own event structure 54 48 55 def __init__(self, figure): 49 56 canvas = figure.canvas 57 50 58 # Link to keyboard/mouse 51 59 try: … … 59 67 ] 60 68 except: 61 # print "bypassing scroll_event: wrong matplotlib version"69 logger.warn("bypassing scroll_event: wrong matplotlib version") 62 70 self._connections = [ 63 71 canvas.mpl_connect('motion_notify_event', self._onMotion), … … 67 75 canvas.mpl_connect('key_release_event', self._onKeyRelease), 68 76 ] 77 69 78 # Turn off picker if it hasn't already been done 70 79 try: 71 80 canvas.mpl_disconnect(canvas.button_pick_id) 72 81 canvas.mpl_disconnect(canvas.scroll_pick_id) 73 except: 74 logger.error(sys.exc_value) 82 except Exception as exc: 83 logger.error(exc) 84 85 self._current = None 86 self._actions = {} 75 87 self.canvas = canvas 76 88 self.figure = figure … … 83 95 84 96 Use clearall() to reset all connections. 85 86 97 """ 87 98 for h in artists: … … 108 119 for action in self.events: 109 120 self._actions[action] = {} 121 110 122 # Need activity state 111 123 self._artists = [] … … 121 133 for cid in self._connections: 122 134 self.canvas.mpl_disconnect(cid) 123 except :124 pass135 except Exception as exc: 136 logger.error("Error disconnection canvas: %s" % exc) 125 137 self._connections = [] 126 138 … … 169 181 sure it applies. E.g., the callback for 'press' might be: 170 182 if event.button == 1 and event.shift: process Shift-click 171 172 :TODO: Only receive events with the correct modifiers (e.g., S-click, 173 :TODO: or *-click for any modifiers). 174 :TODO: Only receive button events for the correct button (e.g., click1 175 :TODO: release3, or dclick* for any button) 176 :TODO: Support virtual artist, so that and artist can be flagged as 177 :TODO: having a tag list and receive the correct events 178 :TODO: Support virtual events for binding to button-3 vs shift button-1 179 :TODO: without changing callback code 180 :TODO: Attach multiple callbacks to the same event? 181 :TODO: Clean up interaction with toolbar modes 182 :TODO: push/pushclear/pop context so that binding changes 183 for the duration 184 :TODO: e.g., to support ? context sensitive help 185 186 """ 183 """ 184 #TODO: Only receive events with the correct modifiers (e.g., S-click, 185 #TODO: or *-click for any modifiers). 186 #TODO: Only receive button events for the correct button (e.g., click1 187 #TODO: release3, or dclick* for any button) 188 #TODO: Support virtual artist, so that and artist can be flagged as 189 #TODO: having a tag list and receive the correct events 190 #TODO: Support virtual events for binding to button-3 vs shift button-1 191 #TODO: without changing callback code 192 #TODO: Attach multiple callbacks to the same event? 193 #TODO: Clean up interaction with toolbar modes 194 #TODO: push/pushclear/pop context so that binding changes for the duration 195 #TODO: e.g., to support ? context sensitive help 196 187 197 # Check that the trigger is valid 188 198 if trigger not in self._actions: 189 raise ValueError, "%s invalid --- valid triggers are %s" \ 190 % (trigger, ", ".join(self.events)) 199 raise ValueError("%s invalid --- valid triggers are %s" 200 % (trigger, ", ".join(self.events))) 201 191 202 # Register the trigger callback 192 203 self._actions[trigger][artist] = action 193 # print "==> added",artist,[artist],"to",trigger,":", 194 # self._actions[trigger].keys() 204 195 205 # Maintain a list of all artists 196 206 if artist not in self._artists: … … 203 213 """ 204 214 if action not in self.events: 205 raise ValueError, "Trigger expects " + ", ".join(self.events) 215 raise ValueError("Trigger expects " + ", ".join(self.events)) 216 206 217 # Tag the event with modifiers 207 218 for mod in ('alt', 'control', 'shift', 'meta'): … … 210 221 setattr(ev, 'action', action) 211 222 setattr(ev, 'prop', {}) 223 212 224 # Fallback scheme. If the event does not return false, pass to parent. 213 225 processed = False … … 233 245 """ 234 246 # TODO: sort by zorder of axes then by zorder within axes 235 self._artists.sort(cmp=lambda x, y: cmp(y.zorder, x.zorder)) 236 # print "search"," ".join([str(h) for h in self._artists]) 247 self._artists.sort(key=lambda x: x.zorder, reverse=True) 237 248 found = Selection() 238 # print "searching in",self._artists239 249 for artist in self._artists: 240 250 # TODO: should contains() return false if invisible? … … 250 260 found.artist, found.prop = artist, prop 251 261 break 252 # print "found",found.artist253 262 254 263 # TODO: how to check if prop is equal? … … 257 266 self.trigger(found, 'enter', event) 258 267 self._current = found 268 259 269 return found 260 270 … … 274 284 275 285 transform = self._hasclick.artist.get_transform() 276 # 286 #x,y = event.xdata,event.ydata 277 287 x, y = event.x, event.y 278 288 try: 279 289 x, y = transform.inverted().transform_point((x, y)) 280 281 except: 290 except: # CRUFT: matplotlib-0.91 support 282 291 x, y = transform.inverse_xy_tup((x, y)) 292 283 293 event.xdata, event.ydata = x, y 284 294 self.trigger(self._hasclick, 'drag', event) 285 295 else: 286 296 found = self._find_current(event) 287 # print "found",found.artist288 297 self.trigger(found, 'motion', event) 289 298 … … 296 305 # Check for double-click 297 306 event_time = time.time() 298 # print event_time,self._last_time,self.dclick_threshhold299 # print (event_time > self._last_time + self.dclick_threshhold)300 # print event.button,self._last_button301 307 if (event.button != self._last_button) or \ 302 308 (event_time > self._last_time + self.dclick_threshhold): … … 381 387 setattr(self, event.key, False) 382 388 return 389 383 390 if self._haskey: 384 391 self.trigger(self._haskey, 'keyup', event) … … 391 398 found = self._find_current(event) 392 399 self.trigger(found, 'scroll', event) 393
Note: See TracChangeset
for help on using the changeset viewer.