fsleyes.actions
This package provides a collection of actions, classes - the
Action
class and the ActionProvider
class, and the action()
and toggleAction()
decorators.
The Action
class represents some sort of action which may be
performed, enabled and disabled, and may be bound to a GUI menu item or
button. The ActionProvider
class represents some entity which can
perform one or more actions. As the FSLeyesPanel
class derives from
ActionProvider
pretty much everything in FSLeyes is an
ActionProvider
.
Many of the modules in this package also contain standalone functions for doing
various things, such as the screenshot.screenshot()
function, and the
loadoverlay.loadImage()
function.
The action()
and toggleAction()
functions are intended to be used
as decorators upon the methods of a class which derives from
ActionProvider
. For example:
>>> import fsleyes.actions as actions
>>> class Thing(actions.ActionProvider):
@actions.action
def doFirstThing(self):
print 'First thing done'
@actions.action
def doSecondThing(self):
print 'Second thing done'
@actions.toggleAction
def toggleOtherThing(self):
print 'Other thing toggled'
In this example, when an instance of Thing
is defined, each of the methods
that are defined as actions will be available through the methods defined in
the ActionProvder
. For example:
>>> t = Thing()
>>> print t.getActions()
[('doFirstThing', Action(doFirstThing)),
('doSecondThing', Action(doSecondThing)),
('toggleOtherThing', ToggleAction(toggleOtherThing))]
You can enable/disable actions through the ActionProvider.enableAction()
and ActionProvider.disableAction()
methods:
>>> t.disableAction('doFirstThing')
>>> t.doFirstThing()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../fsleyes/actions/__init__.py", line 139, in __call__
self.__name))
fsleyes.actions.ActionDisabledError: Action doFirstThing is disabled
It is useful to know that each method on the t
instance has actually been
replaced with an Action
instance, which encapsulates the method.
Using this knowledge, you can access the Action
instances directly:
>>> t.doFirstThing.enabled = True
>>> t.doFirstThing()
First thing done
The Action.bindToWidget()
method allows a widget to be bound to an
Action
. For example:
# We're assuming here that a wx.App, and
# a parent window, has been created
>>> button = wx.Button(parent, label='Do the first thing!')
>>> t.doSecondThing.bindToWidget(parent, button, wx.EVT_BUTTON)
All bound widgets of an Action
can be accessed through the
Action.getBoundWidgets()
method, and can be unbound via the
Action.unbindAllWidgets()
method.
This module also provides two classes which allow a widget to be automatically
created for, and bound to an Action
or ToggleAction
(through the
props.build
package):
Extends the
props.Button
class to encapsulate anAction
instance.Extends the
props.Toggle
class to encapsulate aToggleAction
instance.
- fsleyes.actions.action(*args, **kwargs)[source]
A decorator which identifies a class method as an action.
- fsleyes.actions.toggleAction(*args, **kwargs)[source]
A decorator which identifies a class method as a toggle action.
- fsleyes.actions.toggleControlAction(*args, **kwargs)[source]
A decorator which identifies a class method as a
ToggleControlPanelAction
.
- class fsleyes.actions.ActionProvider(overlayList, displayCtx)[source]
Bases:
object
The
ActionProvider
class is intended to be used as a base class for classes which contain actions. Theaction()
andtoggleAction()
functions can be used as decorators on class methods, to denote them as actions.- __init__(overlayList, displayCtx)[source]
Create an
ActionProvider
.- Parameters:
overlayList – The
OverlayList
.displayCtx – The
DisplayContext
.
- property overlayList
Return a reference to the
OverlayList
.
- property displayCtx
Return a reference to the
DisplayContext
.
- destroy()[source]
Must be called when this
ActionProvider
is no longer needed. Calls theAction.destroy()
method of allAction
instances.
- hasAction(name)[source]
Return
True
if thisActionProvider
has an action with the given name,False
otherwise
- getActions()[source]
Return a list containing the
(name, Action)
of allAction
instances in thisActionProvider
.Sub-classes may wish to override this method to enforce a specific ordering of their actions.
Note
The list returned by this method may contain entries equal to
(None, None)
. This is used as a hint for theFSLeyesFrame
, which creates menu items, to indicate that a separator should be inserted.
- __dict__ = mappingproxy({'__module__': 'fsleyes.actions', '__doc__': 'The ``ActionProvider`` class is intended to be used as a base class for\n classes which contain actions. The :func:`action` and :func:`toggleAction`\n functions can be used as decorators on class methods, to denote them as\n actions.\n ', '__init__': <function ActionProvider.__init__>, 'overlayList': <property object>, 'displayCtx': <property object>, 'destroy': <function ActionProvider.destroy>, 'getAction': <function ActionProvider.getAction>, 'hasAction': <function ActionProvider.hasAction>, 'enableAction': <function ActionProvider.enableAction>, 'disableAction': <function ActionProvider.disableAction>, 'getActions': <function ActionProvider.getActions>, '__dict__': <attribute '__dict__' of 'ActionProvider' objects>, '__weakref__': <attribute '__weakref__' of 'ActionProvider' objects>, '__annotations__': {}})
- __module__ = 'fsleyes.actions'
- __weakref__
list of weak references to the object
- class fsleyes.actions.ActionFactory(actionType, *args, **kwargs)[source]
Bases:
object
The
ActionFactory
is used by theaction()
,toggleAction()
, andtoggleControlPanelAction()
decorators. Its job is to createAction
instances forActionProvider
instances.Warning
This class contains difficult-to-understand code. Read up on decorators and descriptors before proceeding.
Note
This class has no use outside of this module, except for use with custom
Action
/ToggleAction
sub-classes and corresponding decorators (along the lines ofaction()
andtoggleAction()
). A custom decorator simply needs to returnActionFactory(CustomActionClass, *args, **kwargs)
, where the*args
and**kwargs
are the arguments passed to theAction
sub-class.See the
toggleControlAction()
decorator for an example.Boring technical details
Consider the following class:
class MyThing(ActionProvider): @action def myAction(self): # do things here
The
MyClass.myAction
method has been marked as an action, using theaction()
decorator. However, theaction()
decorator cannot create anAction
instance at the point of class definition, because this would lead to a singleAction
instance being shared by multipleMyThing
instances. We need to be able to create anAction
instance for everyMyThing
instance, whilst still allowing the action decorator to be used on class methods.So when the
action()
ortoggleAction()
is used in a class definition, anActionFactory
is created, and used as the decorator of the unbound class method.Later on, when the
ActionFactory
detects that it being is accessed through an instance of the class (aMyThing
instance in the example above), it creates anAction
instance, and then replaces itself with thisAction
instance - theAction
instance becomes the decorator of the bound method. This is possible because theActionFactory
is a descriptor - it uses the__get__()
method so it can differentiate between class-level and instance-level accesses of the decorated method.The
ActionFactory
supports class-method decorators both with and without arguments. While neither theAction
, nor theToggleAction
classes accept any optional arguments, this may be useful for custom sub-classes, i.e.:class MyThing(ActionProvider): @action def myAction(self): # do things here @customAction() def myAction2(self): # do things here @otherCustomAction(arg1=8) def myAction3(self): # do things here
Todo
Merge/replace this class with the
memoize.Instanceify
decorator.- __init__(actionType, *args, **kwargs)[source]
Create an
ActionFactory
.- Parameters:
actionType – The action type (e.g.
Action
orToggleAction
).
The remaining arguments may comprise a single callable object, (an
@action
style decorator was used) or a collection of arguments passed to the decorator (an@action(...)
style decorator was used).
- __call__(func=None)[source]
If this
ActionFactory
was instantiated through a brackets-style decorator (e.g.@action(arg1=1, arg2=2)
), this method is called immediately after__init__()
, with a reference to the decorated function. Otherwise, (an@action
style decorator was used), this method should never be called.
- __get__(instance, cls)[source]
When this
ActionFactory
is accessed through an instance, anAction
instance is created. ThisActionFactory
is then replaced by theAction
instance.If this
ActionFactory
is accessed through a class, the encapsulated function is returned.
- __dict__ = mappingproxy({'__module__': 'fsleyes.actions', '__doc__': 'The ``ActionFactory`` is used by the :func:`action`,\n :func:`toggleAction`, and :func:`toggleControlPanelAction` decorators.\n Its job is to create :class:`Action` instances for :class:`ActionProvider`\n instances.\n\n\n .. warning:: This class contains difficult-to-understand code. Read up\n on decorators and descriptors before proceeding.\n\n\n .. note:: This class has no use outside of this module, except for use\n with custom :class:`.Action`/:class:`.ToggleAction` sub-classes\n and corresponding decorators (along the lines of :func:`.action`\n and :func:`.toggleAction`). A custom decorator simply needs\n to return ``ActionFactory(CustomActionClass, *args, **kwargs)``,\n where the ``*args`` and ``**kwargs`` are the arguments passed to\n the :class:`Action` sub-class.\n\n See the :func:`toggleControlAction` decorator for an example.\n\n\n *Boring technical details*\n\n\n Consider the following class::\n\n class MyThing(ActionProvider):\n\n @action\n def myAction(self):\n # do things here\n\n\n The ``MyClass.myAction`` method has been marked as an action, using the\n :func:`action` decorator. However, the :func:`action` decorator cannot\n create an :class:`Action` instance at the point of class definition,\n because this would lead to a single ``Action`` instance being shared by\n multiple ``MyThing`` instances. We need to be able to create an ``Action``\n instance for every ``MyThing`` instance, whilst still allowing the action\n decorator to be used on class methods.\n\n\n So when the :func:`action` or :func:`toggleAction` is used in a class\n definition, an ``ActionFactory`` is created, and used as the decorator\n of the unbound class method.\n\n\n Later on, when the ``ActionFactory`` detects that it being is accessed\n through an instance of the class (a ``MyThing`` instance in the example\n above), it creates an :class:`Action` instance, and then replaces itself\n with this ``Action`` instance - the ``Action`` instance becomes the\n decorator of the bound method. This is possible because the\n ``ActionFactory`` is a descriptor - it uses the :meth:`__get__` method\n so it can differentiate between class-level and instance-level accesses\n of the decorated method.\n\n\n The ``ActionFactory`` supports class-method decorators both with and\n without arguments. While neither the :class:`.Action`, nor the\n :class:`.ToggleAction` classes accept any optional arguments, this may be\n useful for custom sub-classes, i.e.::\n\n class MyThing(ActionProvider):\n\n @action\n def myAction(self):\n # do things here\n\n @customAction()\n def myAction2(self):\n # do things here\n\n @otherCustomAction(arg1=8)\n def myAction3(self):\n # do things here\n\n\n .. todo:: Merge/replace this class with the :class:`.memoize.Instanceify`\n decorator.\n ', '__init__': <function ActionFactory.__init__>, '__call__': <function ActionFactory.__call__>, '__get__': <function ActionFactory.__get__>, '__dict__': <attribute '__dict__' of 'ActionFactory' objects>, '__weakref__': <attribute '__weakref__' of 'ActionFactory' objects>, '__annotations__': {}})
- __module__ = 'fsleyes.actions'
- __weakref__
list of weak references to the object
- class fsleyes.actions.ActionButton(actionName, classType=None, actionArgs=None, actionKwargs=None, **kwargs)[source]
Bases:
Button
Extends the
props.Button
class to encapsulate anAction
instance.Only actions which are defined using the
action()
ortoggleAction()
decorator are supported.- __init__(actionName, classType=None, actionArgs=None, actionKwargs=None, **kwargs)[source]
Create an
ActionButton
.- Parameters:
actionName – Name of the action
classType – The type which defines the action.
kwargs – Passed to the
props.Button
constructor.
- __setup(instance, parent, widget)
Called when the button is created. Binds the button widget to the
Action
instance.
- __onButton(instance, widget)
Called when the button is pushed. Runs the action.
- __module__ = 'fsleyes.actions'
- class fsleyes.actions.ToggleActionButton(actionName, icon, actionArgs=None, actionKwargs=None, **kwargs)[source]
Bases:
Toggle
Extends the
props.Toggle
class to encapsulate aToggleAction
instance.Only actions which are defined using the
action()
ortoggleAction()
decorator are supported.- __init__(actionName, icon, actionArgs=None, actionKwargs=None, **kwargs)[source]
Create a
ToggleActionButton
.- Parameters:
actionName – Name of the action
icon – One or two icon file names to use on the button.
actionArgs – Positional arguments to pass to the
ToggleAction
when it is invoked.actionKwargs – Keyword arguments to pass to the
ToggleAction
when it is invoked.kwargs – Passed to the
props.Toggle
constructor.
- __setup(instance, parent, widget)
Called when the toggle widget is created. Binds the widget to the
ToggleAction
instance.
- __annotations__ = {}
- __module__ = 'fsleyes.actions'
- __onToggle(instance, widget)
Called when the widget is toggled. Runs the action.