From c03c71182baa76f16057b9acd25c58b183122fc3 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauld.mccarthy@gmail.com> Date: Fri, 18 Sep 2015 18:53:43 +0100 Subject: [PATCH] Half-documented, and refactored LookupTablePanel so it is always usable (previously was only usable when a compatible overlay was selected). Next commit will have finished documentation. --- doc/images/lookuptablepanel.png | Bin 0 -> 47489 bytes fsl/data/strings.py | 4 - fsl/fsleyes/colourmaps.py | 10 + fsl/fsleyes/controls/lookuptablepanel.py | 535 +++++++++++++---------- 4 files changed, 312 insertions(+), 237 deletions(-) create mode 100644 doc/images/lookuptablepanel.png diff --git a/doc/images/lookuptablepanel.png b/doc/images/lookuptablepanel.png new file mode 100644 index 0000000000000000000000000000000000000000..524b9cf090674c2a71296c741468e5dd43f76165 GIT binary patch literal 47489 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 MMp-)VrtyRS0z@T7-2eap literal 0 HcmV?d00001 diff --git a/fsl/data/strings.py b/fsl/data/strings.py index ffd072a4f..d15c7191a 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -107,10 +107,6 @@ messages = TypeDict({ 'HistogramPanel.calcHist' : 'Calculating histogram for {} ...', - - 'LookupTablePanel.notLutOverlay' : 'Choose an overlay which ' - 'uses a lookup table', - 'LookupTablePanel.labelExists' : 'The {} LUT already contains a ' 'label with value {}', diff --git a/fsl/fsleyes/colourmaps.py b/fsl/fsleyes/colourmaps.py index e41127cb3..4cae6337a 100644 --- a/fsl/fsleyes/colourmaps.py +++ b/fsl/fsleyes/colourmaps.py @@ -914,6 +914,16 @@ class LookupTable(props.HasProperties): if lutFile is not None: self._load(lutFile) + + + def __str__(self): + """Returns the name of this ``LookupTable``. """ + return self.name + + + def __repr__(self): + """Returns the name of this ``LookupTable``. """ + return self.name def __len__(self): diff --git a/fsl/fsleyes/controls/lookuptablepanel.py b/fsl/fsleyes/controls/lookuptablepanel.py index 3517986b7..6e66c63de 100644 --- a/fsl/fsleyes/controls/lookuptablepanel.py +++ b/fsl/fsleyes/controls/lookuptablepanel.py @@ -1,20 +1,32 @@ #!/usr/bin/env python # -# lookuptablepanel.py - +# lookuptablepanel.py - The LookupTablePanel class. # # Author: Paul McCarthy <pauldmccarthy@gmail.com> # +"""This module provides the :class:`LookupTablePanel`, a *FSLeyes control* +panel which allows the user to manage lookup tables. See the +:mod:`.colourmaps` module for more details on lookup tables. + +A few other class are defined in this module, all for use by the +``LookupTablePanel``: + +.. autosummary:: + :nosignatures: + + LabelWidget + NewLutDialog + LutLabelDialog +""" + import os -import copy import logging import wx import numpy as np -import props - import pwidgets.elistbox as elistbox import fsl.fsleyes.panel as fslpanel @@ -26,82 +38,45 @@ import fsl.data.strings as strings log = logging.getLogger(__name__) +class LookupTablePanel(fslpanel.FSLEyesPanel): + """A ``LookupTablePanel`` is a :class:`.FLSEyesPanel` which allows users + to manage ``LookupTable`` instances. A ``LookupTablePanel`` looks + something like this: + .. image:: images/lookuptablepanel.png + :scale: 50% + :align: center -class LabelWidget(wx.Panel): + A ``LookupTablePanel`` allows the user to do the following: - def __init__(self, lutPanel, overlayOpts, lut, value): - wx.Panel.__init__(self, lutPanel) - - self.lutPanel = lutPanel - self.opts = overlayOpts - self.lut = lut - self.value = value - - # TODO Change the enable box to a toggle - # button with an eye icon - - self.valueLabel = wx.StaticText(self, - style=wx.ALIGN_CENTRE_VERTICAL | - wx.ALIGN_RIGHT) - self.enableBox = wx.CheckBox(self) - self.colourButton = wx.ColourPickerCtrl(self) - - self.sizer = wx.BoxSizer(wx.HORIZONTAL) - self.SetSizer(self.sizer) - self.sizer.Add(self.valueLabel, flag=wx.ALIGN_CENTRE, proportion=1) - self.sizer.Add(self.enableBox, flag=wx.ALIGN_CENTRE, proportion=1) - self.sizer.Add(self.colourButton, flag=wx.ALIGN_CENTRE, proportion=1) - - label = lut.get(value) - colour = [np.floor(c * 255.0) for c in label.colour()] - - self.valueLabel .SetLabel(str(value)) - self.colourButton.SetColour(colour) - self.enableBox .SetValue(label.enabled()) + - Add/remove labels to/from a :class:`LookupTable`. + + - Change the colour, name, and visibility of a label in a + ``LookupTable``. + + - Create a new ``LookupTable``, or copy an existing one. - self.enableBox .Bind(wx.EVT_CHECKBOX, self.__onEnable) - self.colourButton.Bind(wx.EVT_COLOURPICKER_CHANGED, self.__onColour) + - Save/load a ``LookupTable`` to/from a file. + """ + - - def __onEnable(self, ev): + def __init__(self, parent, overlayList, displayCtx): + """Create a ``LookupTablePanel``. - # Disable the LutPanel listener, otherwise - # it will recreate the label list (see - # LookupTablePanel._initLabelList) - self.lut.disableListener('labels', self.lutPanel._name) - self.lut.set(self.value, enabled=self.enableBox.GetValue()) - self.lut.enableListener('labels', self.lutPanel._name) + :arg parent: The :mod:`wx` parent object. + :arg overlayList: The :class:`.OverlayList` instance. + :arg displayCtx: The :class:`.DisplayContext` instance. + """ - def __onColour(self, ev): - - newColour = self.colourButton.GetColour() - newColour = [c / 255.0 for c in newColour] - - self.lut.disableListener('labels', self.lutPanel._name) - self.lut.set(self.value, colour=newColour) - self.lut.enableListener('labels', self.lutPanel._name) - - -class LookupTablePanel(fslpanel.FSLEyesPanel): - - def __init__(self, parent, overlayList, displayCtx): - fslpanel.FSLEyesPanel.__init__(self, parent, overlayList, displayCtx) self.__controlRow = wx.Panel(self) - self.__disabledLabel = wx.StaticText(self, - style=wx.ALIGN_CENTER_VERTICAL | - wx.ALIGN_CENTER_HORIZONTAL) self.__labelList = elistbox.EditableListBox( self, style=elistbox.ELB_NO_MOVE | elistbox.ELB_EDITABLE) - self.__overlayNameLabel = wx.StaticText(self, - style=wx.ST_ELLIPSIZE_MIDDLE) - - self.__lutWidget = None + self.__lutChoice = wx.Choice(self.__controlRow) self.__newLutButton = wx.Button(self.__controlRow) self.__copyLutButton = wx.Button(self.__controlRow) self.__saveLutButton = wx.Button(self.__controlRow) @@ -113,6 +88,8 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): self.__controlRow.SetSizer(self.__controlRowSizer) self .SetSizer(self.__sizer) + self.__controlRowSizer.Add(self.__lutChoice, + flag=wx.EXPAND, proportion=1) self.__controlRowSizer.Add(self.__newLutButton, flag=wx.EXPAND, proportion=1) self.__controlRowSizer.Add(self.__copyLutButton, @@ -122,13 +99,10 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): self.__controlRowSizer.Add(self.__saveLutButton, flag=wx.EXPAND, proportion=1) - self.__sizer.Add(self.__overlayNameLabel, flag=wx.EXPAND) - self.__sizer.Add(self.__controlRow, flag=wx.EXPAND) - self.__sizer.Add(self.__disabledLabel, flag=wx.EXPAND, proportion=1) - self.__sizer.Add(self.__labelList, flag=wx.EXPAND, proportion=1) + self.__sizer.Add(self.__controlRow, flag=wx.EXPAND) + self.__sizer.Add(self.__labelList, flag=wx.EXPAND, proportion=1) # Label the labels and buttons - self.__disabledLabel.SetLabel(strings.messages[self, 'notLutOverlay']) self.__newLutButton .SetLabel(strings.labels[ self, 'newLut']) self.__copyLutButton.SetLabel(strings.labels[ self, 'copyLut']) self.__loadLutButton.SetLabel(strings.labels[ self, 'loadLut']) @@ -142,6 +116,7 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): self.__labelList.Bind(elistbox.EVT_ELB_EDIT_EVENT, self.__onLabelEdit) + self.__lutChoice .Bind(wx.EVT_CHOICE, self.__onLutChoice) self.__newLutButton .Bind(wx.EVT_BUTTON, self.__onNewLut) self.__copyLutButton.Bind(wx.EVT_BUTTON, self.__onCopyLut) self.__loadLutButton.Bind(wx.EVT_BUTTON, self.__onLoadLut) @@ -158,53 +133,24 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): self._name, self.__selectedOverlayChanged) - self.__disabledLabel.Show(False) - self.__controlRowSizer.SetMinSize(self.__calcControlRowMinSize()) - self.Layout() - self.SetMinSize(self.__sizer.GetMinSize()) - + self.__updateLutChoices() self.__selectedOverlayChanged() - - def __calcControlRowMinSize(self): - """This method calculates and returns a minimum width and height - for the control row. - - When the LookupTable is first created, there is no LUT widget - it is - created when an appropriate overlay is selected (see - :meth:`__overlayTypeChanged`). Here, we create a dummy LUT widget, and - use its best size, along with the control row button sizes, to - calculate the minimum size needed to lay out the control row. - """ - - class DummyLut(props.HasProperties): - lut = copy.copy(displayctx.LabelOpts.lut) - - dl = DummyLut() - dummyLutWidget = props.makeWidget( - self, - dl, - 'lut', - labels=lambda l: l.name) - width, height = dummyLutWidget.GetBestSize().Get() - - for btn in [self.__newLutButton, - self.__copyLutButton, - self.__saveLutButton, - self.__loadLutButton]: + # If the selected lut was not set + # via the selectedOverlayChanged + # call, we'll manually set it + if self.__selectedLut is None: + self.__setLut(fslcmaps.getLookupTables()[0]) - w, h = btn.GetBestSize().Get() - width += w - - if h > height: - height = h - - dummyLutWidget.Destroy() - - return width, height + self.Layout() + self.SetMinSize(self.__sizer.GetMinSize()) def destroy(self): + """Must be called when this ``LookupTablePanel`` is no longer needed. + Removes some property listeners, and calls the + :meth:`FSLEyesPanel.destroy` method. + """ self._overlayList.removeListener('overlays', self._name) self._displayCtx .removeListener('selectedOverlay', self._name) @@ -213,11 +159,9 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): opts = self.__selectedOpts lut = self.__selectedLut - if overlay is not None: + if overlay is not None and overlay in self._overlayList: display = self._displayCtx.getDisplay(overlay) - - display.removeListener('name', self._name) display.removeListener('overlayType', self._name) if opts is not None: @@ -227,141 +171,121 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): lut.removeListener('labels', self._name) lut.removeListener('saved', self._name) - fslpanel.FSLEyesPanel.destroy(self) - - - def __selectedOverlayChanged(self, *a): - - newOverlay = self._displayCtx.getSelectedOverlay() - - if self.__selectedOverlay == newOverlay: - return - - if self.__selectedOverlay is not None and \ - self.__selectedOverlay in self._overlayList: - - display = self._displayCtx.getDisplay(self.__selectedOverlay) - - display.removeListener('name', self._name) - display.removeListener('overlayType', self._name) + self.__selectedOverlay = None + self.__selectedOpts = None + self.__selectedLut = None - self.__selectedOverlay = newOverlay + fslpanel.FSLEyesPanel.destroy(self) - if newOverlay is not None: - display = self._displayCtx.getDisplay(newOverlay) - display.addListener('name', - self._name, - self.__overlayNameChanged) - display.addListener('overlayType', - self._name, - self.__overlayTypeChanged) + + def __updateLutChoices(self): + """Refreshes the contents of the lookup table drop down box. + See the :func:`.colourmaps.getLookupTables` function. + """ - self.__overlayNameChanged() - self.__overlayTypeChanged() + log.debug('Updating lookup table choices') + oldNames = self.__lutChoice.GetItems() + oldSelection = self.__lutChoice.GetSelection() - def __overlayNameChanged(self, *a): + luts = fslcmaps.getLookupTables() + newNames = [l.name for l in luts] - overlay = self.__selectedOverlay + try: newSelection = oldNames.index(oldNames[oldSelection]) + except: newSelection = 0 - if overlay is None: - self.__overlayNameLabel.SetLabel('') - return + self.__lutChoice.SetItems(newNames) + self.__lutChoice.SetSelection(newSelection) - display = self._displayCtx.getDisplay(overlay) + for i, lut in enumerate(luts): + self.__lutChoice.SetClientData(i, lut) - self.__overlayNameLabel.SetLabel(display.name) + def __createLabelList(self): + """Refreshes the contents of the list ``LookupTable` label list.""" - def __overlayTypeChanged(self, *a): - - if self.__lutWidget is not None: - self.__controlRowSizer.Detach(self.__lutWidget) - self.__lutWidget.Destroy() - self.__lutWidget = None - - if self.__selectedOpts is not None: - self.__selectedOpts.removeListener('lut', self._name) - self.__selectedOpts = None + log.debug('Creating lookup table label list') - overlay = self.__selectedOverlay - enabled = False - - if overlay is not None: - opts = self._displayCtx.getOpts(overlay) - - if isinstance(opts, displayctx.LabelOpts): - enabled = True - - self.__overlayNameLabel.Show( enabled) - self.__controlRow .Show( enabled) - self.__labelList .Show( enabled) - self.__disabledLabel .Show(not enabled) - - if not enabled: - self.Layout() - return + self.__labelList.Clear() - opts = self._displayCtx.getOpts(overlay) + lut = self.__selectedLut - opts.addListener('lut', self._name, self.__lutChanged) - - self.__selectedOpts = opts - self.__lutWidget = props.makeWidget( - self.__controlRow, opts, 'lut', labels=lambda l: l.name) + for i, label in enumerate(lut.labels): - self.__controlRowSizer.Insert( - 0, self.__lutWidget, flag=wx.EXPAND, proportion=1) + self.__labelList.Append(label.name()) - self.__lutChanged() + widget = LabelWidget(self, lut, label.value()) + self.__labelList.SetItemWidget(i, widget) - self.Layout() + def __setLut(self, lut): + """Updates this ``LookupTablePanel`` to display the labels for the + given ``lut`` (assumed to be a :class:`.LookupTable` instance). + + If the currently selected overlay is associated with a + :class:`.LabelOpts` instance, its :attr:`.LabelOpts.lut` property + is set to the new ``LookupTable``. + """ - def __lutChanged(self, *a): + log.debug('Selecting lut: {}'.format(lut)) if self.__selectedLut is not None: self.__selectedLut.removeListener('labels', self._name) self.__selectedLut.removeListener('saved', self._name) - self.__selecedLut = None - - opts = self.__selectedOpts + + self.__selectedLut = lut - if opts is not None: - self.__selectedLut = opts.lut + if lut is not None: + lut.addListener('labels', self._name, self.__lutLabelsChanged) + lut.addListener('saved', self._name, self.__lutSaveStateChanged) - self.__selectedLut.addListener( - 'labels', self._name, self.__initLabelList) - self.__selectedLut.addListener( - 'saved', self._name, self.__lutSaveStateChanged) + if lut is not None and self.__selectedOpts is not None: + self.__selectedOpts.disableListener('lut', self._name) + self.__selectedOpts.lut = lut + self.__selectedOpts.enableListener('lut', self._name) - self.__initLabelList() + allLuts = fslcmaps.getLookupTables() + + self.__lutChoice.SetSelection(allLuts.index(lut)) + self.__lutSaveStateChanged() + self.__createLabelList() def __lutSaveStateChanged(self, *a): + """Called when the :attr:`.LookupTable.saved` property of the + current :class:`LookupTable` instance changes. Sets the state + of the *save* button accordingly. + """ self.__saveLutButton.Enable(not self.__selectedLut.saved) - - def __initLabelList(self, *a): - self.__labelList.Clear() + def __lutLabelsChanged(self, *a): + """Called when the :attr:`.LookupTable.labels` property of + the current :class:`LookupTable` instance changes. Updates + the list of labels. + """ + self.__createLabelList() - if self.__selectedOpts is None: - return - opts = self.__selectedOpts - lut = opts.lut + def __onLutChoice(self, ev): + """Called when the user changes the selected :class:`.LookupTable` + via the lookup table drop down box. If a . + """ - for i, label in enumerate(lut.labels): + selection = self.__lutChoice.GetSelection() + lut = self.__lutChoice.GetClientData(selection) - self.__labelList.Append(label.name()) + log.debug('Lut choice: {}'.format(lut)) - widget = LabelWidget(self, opts, lut, label.value()) - self.__labelList.SetItemWidget(i, widget) + self.__setLut(lut) def __onNewLut(self, ev): + """Called when the user presses the *New LUT* button. Displays a + :class:`NewLutDialog`, prompting the user to enter a name, and then + creates and registers a new :class:`.LookupTable` instance. + """ dlg = NewLutDialog(self.GetTopLevelParent()) if dlg.ShowModal() != wx.ID_OK: @@ -373,11 +297,17 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): lut = fslcmaps.LookupTable(dlg.name) fslcmaps.registerLookupTable(lut, self._overlayList, self._displayCtx) - if self.__selectedOpts is not None: - self.__selectedOpts.lut = lut + self.__updateLutChoices() + self.__setLut(lut) def __onCopyLut(self, ev): + """Called when the user presses the *Copy LUT* button. Displays a + :class:`NewLutDialog`, prompting the user to enter a name, and then + creates and registers a new :class:`.LookupTable` instance which is + initialised with the same label as the previously selected + ``LookupTable``. + """ name = self.__selectedLut.name @@ -399,11 +329,20 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): fslcmaps.registerLookupTable(lut, self._overlayList, self._displayCtx) - if self.__selectedOpts is not None: - self.__selectedOpts.lut = lut + self.__updateLutChoices() + self.__setLut(lut) - + def __onLoadLut(self, ev): + """Called when the user presses the *Load LUT* button. Displays a + :class:`NewLutDialog`, prompting the user to enter a name, and + then a ``wx.FileDialog`, prompting the user to select a file + containing lookup table information (See the :mod:`.colourmaps` + module for more details on the file format). + + Then creates and registers a new :class:`.LookupTable` instance, + initialising it with the selected file. + """ nameDlg = NewLutDialog(self.GetTopLevelParent()) @@ -426,63 +365,193 @@ class LookupTablePanel(fslpanel.FSLEyesPanel): self._displayCtx, name) - if self.__selectedOpts is not None: - self.__selectedOpts.lut = lut + self.__updateLutChoices() + self.__setLut(lut) def __onSaveLut(self, ev): + """Called when the user presses the *Save LUT* button. Makes sure + that the current :class:`LookupTable` is saved (see the + :func:`.colourmaps.installLookupTable` function). + """ fslcmaps.installLookupTable(self.__selectedLut.name) def __onLabelAdd(self, ev): + """Called when the user pushes the *add* button on the lookup table + label list. Displays a :class:`LutLabelDialog`, prompting the user + to select a name, value and colour, and then adds a new label to the + current :class:`.LookupTable` instance. + """ dlg = LutLabelDialog(self.GetTopLevelParent()) if dlg.ShowModal() != wx.ID_OK: return - opts = self.__selectedOpts + lut = self.__selectedLut value = dlg.value name = dlg.name colour = dlg.colour[:3] colour = [c / 255.0 for c in colour] - if opts.lut.get(value) is not None: + if lut.get(value) is not None: wx.MessageBox( - strings.messages[self, 'labelExists'].format( - opts.lut.name, value), - strings.titles[ self, 'labelExists'], - wx.ICON_INFORMATION | wx.OK) + strings.messages[self, 'labelExists'].format(lut.name, value), + strings.titles[ self, 'labelExists'], (wx.ICON_INFORMATION | + wx.OK)) return log.debug('New lut label for {}: {}, {}, {}'.format( - opts.lut.name, + lut.name, value, name, colour)) - opts.lut.set(value, name=name, colour=colour) + lut.set(value, name=name, colour=colour) def __onLabelRemove(self, ev): + """Called when the user pushes the *remove* button on the lookup + table label list. Removes the selected label from the current + :class:`.LookupTable`. + """ - opts = self.__selectedOpts - value = opts.lut.labels[ev.idx].value() + lut = self.__selectedLut + value = lut.labels[ev.idx].value() - self.__selectedLut.disableListener('labels', self._name) - opts.lut.delete(value) - self.__selectedLut.enableListener('labels', self._name) + lut.disableListener('labels', self._name) + lut.delete(value) + lut.enableListener('labels', self._name) def __onLabelEdit(self, ev): + """Called when the user edits the name of a label in the lookup + table label list. + """ + + lut = self.__selectedLut + value = lut.labels[ev.idx].value() + + lut.disableListener('labels', self._name) + lut.set(value, name=ev.label) + lut.enableListener('labels', self._name) + + + def __selectedOverlayChanged(self, *a): + """Called when the :class:`OverlayList` or + :attr:`.DisplayContext.selectedOverlay` changes. + Refreshes the ``LookupTablePanel`` accordingly. + """ + + newOverlay = self._displayCtx.getSelectedOverlay() + + if self.__selectedOverlay is not None and \ + self.__selectedOverlay in self._overlayList: + + display = self._displayCtx.getDisplay(self.__selectedOverlay) + display.removeListener('overlayType', self._name) + + self.__selectedOverlay = newOverlay + + if newOverlay is not None: + + display = self._displayCtx.getDisplay(newOverlay) + display.addListener('overlayType', + self._name, + self.__overlayTypeChanged) + + self.__overlayTypeChanged() + + + def __overlayTypeChanged(self, *a): + """Called when the :attr:`.Display.overlayType` property of the + currently selected overlay changes. If the :class:`.DisplayOpts` + instance associated with the new overlay type is a :class:`.LabelOpts`, + a listener is addd to its ``lut`` property. + """ + + if self.__selectedOpts is not None: + self.__selectedOpts.removeListener('lut', self._name) + self.__selectedOpts = None + + overlay = self.__selectedOverlay + opts = None + + if overlay is not None: + opts = self._displayCtx.getOpts(overlay) + + if not isinstance(opts, displayctx.LabelOpts): + return + + opts.addListener('lut', self._name, self.__lutChanged) + + self.__selectedOpts = opts + self.__lutChanged() + self.Layout() + + + def __lutChanged(self, *a): + """Called when the :attr:`.LabelOpts.lut` property associated + with the currently selected overlay changes. + """ + self.__setLut(self.__selectedOpts.lut) + - opts = self.__selectedOpts - value = opts.lut.labels[ev.idx].value() +class LabelWidget(wx.Panel): + + def __init__(self, lutPanel, lut, value): + wx.Panel.__init__(self, lutPanel) - self.__selectedLut.disableListener('labels', self._name) - opts.lut.set(value, name=ev.label) - self.__selectedLut.enableListener('labels', self._name) + self.lutPanel = lutPanel + self.lut = lut + self.value = value + # TODO Change the enable box to a toggle + # button with an eye icon + + self.valueLabel = wx.StaticText(self, + style=wx.ALIGN_CENTRE_VERTICAL | + wx.ALIGN_RIGHT) + self.enableBox = wx.CheckBox(self) + self.colourButton = wx.ColourPickerCtrl(self) + self.sizer = wx.BoxSizer(wx.HORIZONTAL) + self.SetSizer(self.sizer) + self.sizer.Add(self.valueLabel, flag=wx.ALIGN_CENTRE, proportion=1) + self.sizer.Add(self.enableBox, flag=wx.ALIGN_CENTRE, proportion=1) + self.sizer.Add(self.colourButton, flag=wx.ALIGN_CENTRE, proportion=1) + + label = lut.get(value) + colour = [np.floor(c * 255.0) for c in label.colour()] + + self.valueLabel .SetLabel(str(value)) + self.colourButton.SetColour(colour) + self.enableBox .SetValue(label.enabled()) + + self.enableBox .Bind(wx.EVT_CHECKBOX, self.__onEnable) + self.colourButton.Bind(wx.EVT_COLOURPICKER_CHANGED, self.__onColour) + + + def __onEnable(self, ev): + + # Disable the LutPanel listener, otherwise + # it will recreate the label list (see + # LookupTablePanel._createLabelList) + self.lut.disableListener('labels', self.lutPanel._name) + self.lut.set(self.value, enabled=self.enableBox.GetValue()) + self.lut.enableListener('labels', self.lutPanel._name) + + + def __onColour(self, ev): + + newColour = self.colourButton.GetColour() + newColour = [c / 255.0 for c in newColour] + + self.lut.disableListener('labels', self.lutPanel._name) + self.lut.set(self.value, colour=newColour) + self.lut.enableListener('labels', self.lutPanel._name) + + class NewLutDialog(wx.Dialog): """A dialog which is displayed when the user chooses to create a new LUT. -- GitLab