fsleyes.profiles

The profiles package contains logic for mouse/keyboard interaction with ViewPanel panels.

This logic is encapsulated in four classes:

  • The Profile class is intended to be subclassed. A Profile instance contains the mouse/keyboard event handlers for a particular type of ViewPanel to allow the user to interact with the view in a particular way. For example, the OrthoViewProfile class allows the user to navigate through the display space in an OrthoPanel canvas, whereas the OrthoEditProfile class contains interaction logic for selecting and editing Image voxels in an OrthoPanel.

  • The CanvasPanelEventManager manages wx GUI events on the SliceCanvas instances contained in CanvasPanel views.

  • The PlotPanelEventManager manages matplotlib GUI events on the matplotlib Canvas instances contained in PlotPanel views.

  • The ProfileManager class is used by ViewPanel instances to create and change the Profile instance currently in use.

The profiles package is also home to the shortcuts module, which defines global FSLeyes keyboard shortcuts.

class fsleyes.profiles.ProfileManager(viewPanel, overlayList, displayCtx, maxprofiles)[source]

Bases: __main__.docbuilder.run.<locals>.MockClass

Manages creation/registration/de-registration of Profile instances for a ViewPanel instance.

A ProfileManager instance is created and used by every ViewPanel instance. The ProfileManager manages a stack of Profile instances - profiles can be activated and deactivated via the activateProfile() and deactivateProfile() methods.

The ProfileManager uses the Notifier interface to notify any interested listeners when the current profile is changed, using the topic name 'profile'. Registered listeners are passed a tuple containing the types (Profile sub-classes) of the de-registered and newly registered profiles.

__init__(viewPanel, overlayList, displayCtx, maxprofiles)[source]

Create a ProfileManager.

Parameters
  • viewPanel – The ViewPanel instance which this ProfileManager is to manage.

  • overlayList – The OverlayList instance containing the overlays that are being displayed.

  • displayCtx – The DisplayContext instance which defines how overlays are being displayed.

  • maxprofiles – Maximum numbe of profiles which can be in the profile stack.

destroy()[source]

This method must be called by the owning ViewPanel when it is about to be destroyed (or when it no longer needs a ProfileManager).

This method destroys all class:Profile instances, and clears some internal object references to avoid memory leaks.

numProfiles()[source]

Returns the number of profiles that currently exist.

getCurrentProfile()[source]

Returns the Profile instance currently in use.

deactivateProfile(notify=True)[source]

Deactivates and destroys the current profile, and re-activates the previous one.

Parameters

notify – If True (the default), a notification is emitted via the Notifier interface.

Returns

A reference to the re-activated profile.

activateProfile(profileCls, notify=True)[source]

Deregisters the current Profile instance, and creates and registers a new instance of type profileCls.

Parameters

notify – If True (the default), a notification is emitted via the Notifier interface.

Returns

A reference to the newly registered profile.

__annotations__ = {}
__module__ = 'fsleyes.profiles'
class fsleyes.profiles.Profile(viewPanel, overlayList, displayCtx, modes=None)[source]

Bases: __main__.docbuilder.run.<locals>.MockClass, fsleyes.actions.ActionProvider

A Profile class implements keyboard/mouse interaction behaviour for a ViewPanel instance.

Subclasses should specify at least one mode of operation, which defines a sort of sub-profile. The current mode can be changed with the mode property.

Subclasses must also override the getEventTargets() method, to return the wx objects that are to be the targets for mouse/keyboard interaction.

The Profile class currently only supports CanvasPanel and PlotPanel views. Profile instances use a CanvasPanelEventManager instance to manage GUI events on CanvasPanel instances, or a:class:.PlotPanelEventManager to manage GUI events on matplotlib Canvas objects.

Receiving events

In order to receive mouse or keyboard events, subclasses simply need to implement methods which handle the events of interest for the relevant mode, and name them appropriately. The name of a method handler must be of the form:

_[modeName]Mode[eventName]

where modeName is an identifier for the profile mode (see the __init__() method), and eventName is one of the following:

  • LeftMouseMove

  • LeftMouseDown

  • LeftMouseDrag

  • LeftMouseUp

  • RightMouseMove

  • RightMouseDown

  • RightMouseDrag

  • RightMouseUp

  • MiddleMouseMove

  • MiddleMouseDown

  • MiddleMouseDrag

  • MiddleMouseUp

  • MouseWheel

  • Char

Profiles for CanvasPanel views may also implement handlers for these events:

  • MouseEnter

  • MouseLeave

And PlotPanel views may implement handlers for these events:

  • LeftMouseArtistPick

  • RightMouseArtistPick

Note

The MouseEnter and MouseLeave events are not supported on PlotPanel views due to bugs in matplotlib.

For example, if a particular profile has defined a mode called nav, and is interested in left clicks, the profile class must provide a method called _navModeLeftMouseDown. Then, whenever the profile is in the nav mode, this method will be called on left mouse clicks.

Handler methods

The parameters that are passed to these methods differs slightly depending on the type of event:

  • All mouse events, with the exception of MouseWheel must have the following signature:

    def _[modeName]Mode[eventName](ev, canvas, mouseLoc, canvasLoc)
    

    where:

    • ev is the wx.Event object

    • canvas is the source canvas,

    • mouseLoc is the (x, y) mouse coordinates,

    • canvasLoc is the coordinates in the display/data coordinate system.

  • The MouseWheel handler must have the following signature:

    def _[modeName]ModeMouseWheel(ev, canvas, wheel, mouseLoc, canvasLoc)
    

    where wheel is a positive or negative number indicating how much the mouse wheel was moved.

  • Char events must have the following signature:

    def _[modeName]ModeChar(ev, canvas, key)
    

    where key is the key code of the key that was pressed.

  • Pick event handlers (only on PlotPanel views) must have the following signature:

    def _[modeName]Mode[eventType](ev, canvas, artist, mouseLoc, canvasLoc)
    

    where artist is the matplotlib artist that was picked.

All handler methods should return True to indicate that the event was handled, or False if the event was not handled. This is particularly important for Char event handlers - we don’t want Profile sub-classes to be eating global keyboard shortcuts. A return value of None is interpreted as True. If a handler returns False, and a fallback handler is defined (see below), then that fallback handler will be called.

Extra handlers

Additional handlers can be registered for any event type via the registerHandler() method. These handlers do not have to be methods of the Profile sub-class, and will be called for every occurrence of the event, regardless of the current mode. These handlers will be called after the standard handler method.

When an extra handler is no longer needed, it must be removed via the deregisterHandler() method.

Pre- and post- methods

A couple of other methods may be defined which, if they are present, will be called on all handled events:

  • _preEvent

  • _postEvent

The _preEvent method will get called just before an event is passed to the handler. Likewise, the _postEvent method will get called just after the handler has been called. If no handlers for a particular event are defined, neither of these methods will be called.

Temporary, alternate and fallback handlers

The tempModes() function may be overridden to define a keyboard modifier which may be used to temporarily redirect mouse/keyboard events to the handlers for a different mode. For example, if while in nav mode, you would like the user to be able to switch to zoom mode with the control key, you can add a temporary mode map in the dictionary returned by tempModes. Additional temporary modes can be added via the addTempMode() method.

The altHandlers() function may be overridden to allow the re-use of event handlers that have been defined for one mode in another mode. For example, if you would like right clicks in zoom mode to behave like left clicks in nav mode, you can return such a mapping from the altHandler function. Additional alternate handlers can be added via the addAltHandler() method.

The fallbackHandlers() function may be overridden to define fallback handlers - if the default handler for a specific mode/event type returns a value of False, the event will be forwarded to the fallback handler instead. Additional fallback handlers can be added via the addFallbackHandler() method.

Actions and attributes

As the Profile class derives from the ActionProvider class, Profile subclasses may define properties and actions for the user to configure the profile behaviour, and/or to perform any relevant actions.

The following instance attributes are present on a Profile instance, intended to be accessed by sub-classes:

viewPanel

The ViewPanel which is using this Profile.

overlayList

A OverlayList instance.

displayCtx

A DisplayContext instance.

name

A unique name for this Profile instance.

static supportedView()[source]

Returns the ViewPanel type that is supported by this Profile. Must be implemented by sub-classes.

static tempModes()[source]

May be overridden by sub-classes. Should return a dictionary defining temporary modes which, when in a given mode, can be accessed with a keyboard modifer (e.g. Control, Shift, etc). For example, a temporary mode map of:

('view', wx.WXK_SHIFT) : 'zoom'

states that when the Profile is in 'view' mode, and the shift key is held down, the Profile should temporarily switch to 'zoom' mode.

For multi-key combinations, the modifier key IDs must be provided as a tuple, in alphabetical order. For example, to specify shift+ctrl, the tuple must be (wx.WXK_CTRL, wx.WXK_SHIFT)

Important: Any temporary modes which use CTRL, ALT, or CTRL+ALT must not handle character events, as these modifiers are reserved for global shortcuts.

Temporary modes honour the Profile class hierarchy, so if you sub-class an existing Profile class, your class will inherit all of the temporary modes defined on the base class.

static altHandlers()[source]

May be overridden by sub-classes. Should return a dictionary defining alternate handlers for a given mode and event type. Entries in this dictionary allow a Profile sub-class to define a handler for a single mode and event type, but to re-use that handler for other modes and event types. For example, the following alternate handler mapping:

('zoom', 'MiddleMouseDrag') : ('pan',  'LeftMouseDrag')

states that when the Profile is in 'zoom' mode, and a MiddleMouseDrag event occurs, the LeftMouseDrag handler for the 'pan' mode should be called.

Alternate handlers honour the Profile class hierarchy, so if you sub-class an existing Profile class, your class will inherit all of the alternate handlers defined on the base class.

Note

Event bindings defined by altHandlers take precdence over the event bindings defined in the Profile sub-class. So you can use the altHandlers to override the default behaviour of a Profile.

static fallbackHandlers()[source]

May be overridden by sub-classes. Should return a dictionary defining handlers for a given mode and event type which will be called if the handler for that mode/event type returns a value of False, indicating that it has not been handled. For example, the following fallback handler mapping:

(('pick', 'LeftMouseDown'), ('nav', 'LeftMouseDown')),

states that when the profile is in 'pick' mode, and the LeftMouseDown handler for 'pick' mode returns False, the LeftMouseDown handler for 'nav' mode will be called.

Fallback handlers honour the Profile class hierarchy, so if you sub-class an existing Profile class, your class will inherit all of the fallback handlers defined on the base class.

__init__(viewPanel, overlayList, displayCtx, modes=None)[source]

Create a Profile instance.

Parameters
  • viewPanel – The ViewPanel instance for which this Profile instance defines mouse/keyboard interaction behaviour.

  • overlayList – The OverlayList instance which contains the list of overlays being displayed.

  • displayCtx – The DisplayContext instance which defines how the overlays are to be displayed.

  • modes – A sequence of strings, containing the mode identifiers for this profile. These are added as options on the mode property.

mode = <MagicMock name='mock.Choice()' id='140735756677712'>

The current profile mode - by default this is empty, but subclasses may specify the choice options in the __init__ method.

__del__()[source]

Prints a log message.

destroy()[source]

This method must be called when this Profile is no longer needed - it is typically called by a ProfileManager.

Clears references to the display context, view panel, and overlay list, and calls ActionProvider.destroy().

property name

Returns the name of this Profile.

property viewPanel

Returns the ViewPanel associated with this Profile.

getEventTargets()[source]

Must be overridden by subclasses, to return a sequence of wx objects that are the targets of mouse/keyboard interaction.

Note

It is currently assumed that all of the objects in the sequence derive from the SliceCanvas class.

getMouseDownLocation()[source]

If the mouse is currently down, returns a 2-tuple containing the x/y mouse coordinates, and the corresponding 3D display space coordinates, of the mouse down event. Otherwise, returns (None, None).

getLastMouseLocation()[source]

Returns a 2-tuple containing the most recent x/y mouse coordinates, and the corresponding 3D display space coordinates.

getLastMouseUpLocation()[source]

Returns a 2-tuple containing the most recent x/y mouse up event coordinates, and the corresponding 3D display space coordinates.

getLastMouseUpHandler()[source]

Returns a tuple of two strings specifying the (mode, eventType) of the most recent mouse up event that was handled. If no events have been handled, returns (None, None).

getLastHandler()[source]

Returns a tuple of two strings specifying the (mode, eventType) of the most recent event that was handled. If no events have been handled, returns (None, None).

getLastCanvas()[source]

Returns a reference to the canvas which most recently generated a mouse down or up event.

getMplEvent()[source]

If this Profile object is associated with a PlotPanel, this method will return the last matplotlib event that was generated. Otherwise, this method returns None.

This method can be called from within an event handler to retrieve the current matplotlib event. See the PlotPanelEventManager.getMplEvent() method.

addTempMode(mode, modifier, tempMode)[source]

Add a temporary mode to this Profile, in addition to those defined by the tempModes() function.

Parameters
  • mode – The mode to change from.

  • modifier – A keyboard modifier which will temporarily change the mode from mode to tempMode.

  • tempMode – The temporary mode which the modifier key will change into.

addAltHandler(mode, event, altMode, altEvent)[source]

Add an alternate handler to this Profile, in addition to those already defined by the altHandlers() function.

Parameters
  • mode – The source mode.

  • event – Name of the event to handle (e.g. LeftMouseDown).

  • altMode – The mode for which the handler is defined.

  • altEvent – The event name for which the handler is defined.

