diff --git a/fsl/data/strings.py b/fsl/data/strings.py index ffbadc580a64bca2065dabe89e15e187631bf2c7..ece2469269a8ec182ed4ba263d1d23a2f1744340 100644 --- a/fsl/data/strings.py +++ b/fsl/data/strings.py @@ -69,6 +69,11 @@ messages = TypeDict({ 'calling render directly with ' 'this command: \n{}', + 'CanvasPanel.showCommandLineArgs.title' : 'Scene parameters', + 'CanvasPanel.showCommandLineArgs.message' : 'Use these parameters on the ' + 'command line to recreate ' + 'the current scene', + 'PlotPanel.screenshot' : 'Save screenshot', 'PlotPanel.screenshot.error' : 'An error occurred while saving the ' @@ -155,6 +160,7 @@ actions = TypeDict({ 'LoadColourMapAction' : 'Load custom colour map', 'CanvasPanel.screenshot' : 'Take screenshot', + 'CanvasPanel.showCommandLineArgs' : 'Show command line for scene', 'CanvasPanel.toggleColourBar' : 'Colour bar', 'CanvasPanel.toggleOverlayList' : 'Overlay list', 'CanvasPanel.toggleDisplayProperties' : 'Overlay display properties', diff --git a/fsl/fslview/controls/atlasoverlaypanel.py b/fsl/fslview/controls/atlasoverlaypanel.py index ddb44e79663a185c9c23e978d5df40a54e289de5..20f2b03e4126f1279267680fc7b5a7bed1f60a7b 100644 --- a/fsl/fslview/controls/atlasoverlaypanel.py +++ b/fsl/fslview/controls/atlasoverlaypanel.py @@ -211,6 +211,7 @@ class AtlasOverlayPanel(fslpanel.FSLViewPanel): self.__updateAtlasState(atlasIdx) msgdlg.ProcessingDialog( + self, strings.messages[self, 'loadRegions'].format(atlasDesc.name), buildRegionList).Run() diff --git a/fsl/fslview/overlay.py b/fsl/fslview/overlay.py index 0989a12427b27c48fdafebf8da4df9b52669ab18..cc26e907337936f5b8b25d65b223ad3a6123a327 100644 --- a/fsl/fslview/overlay.py +++ b/fsl/fslview/overlay.py @@ -22,6 +22,7 @@ import fsl.data.featresults as featresults import fsl.data.featimage as fslfeatimage import fsl.data.strings as strings import fsl.data.model as fslmodel +import fsl.utils.dialog as fsldlg import fsl.fslview.settings as fslsettings @@ -226,27 +227,13 @@ def loadOverlays(paths, loadFunc='default', errorFunc='default', saveDir=True): # to show the currently loading image if defaultLoad: import wx - loadDlg = wx.Frame(wx.GetApp().GetTopWindow(), style=0) - loadDlgStatus = wx.StaticText(loadDlg, style=wx.ST_ELLIPSIZE_MIDDLE) - - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(loadDlgStatus, - border=25, - proportion=1, - flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTRE) - loadDlg.SetSizer(sizer) - - loadDlg.SetSize((400, 100)) - loadDlg.Layout() + loadDlg = fsldlg.SimpleMessageDialog(wx.GetApp().GetTopWindow()) # The default load function updates # the dialog window created above def defaultLoadFunc(s): msg = strings.messages['overlay.loadOverlays.loading'].format(s) - loadDlgStatus.SetLabel(msg) - loadDlg.Layout() - loadDlg.Refresh() - loadDlg.Update() + loadDlg.SetMessage(msg) # The default error function # shows an error dialog @@ -274,8 +261,7 @@ def loadOverlays(paths, loadFunc='default', errorFunc='default', saveDir=True): # function, show the dialog if defaultLoad: loadDlg.CentreOnParent() - loadDlg.Show(True) - loadDlg.Update() + loadDlg.Show() # Load the images for path in paths: diff --git a/fsl/fslview/views/canvaspanel.py b/fsl/fslview/views/canvaspanel.py index d275473600c47c61ead4332997c0d820e8336fbd..b76e0ee83c5ed0f8559f7c9ea9e1ec91d14c4ce3 100644 --- a/fsl/fslview/views/canvaspanel.py +++ b/fsl/fslview/views/canvaspanel.py @@ -19,6 +19,7 @@ import props import fsl import fsl.tools.fslview_parseargs as fslview_parseargs +import fsl.utils.dialog as fsldlg import fsl.data.image as fslimage import fsl.data.strings as strings import fsl.fslview.overlay as fsloverlay @@ -31,134 +32,6 @@ import viewpanel log = logging.getLogger(__name__) -def _takeScreenShot(overlayList, displayCtx, canvas): - - overlays = displayCtx.getOrderedOverlays() - ovlCopy = list(overlays) - - # Check to make sure that all overlays are saved - # on disk, and ask the user what they want to - # do about the ones that aren't. - for overlay in overlays: - - # Skip disabled overlays - display = displayCtx.getDisplay(overlay) - - if not display.enabled: - ovlCopy.remove(overlay) - continue - - # If the image is not saved, popup a dialog - # telling the user they must save the image - # before the screenshot can proceed - if isinstance(overlay, fslimage.Image) and not overlay.saved: - title = strings.titles[ 'CanvasPanel.screenshot.notSaved'] - msg = strings.messages['CanvasPanel.screenshot.notSaved'] - msg = msg.format(overlay.name) - - dlg = wx.MessageDialog(canvas, - message=msg, - caption=title, - style=(wx.CENTRE | - wx.YES_NO | - wx.CANCEL | - wx.ICON_QUESTION)) - dlg.SetYesNoCancelLabels( - strings.labels['CanvasPanel.screenshot.notSaved.save'], - strings.labels['CanvasPanel.screenshot.notSaved.skip'], - strings.labels['CanvasPanel.screenshot.notSaved.cancel']) - - result = dlg.ShowModal() - - # The user chose to save the image - if result == wx.ID_YES: - fsloverlay.saveOverlay(overlay) - - # The user chose to skip the image - elif result == wx.ID_NO: - ovlCopy.remove(overlay) - continue - - # the user clicked cancel, or closed the dialog - else: - return - - overlays = ovlCopy - - # Ask the user where they want - # the screenshot to be saved - dlg = wx.FileDialog(canvas, - message=strings.messages['CanvasPanel.screenshot'], - style=wx.FD_SAVE) - - if dlg.ShowModal() != wx.ID_OK: - return - - filename = dlg.GetPath() - - # Make the dialog go away before - # the screenshot gets taken - dlg.Destroy() - wx.Yield() - - # Screnshot size and scene options - sceneOpts = canvas.getSceneOptions() - width, height = canvas.getCanvasPanel().GetClientSize().Get() - - # Generate command line arguments for - # a callout to render.py - start with - # the render.py specific options - argv = [] - argv += ['--outfile', filename] - argv += ['--size', '{}'.format(width), '{}'.format(height)] - argv += ['--background', '0', '0', '0', '255'] - - # Add scene options - argv += fslview_parseargs.generateSceneArgs( - overlayList, displayCtx, sceneOpts) - - # Add ortho specific options, if it's - # an orthopanel we're dealing with - if isinstance(sceneOpts, displayctx.OrthoOpts): - - xcanvas = canvas.getXCanvas() - ycanvas = canvas.getYCanvas() - zcanvas = canvas.getZCanvas() - - argv += ['--{}'.format(fslview_parseargs.ARGUMENTS[sceneOpts, - 'xcentre'][1])] - argv += ['{}'.format(c) for c in xcanvas.pos.xy] - argv += ['--{}'.format(fslview_parseargs.ARGUMENTS[sceneOpts, - 'ycentre'][1])] - argv += ['{}'.format(c) for c in ycanvas.pos.xy] - argv += ['--{}'.format(fslview_parseargs.ARGUMENTS[sceneOpts, - 'zcentre'][1])] - argv += ['{}'.format(c) for c in zcanvas.pos.xy] - - # Add display options for each overlay - for overlay in overlays: - - display = displayCtx.getDisplay(overlay) - fname = overlay.dataSource - ovlArgv = fslview_parseargs.generateOverlayArgs(overlay, displayCtx) - argv += [fname] + ovlArgv - - log.debug('Generating screenshot with call ' - 'to render: {}'.format(' '.join(argv))) - - # Run render.py to generate the screenshot - msg = strings.messages['CanvasPanel.screenshot.pleaseWait'] - busyDlg = wx.BusyInfo(msg, canvas) - result = fsl.runTool('render', argv) - - busyDlg.Destroy() - - if result != 0: - title = strings.titles[ 'CanvasPanel.screenshot.error'] - msg = strings.messages['CanvasPanel.screenshot.error'] - msg = msg.format(' '.join(['render'] + argv)) - wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK) - class CanvasPanel(viewpanel.ViewPanel): """ @@ -186,6 +59,7 @@ class CanvasPanel(viewpanel.ViewPanel): actionz = dict({ 'screenshot' : self.screenshot, + 'showCommandLineArgs' : self.showCommandLineArgs, 'toggleOverlayList' : lambda *a: self.togglePanel( fslcontrols.OverlayListPanel), 'toggleAtlasPanel' : lambda *a: self.togglePanel( @@ -265,14 +139,18 @@ class CanvasPanel(viewpanel.ViewPanel): viewpanel.ViewPanel.destroy(self) - - def getSceneOptions(self): - return self.__opts - def screenshot(self, *a): - _takeScreenShot(self._overlayList, self._displayCtx, self) + _screenshot(self._overlayList, self._displayCtx, self) + + + def showCommandLineArgs(self, *a): + _showCommandLineArgs(self._overlayList, self._displayCtx, self) + + def getSceneOptions(self): + return self.__opts + def getCanvasPanel(self): return self.__canvasPanel @@ -375,3 +253,159 @@ class CanvasPanel(viewpanel.ViewPanel): if opts.volume == limit - 1: opts.volume = 0 else: opts.volume += 1 + + + +def _genCommandLineArgs(overlayList, displayCtx, canvas): + + argv = [] + + # Add scene options + sceneOpts = canvas.getSceneOptions() + argv += fslview_parseargs.generateSceneArgs( + overlayList, displayCtx, sceneOpts) + + # Add ortho specific options, if it's + # an orthopanel we're dealing with + if isinstance(sceneOpts, displayctx.OrthoOpts): + + xcanvas = canvas.getXCanvas() + ycanvas = canvas.getYCanvas() + zcanvas = canvas.getZCanvas() + + argv += ['--{}'.format(fslview_parseargs.ARGUMENTS[sceneOpts, + 'xcentre'][1])] + argv += ['{}'.format(c) for c in xcanvas.pos.xy] + argv += ['--{}'.format(fslview_parseargs.ARGUMENTS[sceneOpts, + 'ycentre'][1])] + argv += ['{}'.format(c) for c in ycanvas.pos.xy] + argv += ['--{}'.format(fslview_parseargs.ARGUMENTS[sceneOpts, + 'zcentre'][1])] + argv += ['{}'.format(c) for c in zcanvas.pos.xy] + + # Add display options for each overlay + for overlay in overlayList: + + fname = overlay.dataSource + ovlArgv = fslview_parseargs.generateOverlayArgs(overlay, displayCtx) + argv += [fname] + ovlArgv + + return argv + + +def _showCommandLineArgs(overlayList, displayCtx, canvas): + + args = _genCommandLineArgs(overlayList, displayCtx, canvas) + dlg = fsldlg.TextEditDialog( + canvas, + title=strings.messages[ canvas, 'showCommandLineArgs', 'title'], + message=strings.messages[canvas, 'showCommandLineArgs', 'message'], + text=' '.join(args), + icon=wx.ICON_INFORMATION, + style=(fsldlg.TED_OK | + fsldlg.TED_READONLY | + fsldlg.TED_MULTILINE | + fsldlg.TED_COPY)) + + dlg.CentreOnParent() + + dlg.ShowModal() + + +def _screenshot(overlayList, displayCtx, canvas): + + overlays = displayCtx.getOrderedOverlays() + ovlCopy = list(overlays) + + # Check to make sure that all overlays are saved + # on disk, and ask the user what they want to + # do about the ones that aren't. + for overlay in overlays: + + # Skip disabled overlays + display = displayCtx.getDisplay(overlay) + + if not display.enabled: + ovlCopy.remove(overlay) + continue + + # If the image is not saved, popup a dialog + # telling the user they must save the image + # before the screenshot can proceed + if isinstance(overlay, fslimage.Image) and not overlay.saved: + title = strings.titles[ 'CanvasPanel.screenshot.notSaved'] + msg = strings.messages['CanvasPanel.screenshot.notSaved'] + msg = msg.format(overlay.name) + + dlg = wx.MessageDialog(canvas, + message=msg, + caption=title, + style=(wx.CENTRE | + wx.YES_NO | + wx.CANCEL | + wx.ICON_QUESTION)) + dlg.SetYesNoCancelLabels( + strings.labels['CanvasPanel.screenshot.notSaved.save'], + strings.labels['CanvasPanel.screenshot.notSaved.skip'], + strings.labels['CanvasPanel.screenshot.notSaved.cancel']) + + result = dlg.ShowModal() + + # The user chose to save the image + if result == wx.ID_YES: + fsloverlay.saveOverlay(overlay) + + # The user chose to skip the image + elif result == wx.ID_NO: + ovlCopy.remove(overlay) + continue + + # the user clicked cancel, or closed the dialog + else: + return + + overlays = ovlCopy + + # Ask the user where they want + # the screenshot to be saved + dlg = wx.FileDialog(canvas, + message=strings.messages['CanvasPanel.screenshot'], + style=wx.FD_SAVE) + + if dlg.ShowModal() != wx.ID_OK: + return + + filename = dlg.GetPath() + + # Make the dialog go away before + # the screenshot gets taken + dlg.Destroy() + wx.Yield() + + width, height = canvas.getCanvasPanel().GetClientSize().Get() + + # generate command line arguments for + # a callout to render.py - start with + # the render.py specific options + argv = [] + argv += ['--outfile', filename] + argv += ['--size', '{}'.format(width), '{}'.format(height)] + argv += ['--background', '0', '0', '0', '255'] + + argv += _genCommandLineArgs(overlayList, displayCtx, canvas) + + log.debug('Generating screenshot with call ' + 'to render: {}'.format(' '.join(argv))) + + # Run render.py to generate the screenshot + msg = strings.messages['CanvasPanel.screenshot.pleaseWait'] + busyDlg = wx.BusyInfo(msg, canvas) + result = fsl.runTool('render', argv) + + busyDlg.Destroy() + + if result != 0: + title = strings.titles[ 'CanvasPanel.screenshot.error'] + msg = strings.messages['CanvasPanel.screenshot.error'] + msg = msg.format(' '.join(['render'] + argv)) + wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK) diff --git a/fsl/fslview/views/histogrampanel.py b/fsl/fslview/views/histogrampanel.py index b2e8aee8dfa191afbee02078ecada5de43be3020..d28dbe7d3074bd5b8559c2eebd98df94dfa7a1a9 100644 --- a/fsl/fslview/views/histogrampanel.py +++ b/fsl/fslview/views/histogrampanel.py @@ -15,7 +15,7 @@ import props import fsl.data.image as fslimage import fsl.data.strings as strings -import fsl.utils.messagedlg as messagedlg +import fsl.utils.dialog as fsldlg import fsl.fslview.controls as fslcontrols import plotpanel @@ -515,7 +515,8 @@ class HistogramPanel(plotpanel.PlotPanel): # calculations. Show a message while this is # happening. if baseHs is None: - hs = messagedlg.ProcessingDialog( + hs = fsldlg.ProcessingDialog( + self, strings.messages[self, 'calcHist'].format(overlay.name), loadHs).Run() diff --git a/fsl/tools/fslview_parseargs.py b/fsl/tools/fslview_parseargs.py index 699dd6a14809d0ae21abe7ae8794c7f8058b1aa0..3919c467869786cf5c8a15bef68107110839f9b7 100644 --- a/fsl/tools/fslview_parseargs.py +++ b/fsl/tools/fslview_parseargs.py @@ -216,11 +216,12 @@ ARGUMENTS = td.TypeDict({ 'ImageOpts.transform' : ('tf', 'transform'), 'ImageOpts.volume' : ('vl', 'volume'), - 'VolumeOpts.displayRange' : ('dr', 'displayRange'), - 'VolumeOpts.interpolation' : ('in', 'interp'), - 'VolumeOpts.clippingRange' : ('cr', 'clippingRange'), - 'VolumeOpts.cmap' : ('cm', 'cmap'), - 'VolumeOpts.invert' : ('ci', 'cmapInvert'), + 'VolumeOpts.displayRange' : ('dr', 'displayRange'), + 'VolumeOpts.interpolation' : ('in', 'interp'), + 'VolumeOpts.invertClipping' : ('ic', 'invertClipping'), + 'VolumeOpts.clippingRange' : ('cr', 'clippingRange'), + 'VolumeOpts.cmap' : ('cm', 'cmap'), + 'VolumeOpts.invert' : ('ci', 'cmapInvert'), 'MaskOpts.colour' : ('co', 'maskColour'), 'MaskOpts.invert' : ('mi', 'maskInvert'), @@ -301,11 +302,12 @@ HELP = td.TypeDict({ 'ImageOpts.transform' : 'Transformation', 'ImageOpts.volume' : 'Volume', - 'VolumeOpts.displayRange' : 'Display range', - 'VolumeOpts.clippingRange' : 'Clipping range', - 'VolumeOpts.cmap' : 'Colour map', - 'VolumeOpts.interpolation' : 'Interpolation', - 'VolumeOpts.invert' : 'Invert colour map', + 'VolumeOpts.displayRange' : 'Display range', + 'VolumeOpts.clippingRange' : 'Clipping range', + 'VolumeOpts.invertClipping' : 'Invert clipping', + 'VolumeOpts.cmap' : 'Colour map', + 'VolumeOpts.interpolation' : 'Interpolation', + 'VolumeOpts.invert' : 'Invert colour map', 'MaskOpts.colour' : 'Colour', 'MaskOpts.invert' : 'Invert', diff --git a/fsl/utils/dialog.py b/fsl/utils/dialog.py new file mode 100644 index 0000000000000000000000000000000000000000..0910e00a1bebf854f4b8ffe70173fedacf9775cc --- /dev/null +++ b/fsl/utils/dialog.py @@ -0,0 +1,292 @@ +#!/usr/bin/env python +# +# dialog.py - Miscellaneous dialogs. +# +# Author: Paul McCarthy <pauldmccarthy@gmail.com> +# + +import wx + +import fsl.data.strings as strings + + +class SimpleMessageDialog(wx.Dialog): + + + def __init__(self, parent=None, message=''): + + wx.Dialog.__init__(self, parent, style=wx.STAY_ON_TOP) + + self.__message = wx.StaticText( + self, + style=(wx.ST_ELLIPSIZE_MIDDLE | + wx.ALIGN_CENTRE_HORIZONTAL | + wx.ALIGN_CENTRE_VERTICAL)) + + self.__sizer = wx.BoxSizer(wx.HORIZONTAL) + self.__sizer.Add(self.__message, + border=25, + proportion=1, + flag=wx.CENTRE | wx.ALL) + + self.SetBackgroundColour((250, 250, 225)) + + self.SetSizer(self.__sizer) + self.SetMessage(message) + + + def SetMessage(self, msg): + + msg = str(msg) + + self.__message.SetLabel(msg) + + # Figure out the dialog size + # required to fit the message + dc = wx.ClientDC(self.__message) + + defWidth, defHeight = 25, 25 + msgWidth, msgHeight = dc.GetTextExtent(msg) + + if msgWidth > defWidth: width = msgWidth + 25 + else: width = defWidth + + if msgHeight > defHeight: height = msgHeight + 25 + else: height = defHeight + + self.__message.SetMinSize((width, height)) + + self.Fit() + self.Refresh() + self.Update() + + +class TimeoutDialog(SimpleMessageDialog): + + + def __init__(self, parent, message, timeout=1000): + + SimpleMessageDialog.__init__(self, parent, message) + self.__timeout = timeout + + + def __close(self): + self.Close() + self.Destroy() + + + def Show(self): + wx.CallLater(self.__timeout, self.__close) + SimpleMessageDialog.Show(self) + + + def ShowModal(self): + wx.CallLater(self.__timeout, self.__close) + SimpleMessageDialog.ShowModal(self) + + +class ProcessingDialog(SimpleMessageDialog): + + def __init__(self, parent, message, task, *args, **kwargs): + """ + + :arg message: + + :arg task: + + :arg passFuncs: + + :arg messageFunc: + + :arg errorFunc: + """ + + passFuncs = kwargs.get('passFuncs', False) + + if not passFuncs: + kwargs.pop('messageFunc', None) + kwargs.pop('errorFunc', None) + else: + kwargs['messageFunc'] = kwargs.get('messageFunc', + self.__defaultMessageFunc) + kwargs['errortFunc'] = kwargs.get('errorFunc', + self.__defaultErrorFunc) + + self.task = task + self.args = args + self.kwargs = kwargs + + SimpleMessageDialog.__init__(self, parent, message) + + + def Run(self): + + disable = wx.WindowDisabler() + + self.CentreOnParent() + self.Show() + self.SetFocus() + self.Update() + + result = self.task(*self.args, **self.kwargs) + + self.Close() + self.Destroy() + + del disable + + return result + + + def __defaultMessageFunc(self, msg): + self.SetMessage(msg) + + + def __defaultErrorFunc(self, msg, err): + err = str(err) + msg = strings.messages[self, 'error'].format(msg, err) + title = strings.titles[ self, 'error'] + wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK) + + + +TED_READONLY = 1 +TED_MULTILINE = 2 +TED_OK = 4 +TED_CANCEL = 8 +TED_OK_CANCEL = 12 +TED_COPY = 16 + + +class TextEditDialog(wx.Dialog): + """A dialog which shows an editable/selectable text field.""" + + def __init__(self, + parent, + title='', + message='', + text='', + icon=None, + style=TED_OK): + + wx.Dialog.__init__(self, + parent, + title=title, + style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) + + textStyle = 0 + if style & TED_READONLY: textStyle |= wx.TE_READONLY + if style & TED_MULTILINE: textStyle |= wx.TE_MULTILINE + + self.__message = wx.StaticText(self) + self.__textEdit = wx.TextCtrl( self, style=textStyle) + + self.__message .SetLabel(message) + self.__textEdit.SetValue(text) + + # set the min size of the text + # ctrl so it can fit a few lines + self.__textEdit.SetMinSize((-1, 120)) + + self.__ok = (-1, -1) + self.__copy = (-1, -1) + self.__cancel = (-1, -1) + self.__icon = (-1, -1) + + if icon is not None: + + icon = wx.ArtProvider.GetMessageBoxIcon(icon) + bmp = wx.EmptyBitmap(icon.GetWidth(), icon.GetHeight()) + bmp.CopyFromIcon(icon) + self.__icon = wx.StaticBitmap(self) + self.__icon.SetBitmap(bmp) + + if style & TED_OK: + self.__ok = wx.Button(self, id=wx.ID_OK) + self.__ok.Bind(wx.EVT_BUTTON, self.__onOk) + + if style & TED_CANCEL: + self.__cancel = wx.Button(self, id=wx.ID_CANCEL) + self.__cancel.Bind(wx.EVT_BUTTON, self.__onCancel) + + if style & TED_COPY: + self.__copy = wx.Button(self, label='Copy to clipboard') + self.__copy.Bind(wx.EVT_BUTTON, self.__onCopy) + + textSizer = wx.BoxSizer(wx.VERTICAL) + iconSizer = wx.BoxSizer(wx.HORIZONTAL) + btnSizer = wx.BoxSizer(wx.HORIZONTAL) + mainSizer = wx.BoxSizer(wx.VERTICAL) + + textSizer.Add(self.__message, + flag=wx.ALL | wx.CENTRE, + border=20) + textSizer.Add(self.__textEdit, + flag=wx.ALL | wx.EXPAND, + border=20, + proportion=1) + + iconSizer.Add(self.__icon, flag=wx.ALL | wx.CENTRE, border=20) + iconSizer.Add(textSizer, flag=wx.EXPAND, proportion=1) + + btnSizer.AddStretchSpacer() + btnSizer.Add(self.__ok, + flag=wx.ALL | wx.CENTRE, + border=10) + btnSizer.Add(self.__copy, + flag=wx.ALL | wx.CENTRE, + border=10) + btnSizer.Add(self.__cancel, + flag=wx.ALL | wx.CENTRE, + border=10) + btnSizer.Add((-1, 20)) + + mainSizer.Add(iconSizer, flag=wx.EXPAND, proportion=1) + mainSizer.Add(btnSizer, flag=wx.EXPAND) + + self.SetSizer(mainSizer) + self.Fit() + + + def __onOk(self, ev): + self.EndModal(wx.ID_OK) + + + def __onCancel(self, ev): + self.EndModal(wx.ID_CANCEL) + + + def __onCopy(self, ev): + text = self.__textEdit.GetValue() + + cb = wx.TheClipboard + + if cb.Open(): + cb.SetData(wx.TextDataObject(text)) + cb.Close() + td = TimeoutDialog(self, 'Copied!') + td.CentreOnParent() + td.Show() + + + def SetMessage(self, message): + self.__message.SetLabel(message) + + + def SetOkLabel(self, label): + self.__ok.SetLabel(label) + + def SetCopyLabel(self, label): + self.__copy.SetLabel(label) + + + def SetCancelLabel(self, label): + self.__cancel.SetLabel(label) + + + def SetText(self, text): + self.__textEdit.SetValue(text) + + + def GetText(self): + return self.__textEdit.GetValue() diff --git a/fsl/utils/messagedlg.py b/fsl/utils/messagedlg.py deleted file mode 100644 index e79537da69424016a9a958991f37a646828ef4f1..0000000000000000000000000000000000000000 --- a/fsl/utils/messagedlg.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python -# -# messagedlg.py - -# -# Author: Paul McCarthy <pauldmccarthy@gmail.com> -# - -import wx - -import fsl.data.strings as strings - - -class ProcessingDialog(wx.Dialog): - - def __init__(self, message, task, *args, **kwargs): - """ - - :arg message: - - :arg task: - - :arg passFuncs: - - :arg messageFunc: - - :arg errorFunc: - """ - - passFuncs = kwargs.get('passFuncs', False) - - if not passFuncs: - kwargs.pop('messageFunc', None) - kwargs.pop('errorFunc', None) - else: - kwargs['messageFunc'] = kwargs.get('messageFunc', - self.__defaultMessageFunc) - kwargs['errortFunc'] = kwargs.get('errorFunc', - self.__defaultErrorFunc) - - self.task = task - self.args = args - self.kwargs = kwargs - - wx.Dialog.__init__( - self, wx.GetApp().GetTopWindow(), - style=wx.STAY_ON_TOP) - - self.message = wx.StaticText(self, style=wx.ST_ELLIPSIZE_MIDDLE) - - self.sizer = wx.BoxSizer(wx.HORIZONTAL) - self.sizer.Add(self.message, - border=25, - proportion=1, - flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTRE) - - self.SetSizer(self.sizer) - self.SetMessage(message) - - - def Run(self): - - disable = wx.WindowDisabler() - - self.CentreOnParent() - self.Show() - self.SetFocus() - self.Update() - - result = self.task(*self.args, **self.kwargs) - - self.Close() - self.Destroy() - - del disable - - return result - - - def SetMessage(self, msg): - - msg = str(msg) - - self.message.SetLabel(msg) - - # Figure out the dialog size - # required to fit the message - dc = wx.ClientDC(self.message) - - defWidth, defHeight = 400, 100 - msgWidth, msgHeight = dc.GetTextExtent(msg) - - # Account for box sizer - # border (see __init__) - msgWidth += 50 - msgHeight += 50 - - if msgWidth > defWidth: width = msgWidth + 50 - else: width = defWidth - - if msgHeight > defHeight: height = msgHeight + 50 - else: height = defHeight - - # TODO Should I impose a - # maximum dialog width? - - self.SetSize((width, height)) - - self.Layout() - self.Refresh() - self.Update() - - - def __defaultMessageFunc(self, msg): - self.SetMessage(msg) - - - def __defaultErrorFunc(self, msg, err): - err = str(err) - msg = strings.messages[self, 'error'].format(msg, err) - title = strings.titles[ self, 'error'] - wx.MessageBox(msg, title, wx.ICON_ERROR | wx.OK)