#
# plotlistpanel.py - The PlotListPanel class
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :class:`PlotListPanel` a *FSLeyes control* panel
which allows the user to add/remove :class:`.DataSeries` from an
:class:`.OverlayPlotPanel`.
"""
import numpy as np
import wx
import fsleyes_props as props
import fsleyes_widgets.elistbox as elistbox
import fsleyes.controls.controlpanel as ctrlpanel
import fsleyes.tooltips as fsltooltips
import fsleyes.strings as strings
[docs]class PlotListPanel(ctrlpanel.ControlPanel):
"""The ``PlotListPanel`` is a *FSLeyes control* panel for use with
:class:`.OverlayPlotPanel` views. It allows the user to add and remove
:class:`.DataSeries` instances from the :attr:`.PlotPanel.dataSeries`
list.
For every :class:`.DataSeries` instance in the
:attr:`.PlotPanel.dataSeries` list of the :class:`.OverlayPlotPanel`, the
``PlotListPanel`` creates a :class:`.DataSeriesWidget`, which allows the
user to change the display settings of the :class:`.DataSeries`
instance. A :class:`.EditableListBox` is used to display the labels for
each :class:`.DataSeries` instance, and the associated
:class:`.DataSeriesWidget` controls.
"""
[docs] def __init__(self, parent, overlayList, displayCtx, frame, plotPanel):
"""Create a ``PlotListPanel``.
:arg parent: The :mod:`wx` parent object.
:arg overlayList: The :class:`.OverlayList`.
:arg displayCtx: The :class:`.DisplayContext` instance.
:arg frame: The :class:`.FSLeyesFrame` instance.
:arg plotPanel: The :class:`.OverlayPlotPanel` associated with this
``PlotListPanel``.
"""
ctrlpanel.ControlPanel.__init__(
self, parent, overlayList, displayCtx, frame)
self.__plotPanel = plotPanel
self.__dsList = elistbox.EditableListBox(
self, style=(elistbox.ELB_NO_MOVE |
elistbox.ELB_EDITABLE |
elistbox.ELB_WIDGET_RIGHT))
self.__sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.__sizer)
self.__sizer.Add(self.__dsList, flag=wx.EXPAND, proportion=1)
self.__dsList.Bind(elistbox.EVT_ELB_ADD_EVENT, self.__onListAdd)
self.__dsList.Bind(elistbox.EVT_ELB_REMOVE_EVENT, self.__onListRemove)
self.__dsList.Bind(elistbox.EVT_ELB_EDIT_EVENT, self.__onListEdit)
self.__dsList.Bind(elistbox.EVT_ELB_SELECT_EVENT, self.__onListSelect)
self.__plotPanel.addListener('dataSeries',
self.name,
self.__dataSeriesChanged)
self.__dataSeriesChanged()
self.Layout()
self.SetMinSize(self.__sizer.GetMinSize())
[docs] def destroy(self):
"""Must be called when this ``PlotListPanel`` is no longer
needed. Removes some property listeners, and calls the
:meth:`.ControlPanel.destroy` method.
"""
self.__plotPanel.removeListener('dataSeries', self.name)
self.__plotPanel = None
self.__dsList.Clear()
ctrlpanel.ControlPanel.destroy(self)
def __dataSeriesChanged(self, *a):
"""Called when the :attr:`.PlotPanel.dataSeries` list of the
:class:`.OverlayPlotPanel` changes. Updates the list of
:class:`.TimeSeriesWidget` controls.
"""
self.__dsList.Clear()
for ds in self.__plotPanel.dataSeries:
widg = DataSeriesWidget(self, ds)
self.__dsList.Append(
ds.label,
clientData=ds,
tooltip=fsltooltips.properties[ds, 'label'],
extraWidget=widg)
def __onListAdd(self, ev):
"""Called when the user pushes the *add* button on the
:class:`.EditableListBox`. Adds the :class:`.DataSeries` associated
with the currently selected overlay to the
:attr:`.PlotPanel.dataSeries` list of the :class:`.OverlayPlotPanel`.
"""
self.__plotPanel.addDataSeries()
def __onListEdit(self, ev):
"""Called when the user edits a label on the
:class:`.EditableListBox`. Updates the :attr:`.DataSeries.label`
property of the corresponding :class:`DataSeries` instance.
"""
ev.data.label = ev.label
def __onListSelect(self, ev):
"""Called when the user selects an item in the
:class:`.EditableListBox`. Sets the
:attr:`.DisplayContext.selectedOverlay` to the overlay associated
with the corresponding :class:`.DataSeries` instance.
"""
ds = ev.data
overlay = ds.overlay
if overlay is None:
return
opts = self.displayCtx.getOpts(overlay)
self.displayCtx.selectedOverlay = self.overlayList.index(overlay)
# See hacky things in __onListAdd
if hasattr(ds, '_volume'):
opts.volume = ds._volume
elif hasattr(ds, '_location'):
voxLoc = np.array(ds._location)
disLoc = opts.transformCoords([voxLoc], 'voxel', 'display')[0]
self.displayCtx.location = disLoc
def __onListRemove(self, ev):
"""Called when the user removes an item from the
:class:`.EditableListBox`. Removes the corresponding
:class:`.DataSeries` instance from the :attr:`.PlotPanel.dataSeries`
list of the :class:`.OverlayPlotPanel`.
"""
with props.skip(self.__plotPanel, 'dataSeries', self.name):
self.__plotPanel.dataSeries.remove(ev.data)