addFallbackHandler(mode, event, fbMode, fbEvent)[source]

Add a fallback handler to this Profile, in addition to those already defined by the fallbackHandlers() function.

Parameters
  • mode – The source mode.

  • event – Name of the event to handle (e.g. LeftMouseDown).

  • fbMode – The mode for which the handler is defined.

  • fbEvent – The event name for which the handler is defined.

register()[source]

This method must be called to register this Profile instance as the target for mouse/keyboard events. This method is called by the ProfileManager.

Subclasses may override this method to performa any initialisation, but must make sure to call this implementation.

deregister()[source]

This method de-registers this Profile instance from receiving mouse/keybouard events. This method is called by the ProfileManager.

Subclasses may override this method to performa any initialisation, but must make sure to call this implementation.

registerHandler(event, name, handler)[source]

Add an extra handler for the specified event.

When the event occurs, The handler function will be called after the default handler, provided by the Profie sub-class, is called.

Parameters
  • event – The event type (e.g. LeftMouseDown).

  • name – A unique name for the handler. A KeyError will be raised if a handler with name is already registered.

  • handler – Function to call when the event occurs. See the class documentation for details on the required signature.

deregisterHandler(event, name)[source]

Remove an extra handler from the specified event, that was previously added via registerHandler()

Parameters
  • event – The event type (e.g. LeftMouseDown).

  • name – A unique name for the handler. A KeyError will be raised if a handler with name is already registered.

handleEvent(ev)[source]

Called by the event manager when any event occurs on any of the ViewPanel targets. Delegates the event to one of the handler functions.

Parameters

ev – The wx.Event that occurred.

handlePickEvent(ev)[source]

Called by the PlotPanelEventManager when a matplotlib pick_event occurs.

__getTempMode(ev)

Checks the temporary mode map to see if a temporary mode should be applied. Returns the mode identifier, or None if no temporary mode is applicable.

__getMouseLocation(ev)

Returns two tuples; the first contains the x/y coordinates of the given wx.MouseEvent, and the second contains the corresponding x/y/z display space coordinates (for CanvasPanel views), or x/y data coordinates (for PlotPanel views).

See the CanvasPanelEventManager.getMouseLocation() and PlotPanelEventManager.getMouseLocation() methods.

__getMouseButton(ev)

Returns a string describing the mouse button associated with the given wx.MouseEvent.

__getMode(ev)

Returns the current profile mode - either the value of mode, or a temporary mode if one is active.

__getHandler(ev, evType, mode=None, origEvType=None, direct=False)

Returns a function which will handle the given wx.MouseEvent or wx.KeyEvent (the ev argument), or None if no handlers are found.

If an alternate handler for the mode/event has been specified, it is returned.

Parameters
  • ev – The event object

  • evType – The event type (e.g. 'LeftMouseDown')

  • mode – Override the default mode with this one. If not provided, the handler for the current mode (or temporary mode, if one is active) will be used.

  • origEvType – If the evType is not the actual event that occurred (e.g. this method has been called to look up an alternate or fallback handler), the original event type must be passed in here.

  • direct – If False (the default), the returned function will call the standard event handler (a method of the Profile sub-class), its fallback handler if it returns False and a fallback has been specfiied, any extra handlers that have been registered for the event type, and will also call the pre- and post- event methods. Otherwise, the returned function will just be the sub-class handler method for the specified for evType/ ``mode.

__onMouseWheel(ev)

Called when the mouse wheel is moved.

Delegates to a mode specific handler if one is present.

__onMouseEnter(ev)

Called when the mouse enters a canvas target.

Delegates to a mode specific handler if one is present.

__onMouseLeave(ev)

Called when the mouse leaves a canvas target.

Delegates to a mode specific handler if one is present.

__onMouseDown(ev)

Called when any mouse button is pushed.

Delegates to a mode specific handler if one is present.

__onMouseUp(ev)

Called when any mouse button is released.

Delegates to a mode specific handler if one is present.

__onMouseMove(ev)

Called on mouse motion. If a mouse button is down, delegates to __onMouseDrag().

Otherwise, delegates to a mode specific handler if one is present.

__onMouseDrag(ev)

Called on mouse drags.

Delegates to a mode specific handler if one is present.

__onChar(ev)

Called on keyboard key presses.

Delegates to a mode specific handler if one is present.

__onPick(ev)

Called by the handlePickEvent(). Delegates the event to a suitable handler, if one exists.

__annotations__ = {}
__module__ = 'fsleyes.profiles'
class fsleyes.profiles.CanvasPanelEventManager(profile)[source]

Bases: object

This class manages wx mouse/keyboard events originating from SliceCanvas instances contained within CanvasPanel views.

__init__(profile)[source]

Create a CanvasPanelEventManager.

Parameters

profile – The Profile instance that owns this event manager.

register()[source]

This method must be called to register event listeners on mouse/ keyboard events. This method is called by meth :Profile.register.

deregister()[source]

This method de-registers mouse/keybouard event listeners. This method is called by the Profile.deregister() method.

getMouseLocation(ev)[source]

Returns two tuples; the first contains the x/y coordinates of the given wx.MouseEvent, and the second contains the corresponding x/y/z display space coordinates.

__onEvent(ev)

Event handler. Passes the event to Profile.handleEvent.

__dict__ = mappingproxy({'__module__': 'fsleyes.profiles', '__doc__': 'This class manages ``wx`` mouse/keyboard events originating from\n    :class:`.SliceCanvas` instances contained within :class:`.CanvasPanel`\n    views.\n    ', '__init__': <function CanvasPanelEventManager.__init__>, 'register': <function CanvasPanelEventManager.register>, 'deregister': <function CanvasPanelEventManager.deregister>, 'getMouseLocation': <function CanvasPanelEventManager.getMouseLocation>, '_CanvasPanelEventManager__onEvent': <function CanvasPanelEventManager.__onEvent>, '__dict__': <attribute '__dict__' of 'CanvasPanelEventManager' objects>, '__weakref__': <attribute '__weakref__' of 'CanvasPanelEventManager' objects>, '__annotations__': {}})
__module__ = 'fsleyes.profiles'
__weakref__

list of weak references to the object (if defined)

class fsleyes.profiles.PlotPanelEventManager(profile)[source]

Bases: object

This class manages events originating from matplotlib Canvas objects contained within PlotPanel views.

Note

This class has no support for figure_enter_event, figure_leave_event, axis_enter_event, or axis_leave_event events. There appears to be some bugs lurking in the matplotlib/backend_bases.py file (something to do with the LocationEvent.lastevent property) which cause FSLeyes to seg-fault on figure_enter_event events.

__init__(profile)[source]

Create a PlotPanelEventManager.

Parameters

profile – The Profile instance that owns this event manager.

register()[source]

Register listeners on all relevant matplotlib events. This method is called by Profile.register().

deregister()[source]

De-register listeners on all relevant matplotlib events. This method is called by Profile.deregister().

getMouseLocation(ev=None)[source]

Returns two tuples; the first contains the x/y coordinates of the most recent matplotlib event, and the second contains the corresponding x/y data coordinates.

If an event has not yet occurred, or if the mouse position is not on any event target, this method returns (None, None).

Parameters

ev – Ignored.

__dict__ = mappingproxy({'__module__': 'fsleyes.profiles', '__doc__': 'This class manages events originating from ``matplotlib`` ``Canvas``\n    objects contained within :class:`.PlotPanel` views.\n\n\n    .. note:: This class has no support for ``figure_enter_event``,\n              ``figure_leave_event``, ``axis_enter_event``, or\n              ``axis_leave_event`` events. There appears to be some bugs\n              lurking in the ``matplotlib/backend_bases.py``  file (something\n              to do with the ``LocationEvent.lastevent`` property) which\n              cause FSLeyes to seg-fault on ``figure_enter_event`` events.\n    ', '__init__': <function PlotPanelEventManager.__init__>, 'register': <function PlotPanelEventManager.register>, 'deregister': <function PlotPanelEventManager.deregister>, 'getMouseLocation': <function PlotPanelEventManager.getMouseLocation>, 'getPickedArtist': <function PlotPanelEventManager.getPickedArtist>, 'getMplEvent': <function PlotPanelEventManager.getMplEvent>, '_PlotPanelEventManager__onEvent': <function PlotPanelEventManager.__onEvent>, '__dict__': <attribute '__dict__' of 'PlotPanelEventManager' objects>, '__weakref__': <attribute '__weakref__' of 'PlotPanelEventManager' objects>, '__annotations__': {}})
__module__ = 'fsleyes.profiles'
__weakref__

list of weak references to the object (if defined)

getPickedArtist()[source]

Returns the matplotlib.Artist that was most recently picked (clicked on) by the user.

getMplEvent()[source]

Returns the most recent matplotlib event that occurred, or None if no events have occurred yet.

__onEvent(ev)

Handler for matplotlib events. Passes the corresponding wx event to the Profile.handleEvent() method.