Skip to content
Snippets Groups Projects
Commit dfbd80ab authored by Paul McCarthy's avatar Paul McCarthy
Browse files

AtlasOverlayPanel now uses status bar instead of a modal dialog. And it

generates the region list on the wx idle loop, so the user can do other
stuff while big atlases are loading.
parent 7a65c0b2
No related branches found
No related tags found
No related merge requests found
...@@ -92,7 +92,9 @@ messages = TypeDict({ ...@@ -92,7 +92,9 @@ messages = TypeDict({
'AtlasPanel.loadingAtlas' : 'Loading {} atlas ...', 'AtlasPanel.loadingAtlas' : 'Loading {} atlas ...',
'AtlasOverlayPanel.loadRegions' : 'Loading region descriptions for {} ...', 'AtlasOverlayPanel.loadRegions' : 'Loading region descriptions '
'for {} ...',
'AtlasOverlayPanel.regionsLoaded' : '{} region descriptions loaded.',
'AtlasInfoPanel.notMNISpace' : 'The selected overlay does not appear to ' 'AtlasInfoPanel.notMNISpace' : 'The selected overlay does not appear to '
'be in MNI152 space - atlas ' 'be in MNI152 space - atlas '
......
...@@ -17,7 +17,8 @@ import pwidgets.elistbox as elistbox ...@@ -17,7 +17,8 @@ import pwidgets.elistbox as elistbox
import fsl.data.atlases as atlases import fsl.data.atlases as atlases
import fsl.data.strings as strings import fsl.data.strings as strings
import fsl.utils.dialog as dialog import fsl.utils.status as status
import fsl.utils.async as async
import fsl.fsleyes.panel as fslpanel import fsl.fsleyes.panel as fslpanel
...@@ -212,9 +213,9 @@ class AtlasOverlayPanel(fslpanel.FSLEyesPanel): ...@@ -212,9 +213,9 @@ class AtlasOverlayPanel(fslpanel.FSLEyesPanel):
If a region list (a list of :class:`OverlayListWidget` items for every If a region list (a list of :class:`OverlayListWidget` items for every
region in the atlas, to be displayed in the region list) has not yet region in the atlas, to be displayed in the region list) has not yet
been created, it is created - a :class:`.ProcessingDialog` is displayed been created, it is created - this is done asynchronously (via the
while this takes place, as it can be time consuming for atlases with a :func:`async.idle` function), as it can take quite a long time for
large number of regions (hint: Talairach). some of the atlases (e.g. the Talairach and Juelich).
Then the region list is updated to show the regions for the newly Then the region list is updated to show the regions for the newly
selected atlas. selected atlas.
...@@ -225,53 +226,80 @@ class AtlasOverlayPanel(fslpanel.FSLEyesPanel): ...@@ -225,53 +226,80 @@ class AtlasOverlayPanel(fslpanel.FSLEyesPanel):
regionList = self.__regionLists[atlasIdx] regionList = self.__regionLists[atlasIdx]
if regionList is None: if regionList is None:
# The region list for this atlas has not yet been
# created. So we create the list, and then create
# a widget for every region in the atlas. Some of
# the atlases (Juelich and Talairach in particular)
# have a large number of regions, so we create the
# widgets asynchronously on the wx idle loop.
regionList = elistbox.EditableListBox( regionList = elistbox.EditableListBox(
self.__regionPanel, self.__regionPanel,
style=(elistbox.ELB_NO_ADD | style=(elistbox.ELB_NO_ADD |
elistbox.ELB_NO_REMOVE | elistbox.ELB_NO_REMOVE |
elistbox.ELB_NO_MOVE)) elistbox.ELB_NO_MOVE))
regionList.Show(False)
self.__regionLists[atlasIdx] = regionList
def buildRegionList(): def addToRegionList(label, i):
log.debug('Creating region list for {} ({})'.format( regionList.Append(label.name)
atlasDesc.atlasID, id(regionList))) widget = OverlayListWidget(regionList,
atlasDesc.atlasID,
self.__atlasPanel,
label.index)
regionList.SetItemWidget(i, widget)
self.__regionLists[atlasIdx] = regionList log.debug('Creating region list for {} ({})'.format(
atlasDesc.atlasID, id(regionList)))
for i, label in enumerate(atlasDesc.labels): status.update(
regionList.Append(label.name) strings.messages[self, 'loadRegions'].format(atlasDesc.name),
widget = OverlayListWidget(regionList, timeout=None)
atlasDesc.atlasID,
self.__atlasPanel,
label.index)
regionList.SetItemWidget(i, widget)
wx.Yield()
filterStr = self.__regionFilter.GetValue().lower().strip() # Schedule addToRegionList on the
regionList.ApplyFilter(filterStr, ignoreCase=True) # wx idle loop for every region.
# Disable the panel while this is
# occurring.
self.Disable()
for i, label in enumerate(atlasDesc.labels):
async.idle(addToRegionList, label, i)
self.__updateAtlasState(atlasIdx) # This function changes the displayed region
# list. We schedule it on the wx idle loop,
# so it will get called after the region list
# has been populated (if it has not been
# displayed before).
def changeAtlasList():
dialog.ProcessingDialog( filterStr = self.__regionFilter.GetValue().lower().strip()
None, regionList.ApplyFilter(filterStr, ignoreCase=True)
strings.messages[self, 'loadRegions'].format(atlasDesc.name),
buildRegionList).Run(mainThread=True)
log.debug('Showing region list for {} ({})'.format(
atlasDesc.atlasID, id(regionList)))
old = self.__regionSizer.GetItem(1).GetWindow() self.__updateAtlasState(atlasIdx)
if old is not None: status.update(strings.messages[self, 'regionsLoaded'].format(
old.Show(False) atlasDesc.name))
log.debug('Showing region list for {} ({})'.format(
regionList.Show(True) atlasDesc.atlasID, id(regionList)))
self.__regionSizer.Remove(1)
old = self.__regionSizer.GetItem(1).GetWindow()
self.__regionSizer.Insert(1, regionList, flag=wx.EXPAND, proportion=1)
self.__regionSizer.Layout() if old is not None:
old.Show(False)
regionList.Show(True)
self.__regionSizer.Remove(1)
self.__regionSizer.Insert(1,
regionList,
flag=wx.EXPAND,
proportion=1)
self.__regionSizer.Layout()
self.Enable()
async.idle(changeAtlasList)
class OverlayListWidget(wx.Panel): class OverlayListWidget(wx.Panel):
......
...@@ -622,10 +622,10 @@ def _showCommandLineArgs(overlayList, displayCtx, canvas): ...@@ -622,10 +622,10 @@ def _showCommandLineArgs(overlayList, displayCtx, canvas):
style=(fsldlg.TED_OK | style=(fsldlg.TED_OK |
fsldlg.TED_READONLY | fsldlg.TED_READONLY |
fsldlg.TED_MULTILINE | fsldlg.TED_MULTILINE |
fsldlg.TED_COPY)) fsldlg.TED_COPY |
fsldlg.TED_COPY_MESSAGE))
dlg.CentreOnParent() dlg.CentreOnParent()
dlg.ShowModal() dlg.ShowModal()
......
...@@ -97,7 +97,7 @@ class SimpleMessageDialog(wx.Dialog): ...@@ -97,7 +97,7 @@ class SimpleMessageDialog(wx.Dialog):
flag=wx.EXPAND | wx.CENTRE | wx.ALL) flag=wx.EXPAND | wx.CENTRE | wx.ALL)
self.SetTransparent(240) self.SetTransparent(240)
self.SetBackgroundColour((225, 225, 200)) self.SetBackgroundColour((225, 225, 255))
self.SetSizer(self.__sizer) self.SetSizer(self.__sizer)
...@@ -380,6 +380,7 @@ class TextEditDialog(wx.Dialog): ...@@ -380,6 +380,7 @@ class TextEditDialog(wx.Dialog):
TED_CANCEL TED_CANCEL
TED_OK_CANCEL TED_OK_CANCEL
TED_COPY TED_COPY
TED_COPY_MESSAGE
A ``TextEditDialog`` looks something like this: A ``TextEditDialog`` looks something like this:
...@@ -410,8 +411,9 @@ class TextEditDialog(wx.Dialog): ...@@ -410,8 +411,9 @@ class TextEditDialog(wx.Dialog):
:arg style: A combination of :data:`TED_READONLY`, :arg style: A combination of :data:`TED_READONLY`,
:data:`TED_MULTILINE`, :data:`TED_OK`, :data:`TED_MULTILINE`, :data:`TED_OK`,
:data:`TED_CANCEL`, :data:`TED_OK_CANCEL`, and :data:`TED_CANCEL`, :data:`TED_OK_CANCEL`,
:data:`TED_COPY`. Defaults to :data:`TED_OK`. :data:`TED_COPY` and :data:`TED_COPY_MESSAGE` . Defaults
to :data:`TED_OK`.
""" """
if style is None: if style is None:
...@@ -432,6 +434,8 @@ class TextEditDialog(wx.Dialog): ...@@ -432,6 +434,8 @@ class TextEditDialog(wx.Dialog):
self.__message .SetLabel(message) self.__message .SetLabel(message)
self.__textEdit.SetValue(text) self.__textEdit.SetValue(text)
self.__showCopyMessage = style & TED_COPY_MESSAGE
# set the min size of the text # set the min size of the text
# ctrl so it can fit a few lines # ctrl so it can fit a few lines
self.__textEdit.SetMinSize((-1, 120)) self.__textEdit.SetMinSize((-1, 120))
...@@ -518,8 +522,10 @@ class TextEditDialog(wx.Dialog): ...@@ -518,8 +522,10 @@ class TextEditDialog(wx.Dialog):
if cb.Open(): if cb.Open():
cb.SetData(wx.TextDataObject(text)) cb.SetData(wx.TextDataObject(text))
cb.Close() cb.Close()
td = TimeoutDialog(self, 'Copied!', 1000)
td.Show() if self.__showCopyMessage:
td = TimeoutDialog(self, 'Copied!', 1000)
td.Show()
def SetMessage(self, message): def SetMessage(self, message):
...@@ -695,3 +701,9 @@ TED_COPY = 16 ...@@ -695,3 +701,9 @@ TED_COPY = 16
"""If set, a *Copy* button will be shown, allowing the use to copy """If set, a *Copy* button will be shown, allowing the use to copy
the text to the system clipboard. the text to the system clipboard.
""" """
TED_COPY_MESSAGE = 32
"""If set, and if :attr:`TED_COPY` is also set, when the user chooses
to copy the text to the system clipboard, a popup message is displayed.
"""
...@@ -133,6 +133,7 @@ class ClearThread(threading.Thread): ...@@ -133,6 +133,7 @@ class ClearThread(threading.Thread):
"""Clear the status after the specified timeout (in seconds). """ """Clear the status after the specified timeout (in seconds). """
self.__timeout = timeout self.__timeout = timeout
self.__vetoEvent .clear()
self.__clearEvent.set() self.__clearEvent.set()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment