diff --git a/doc/images/lookuptablepanel.png b/doc/images/lookuptablepanel.png
new file mode 100644
index 0000000000000000000000000000000000000000..524b9cf090674c2a71296c741468e5dd43f76165
Binary files /dev/null and b/doc/images/lookuptablepanel.png differ
diff --git a/fsl/data/strings.py b/fsl/data/strings.py
index ffd072a4f06782e657ba55f295f66586a79ea705..d15c7191a9dad291c633b5abe536d03fc636cbae 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 e41127cb359d6fbc39c629818898958101ec06ca..4cae6337aa6f5f7539eaec38fc7c486cbeddf9c3 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 3517986b77e5372cd0afebe72cc33b5864c3574f..6e66c63dea38d2b15698a5fb1ff71a2341439e01 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.