diff --git a/fsl/data/strings.py b/fsl/data/strings.py index df9fd6a79285d795b02ddb3006a37ca76138f1a1..364efbbd31061616c9e9220d6092c0c0da7c1e00 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -12,16 +12,18 @@ The strings are stored in :class:`.TypeDict` dictionaries, roughly organised into the following categories: - - :data:`messages`: Messages to be displayed to the user. - - :data:`titles`: Titles of windows, panels, and dialogs. - - :data:`actions`: Names of actions tied to menu options, buttons, etc. - - :data:`labels`: Labels for miscellaneous things. - - :data:`properties`: Display names for ``props.HasProperties`` properties. - - :data:`choices`: Display names for ``props.HasProperties`` choice - properties. - - :data:`anatomy`: Anatomical and orientation labels. - - :data:`nifti`: Labels for NIFTI header fields. - - :data:`feat`: FEAT specific names and labels. + ================== ===================================================== + :data:`messages` Messages to be displayed to the user. + :data:`titles` Titles of windows, panels, and dialogs. + :data:`actions` Names of actions tied to menu options, buttons, etc. + :data:`labels` Labels for miscellaneous things. + :data:`properties` Display names for ``props.HasProperties`` properties. + :data:`choices` Display names for ``props.HasProperties`` choice + properties. + :data:`anatomy` Anatomical and orientation labels. + :data:`nifti` Labels for NIFTI header fields. + :data:`feat` FEAT specific names and labels. + ================== ===================================================== """ diff --git a/fsl/fsleyes/icons.py b/fsl/fsleyes/icons.py index 70257d47c4411c85da6132ed2927a466cd267567..8a06bb4438e1cadcd9fae3345c72f4669de63147 100644 --- a/fsl/fsleyes/icons.py +++ b/fsl/fsleyes/icons.py @@ -1,37 +1,46 @@ #!/usr/bin/env python # -# icons.py - +# icons.py - Application/button icons for FSLeyes. # # Author: Paul McCarthy <pauldmccarthy@gmail.com> # -import os.path as op +"""This module contains a couple of convenience functions for looking up +*FSLeyes* icon images. -import wx +Icons can be looked up by their ID, which is simply the icon file base name. +For exmaple, the bitmap for an icon called ``gear.png`` can be retreived +like so:: -_bitmapPath = op.join(op.dirname(__file__), 'icons') + import fsl.fsleyes.icons as icons + # Get the file name + fname = icons.findImageFile('gear') -def findImageFile(iconId): - return op.join(_bitmapPath, '{}.png'.format(iconId)) + # Get a wx.Bitmap containing the gear icon + gearBmp = icons.loadBitmap('gear') +""" -def _resizeImage(image, size): - - w, h = image.GetSize().Get() +import os.path as op - if w >= h: - h = size * h / float(w) - w = size - else: - w = size * (w / float(h)) - h = size +import wx - image.Rescale(w, h, wx.IMAGE_QUALITY_BICUBIC) - return image + +_ICON_PATH = op.join(op.dirname(__file__), 'icons') +"""The directory which contains all of the icons used in *FSLeyes*. """ + + +def findImageFile(iconId): + """Returns the full path to the icon with the given ``iconId``. + """ + return op.join(_ICON_PATH, '{}.png'.format(iconId)) def loadBitmap(iconId): + """Loads and returns a :class:`wx.Bitmap` containing the specified + ``iconId``. + """ filename = findImageFile(iconId) bmp = wx.EmptyBitmap(1, 1) diff --git a/fsl/fsleyes/splash.py b/fsl/fsleyes/splash.py index 8344ef5c0961359e30b770d289ab39e160fab7b0..3a4faef6ccd4600f327e5912381ae9da1ef64dcf 100644 --- a/fsl/fsleyes/splash.py +++ b/fsl/fsleyes/splash.py @@ -1,23 +1,47 @@ #!/usr/bin/env python # -# splash.py - +# splash.py - FSLeyes splash screen. # # Author: Paul McCarthy <pauldmccarthy@gmail.com> # +"""This module provides the :class:`FSLEyesSplash` class, a splash screen for +*FSLeyes*. +""" -import os.path as op +import os.path as op import wx - import fsl.fsleyes.widgets.imagepanel as imagepanel import fsl.data.strings as strings class FSLEyesSplash(wx.Frame): + """A simple splash screen for *FSLeyes*. An image and a status bar are + displayed; the status bar can be updated via the :meth:`SetStatus` method. + + + The :class:`.ImagePanel` class is used to display the image. + + + Typical usage would be something like the following:: + + splash = FSLEyesSplash(None) + splash.Show() + + # Do something, e.g. loading overlays + splash.SetStatus('Loading blah.nii.gz ...') + + # Finished initialising, the application is ready + splash.Close() + """ def __init__(self, parent): + """Create a ``FSLEyesSplash`` frame. + + :arg parent: The :mod:`wx` parent object. + """ wx.Frame.__init__(self, parent, style=0) @@ -25,23 +49,26 @@ class FSLEyesSplash(wx.Frame): splashbmp = wx.Bitmap(splashfile, wx.BITMAP_TYPE_PNG) splashimg = splashbmp.ConvertToImage() - splashPanel = imagepanel.ImagePanel(self, splashimg) - self.statusBar = wx.StaticText(self, style=wx.ELLIPSIZE_MIDDLE) - self.statusBar.SetLabel(strings.messages[self, 'default']) + self.__splashPanel = imagepanel.ImagePanel(self, splashimg) + self.__statusBar = wx.StaticText(self, style=wx.ELLIPSIZE_MIDDLE) + + self.__statusBar.SetLabel(strings.messages[self, 'default']) - self.statusBar.SetBackgroundColour('#636a70') - self.statusBar.SetForegroundColour('#ffffff') - self .SetBackgroundColour('#636a70') + self.__statusBar.SetBackgroundColour('#636a70') + self.__statusBar.SetForegroundColour('#ffffff') + self .SetBackgroundColour('#636a70') - sizer = wx.BoxSizer(wx.VERTICAL) + self.__sizer = wx.BoxSizer(wx.VERTICAL) - sizer.Add(splashPanel, flag=wx.EXPAND, proportion=1) - sizer.Add(self.statusBar, flag=wx.EXPAND) + self.__sizer.Add(self.__splashPanel, flag=wx.EXPAND, proportion=1) + self.__sizer.Add(self.__statusBar, flag=wx.EXPAND) - self.SetSizer(sizer) + self.SetSizer(self.__sizer) self.Layout() self.Fit() + def SetStatus(self, text): - self.statusBar.SetLabel(text) + """Sets the text shown on the status bar to the specified ``text``. """ + self.__statusBar.SetLabel(text) diff --git a/fsl/fsleyes/tooltips.py b/fsl/fsleyes/tooltips.py index 06f4321ad97be159fc569f881cac90b56ca72edb..ae926a307bbd20fc25734dd47cbdb7ef72ec54dc 100644 --- a/fsl/fsleyes/tooltips.py +++ b/fsl/fsleyes/tooltips.py @@ -1,10 +1,20 @@ #!/usr/bin/env python # -# tooltips.py - Tooltips for FSLEyes. +# tooltips.py - Tooltips for FSLeyes. # # Author: Paul McCarthy <pauldmccarthy@gmail.com> # -"""This module contains tooltips used throughout FSLEyes. """ +"""This module contains tooltips used throughout *FSLeyes*. + +Tooltips are stored in :class:`.TypeDict` dictionariesa, broadly organised +into the following categories: + + ================== ================================================ + :data:`properties` Tooltips for ``props.HasProperties`` properties. + :data:`actions` Tooltips for :class:`.ActionProvider` actions. + :data:`misc` Tooltips for everything else. + ================== ================================================ +""" from fsl.utils.typedict import TypeDict diff --git a/fsl/utils/typedict.py b/fsl/utils/typedict.py index 7c361f4b350f80f0327584c040655f701ed85410..c51176a88502f7cf38bebf959a7493bf24b88e57 100644 --- a/fsl/utils/typedict.py +++ b/fsl/utils/typedict.py @@ -8,17 +8,133 @@ """ class TypeDict(object): - """A custom dictionary which allows classes or class instances to be used - as keys for value lookups, but internally transforms any class/instance - keys into strings. Tuple keys are supported. Value assignment with - class/instance keys is not supported. + """A type-aware dictionary. + + + The purpose of the ``TypeDict`` is to allow value lookup using either + classes or instances as keys. The ``TypeDict`` can be used in the same way + that you would use a regular ``dict``, but the ``get`` and ``__getitem__`` + methods have some extra functionality. + + + **Easy to understand example** + + + Let's say we have a class with some properties:: + + import props + import fsl.utils.typedict as td + + class Animal(props.HasProperties): + isMammal = props.Boolean() + numLegs = props.Int() + + + And we want to associate some tooltips with those properties:: + + tooltips = td.TypeDict({ + + 'Animal.isMammal' : 'Set this to True for mammals, ' + 'False for reptiles.', + 'Animal.numLegs' : 'The nuber of legs on this animal.' + }) + + Because we used a ``TypeDict``, we can now look up those tooltips + in a number of ways:: + + a = Animal() + + # Lookup by string (equivalent to a normal dict lookup) + tt = tooltips['Animal.isMammal'] + + # Lookup by class + tt = tooltips[Animal, 'isMammal'] + + # Lookup by instance + tt = tooltips[a, 'isMammal'] + + + This functionality also works across class hierarchies:: + + class Cat(Animal): + numYoutubeHits = props.Int() + + tooltips = td.TypeDict({ + + 'Animal.isMammal' : 'Set this to True for mammals, ' + 'False for reptiles.', + 'Animal.numLegs' : 'The nuber of legs on this animal.', + 'Cat.numYoutubeHits' : 'Number of youtube videos this cat ' + 'has starred in.' + }) + + c = Cat() + + isMammalTooltip = tooltips[Cat, 'isMammal'] + numLegsTooltip = tooltips[c, 'numLegs'] + youtubeHitsTooltip = tooltips[c, 'numYoutubeHits'] + + # Class-hierachy-aware TypeDict lookups only + # work when you pass in an instance/class as + # the key - the following will result in a + # KeyError: + t = tooltips['Cat.numLegs'] + + + The :meth:`get` method has some extra functionality for working with + class hierarchies:: + + + tooltips = td.TypeDict({ + + 'Animal.isMammal' : 'Set this to True for mammals, ' + 'False for reptiles.', + + 'Animal.numLegs' : 'The nuber of legs on this animal.', + + 'Cat.numLegs' : 'This will be equal to four for all cats, ' + 'but could be less for disabled cats, ' + 'or more for lucky cats.', + + 'Cat.numYoutubeHits' : 'Number of youtube videos this cat ' + 'has starred in.' + }) + + print tooltips.get((c, 'numLegs')) + # 'This will be equal to four for all cats, but could ' + # 'be less for disabled cats, or more for lucky cats.' + + print tooltips.get((c, 'numLegs'), allhits=True) + # ['This will be equal to four for all cats, but could ' + # 'be less for disabled cats, or more for lucky cats.', + # 'The nuber of legs on this animal.'] + + print tooltips.get((c, 'numLegs'), allhits=True, bykey=True) + # {('Animal', 'numLegs'): 'The nuber of legs on this animal.', + # ('Cat', 'numLegs'): 'This will be equal to four for all cats, ' + # 'but could be less for disabled cats, or ' + # 'more for lucky cats.'} + + + **Boring technical description** + + + The ``TypeDict`` is a custom dictionary which allows classes or class + instances to be used as keys for value lookups, but internally transforms + any class/instance keys into strings. Tuple keys are supported. Value + assignment with class/instance keys is not supported. If a class/instance is passed in as a key, and there is no value associated with that class, a search is performed on all of the base classes of that class to see if any values are present for them. """ + def __init__(self, initial=None): + """Create a ``TypeDict``. + + :arg initial: Dictionary containing initial values. + """ if initial is None: initial = {}