X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8b9a4190f70909de9568f45389e7aa3ecbc66b8a..2091f5e71a1d04cf9277565121725f764d466a06:/wxPython/wx/py/editor.py diff --git a/wxPython/wx/py/editor.py b/wxPython/wx/py/editor.py index f7862bb7c5..8dc8981798 100644 --- a/wxPython/wx/py/editor.py +++ b/wxPython/wx/py/editor.py @@ -1,8 +1,841 @@ +"""PyAlaCarte and PyAlaMode editors.""" -"""Renamer stub: provides a way to drop the wx prefix from wxPython objects.""" +__author__ = "Patrick K. O'Brien " +__cvsid__ = "$Id$" +__revision__ = "$Revision$"[11:-2] -from wx import _rename -from wxPython.py import editor -_rename(globals(), editor.__dict__, modulename='py.editor') -del editor -del _rename +import wx + +from buffer import Buffer +import crust +import dispatcher +import editwindow +import frame +from shell import Shell +import version + + +class EditorFrame(frame.Frame): + """Frame containing one editor.""" + + def __init__(self, parent=None, id=-1, title='PyAlaCarte', + pos=wx.DefaultPosition, size=(800, 600), + style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE, + filename=None): + """Create EditorFrame instance.""" + frame.Frame.__init__(self, parent, id, title, pos, size, style) + self.buffers = {} + self.buffer = None # Current buffer. + self.editor = None + self._defaultText = title + ' - the tastiest Python editor.' + self._statusText = self._defaultText + self.SetStatusText(self._statusText) + self.Bind(wx.EVT_IDLE, self.OnIdle) + self._setup() + if filename: + self.bufferCreate(filename) + + def _setup(self): + """Setup prior to first buffer creation. + + Useful for subclasses.""" + pass + + def setEditor(self, editor): + self.editor = editor + self.buffer = self.editor.buffer + self.buffers[self.buffer.id] = self.buffer + + def OnAbout(self, event): + """Display an About window.""" + title = 'About PyAlaCarte' + text = 'Another fine, flaky program.' + dialog = wx.MessageDialog(self, text, title, + wx.OK | wx.ICON_INFORMATION) + dialog.ShowModal() + dialog.Destroy() + + def OnClose(self, event): + """Event handler for closing.""" + for buffer in self.buffers.values(): + self.buffer = buffer + if buffer.hasChanged(): + cancel = self.bufferSuggestSave() + if cancel and event.CanVeto(): + event.Veto() + return + self.Destroy() + + def OnIdle(self, event): + """Event handler for idle time.""" + self._updateStatus() + if hasattr(self, 'notebook'): + self._updateTabText() + self._updateTitle() + event.Skip() + + def _updateStatus(self): + """Show current status information.""" + if self.editor and hasattr(self.editor, 'getStatus'): + status = self.editor.getStatus() + text = 'File: %s | Line: %d | Column: %d' % status + else: + text = self._defaultText + if text != self._statusText: + self.SetStatusText(text) + self._statusText = text + + def _updateTabText(self): + """Show current buffer information on notebook tab.""" +## suffix = ' **' +## notebook = self.notebook +## selection = notebook.GetSelection() +## if selection == -1: +## return +## text = notebook.GetPageText(selection) +## window = notebook.GetPage(selection) +## if window.editor and window.editor.buffer.hasChanged(): +## if text.endswith(suffix): +## pass +## else: +## notebook.SetPageText(selection, text + suffix) +## else: +## if text.endswith(suffix): +## notebook.SetPageText(selection, text[:len(suffix)]) + + def _updateTitle(self): + """Show current title information.""" + title = self.GetTitle() + if self.bufferHasChanged(): + if title.startswith('* '): + pass + else: + self.SetTitle('* ' + title) + else: + if title.startswith('* '): + self.SetTitle(title[2:]) + + def hasBuffer(self): + """Return True if there is a current buffer.""" + if self.buffer: + return True + else: + return False + + def bufferClose(self): + """Close buffer.""" + if self.bufferHasChanged(): + cancel = self.bufferSuggestSave() + if cancel: + return cancel + self.bufferDestroy() + cancel = False + return cancel + + def bufferCreate(self, filename=None): + """Create new buffer.""" + self.bufferDestroy() + buffer = Buffer() + self.panel = panel = wx.Panel(parent=self, id=-1) + panel.Bind (wx.EVT_ERASE_BACKGROUND, lambda x: x) + editor = Editor(parent=panel) + panel.editor = editor + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(editor.window, 1, wx.EXPAND) + panel.SetSizer(sizer) + panel.SetAutoLayout(True) + sizer.Layout() + buffer.addEditor(editor) + buffer.open(filename) + self.setEditor(editor) + self.editor.setFocus() + self.SendSizeEvent() + + + def bufferDestroy(self): + """Destroy the current buffer.""" + if self.buffer: + for editor in self.buffer.editors.values(): + editor.destroy() + self.editor = None + del self.buffers[self.buffer.id] + self.buffer = None + self.panel.Destroy() + + + def bufferHasChanged(self): + """Return True if buffer has changed since last save.""" + if self.buffer: + return self.buffer.hasChanged() + else: + return False + + def bufferNew(self): + """Create new buffer.""" + if self.bufferHasChanged(): + cancel = self.bufferSuggestSave() + if cancel: + return cancel + self.bufferCreate() + cancel = False + return cancel + + def bufferOpen(self): + """Open file in buffer.""" + if self.bufferHasChanged(): + cancel = self.bufferSuggestSave() + if cancel: + return cancel + filedir = '' + if self.buffer and self.buffer.doc.filedir: + filedir = self.buffer.doc.filedir + result = openSingle(directory=filedir) + if result.path: + self.bufferCreate(result.path) + cancel = False + return cancel + +## def bufferPrint(self): +## """Print buffer.""" +## pass + +## def bufferRevert(self): +## """Revert buffer to version of file on disk.""" +## pass + + def bufferSave(self): + """Save buffer to its file.""" + if self.buffer.doc.filepath: + self.buffer.save() + cancel = False + else: + cancel = self.bufferSaveAs() + return cancel + + def bufferSaveAs(self): + """Save buffer to a new filename.""" + if self.bufferHasChanged() and self.buffer.doc.filepath: + cancel = self.bufferSuggestSave() + if cancel: + return cancel + filedir = '' + if self.buffer and self.buffer.doc.filedir: + filedir = self.buffer.doc.filedir + result = saveSingle(directory=filedir) + if result.path: + self.buffer.saveAs(result.path) + cancel = False + else: + cancel = True + return cancel + + def bufferSuggestSave(self): + """Suggest saving changes. Return True if user selected Cancel.""" + result = messageDialog(parent=None, + message='%s has changed.\n' + 'Would you like to save it first' + '?' % self.buffer.name, + title='Save current file?') + if result.positive: + cancel = self.bufferSave() + else: + cancel = result.text == 'Cancel' + return cancel + + def updateNamespace(self): + """Update the buffer namespace for autocompletion and calltips.""" + if self.buffer.updateNamespace(): + self.SetStatusText('Namespace updated') + else: + self.SetStatusText('Error executing, unable to update namespace') + + +class EditorNotebookFrame(EditorFrame): + """Frame containing one or more editors in a notebook.""" + + def __init__(self, parent=None, id=-1, title='PyAlaMode', + pos=wx.DefaultPosition, size=(800, 600), + style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE, + filename=None): + """Create EditorNotebookFrame instance.""" + self.notebook = None + EditorFrame.__init__(self, parent, id, title, pos, + size, style, filename) + if self.notebook: + dispatcher.connect(receiver=self._editorChange, + signal='EditorChange', sender=self.notebook) + + def _setup(self): + """Setup prior to first buffer creation. + + Called automatically by base class during init.""" + self.notebook = EditorNotebook(parent=self) + intro = 'Py %s' % version.VERSION + import imp + module = imp.new_module('__main__') + import __builtin__ + module.__dict__['__builtins__'] = __builtin__ + namespace = module.__dict__.copy() + self.crust = crust.Crust(parent=self.notebook, intro=intro, locals=namespace) + self.shell = self.crust.shell + # Override the filling so that status messages go to the status bar. + self.crust.filling.tree.setStatusText = self.SetStatusText + # Override the shell so that status messages go to the status bar. + self.shell.setStatusText = self.SetStatusText + # Fix a problem with the sash shrinking to nothing. + self.crust.filling.SetSashPosition(200) + self.notebook.AddPage(page=self.crust, text='*Shell*', select=True) + self.setEditor(self.crust.editor) + self.crust.editor.SetFocus() + + def _editorChange(self, editor): + """Editor change signal receiver.""" + self.setEditor(editor) + + def OnAbout(self, event): + """Display an About window.""" + title = 'About PyAlaMode' + text = 'Another fine, flaky program.' + dialog = wx.MessageDialog(self, text, title, + wx.OK | wx.ICON_INFORMATION) + dialog.ShowModal() + dialog.Destroy() + + def _updateTitle(self): + """Show current title information.""" + pass +## title = self.GetTitle() +## if self.bufferHasChanged(): +## if title.startswith('* '): +## pass +## else: +## self.SetTitle('* ' + title) +## else: +## if title.startswith('* '): +## self.SetTitle(title[2:]) + + def bufferCreate(self, filename=None): + """Create new buffer.""" + buffer = Buffer() + panel = wx.Panel(parent=self.notebook, id=-1) + panel.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: x) + editor = Editor(parent=panel) + panel.editor = editor + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(editor.window, 1, wx.EXPAND) + panel.SetSizer(sizer) + panel.SetAutoLayout(True) + sizer.Layout() + buffer.addEditor(editor) + buffer.open(filename) + self.setEditor(editor) + self.notebook.AddPage(page=panel, text=self.buffer.name, select=True) + self.editor.setFocus() + + def bufferDestroy(self): + """Destroy the current buffer.""" + selection = self.notebook.GetSelection() +## print "Destroy Selection:", selection + if selection > 0: # Don't destroy the PyCrust tab. + if self.buffer: + del self.buffers[self.buffer.id] + self.buffer = None # Do this before DeletePage(). + self.notebook.DeletePage(selection) + + def bufferNew(self): + """Create new buffer.""" + self.bufferCreate() + cancel = False + return cancel + + def bufferOpen(self): + """Open file in buffer.""" + filedir = '' + if self.buffer and self.buffer.doc.filedir: + filedir = self.buffer.doc.filedir + result = openMultiple(directory=filedir) + for path in result.paths: + self.bufferCreate(path) + cancel = False + return cancel + + +class EditorNotebook(wx.Notebook): + """A notebook containing a page for each editor.""" + + def __init__(self, parent): + """Create EditorNotebook instance.""" + wx.Notebook.__init__(self, parent, id=-1, style=wx.CLIP_CHILDREN) + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging, id=self.GetId()) + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId()) + self.Bind(wx.EVT_IDLE, self.OnIdle) + + def OnIdle(self, event): + """Event handler for idle time.""" + self._updateTabText() + event.Skip() + + def _updateTabText(self): + """Show current buffer display name on all but first tab.""" + size = 3 + changed = ' **' + unchanged = ' --' + selection = self.GetSelection() + if selection < 1: + return + text = self.GetPageText(selection) + window = self.GetPage(selection) + if not window.editor: + return + if text.endswith(changed) or text.endswith(unchanged): + name = text[:-size] + else: + name = text + if name != window.editor.buffer.name: + text = window.editor.buffer.name + if window.editor.buffer.hasChanged(): + if text.endswith(changed): + text = None + elif text.endswith(unchanged): + text = text[:-size] + changed + else: + text += changed + else: + if text.endswith(changed): + text = text[:-size] + unchanged + elif text.endswith(unchanged): + text = None + else: + text += unchanged + if text is not None: + self.SetPageText(selection, text) + self.Refresh() # Needed on Win98. + + def OnPageChanging(self, event): + """Page changing event handler.""" + event.Skip() + + def OnPageChanged(self, event): + """Page changed event handler.""" + new = event.GetSelection() + window = self.GetPage(new) + dispatcher.send(signal='EditorChange', sender=self, + editor=window.editor) + window.SetFocus() + event.Skip() + + +class EditorShellNotebookFrame(EditorNotebookFrame): + """Frame containing a notebook containing EditorShellNotebooks.""" + + def __init__(self, parent=None, id=-1, title='PyAlaModeTest', + pos=wx.DefaultPosition, size=(600, 400), + style=wx.DEFAULT_FRAME_STYLE, + filename=None, singlefile=False): + """Create EditorShellNotebookFrame instance.""" + self._singlefile = singlefile + EditorNotebookFrame.__init__(self, parent, id, title, pos, + size, style, filename) + + def _setup(self): + """Setup prior to first buffer creation. + + Called automatically by base class during init.""" + if not self._singlefile: + self.notebook = EditorNotebook(parent=self) + + def OnAbout(self, event): + """Display an About window.""" + title = 'About PyAlaModePlus' + text = 'Another fine, flaky program.' + dialog = wx.MessageDialog(self, text, title, + wx.OK | wx.ICON_INFORMATION) + dialog.ShowModal() + dialog.Destroy() + + def bufferCreate(self, filename=None): + """Create new buffer.""" + if self._singlefile: + self.bufferDestroy() + notebook = EditorShellNotebook(parent=self, + filename=filename) + self.notebook = notebook + else: + notebook = EditorShellNotebook(parent=self.notebook, + filename=filename) + self.setEditor(notebook.editor) + if not self._singlefile: + self.notebook.AddPage(page=notebook, text=self.buffer.name, + select=True) + self.editor.setFocus() + + def bufferDestroy(self): + """Destroy the current buffer.""" + if self.buffer: + self.editor = None + del self.buffers[self.buffer.id] + self.buffer = None # Do this before DeletePage(). + if self._singlefile: + self.notebook.Destroy() + self.notebook = None + else: + selection = self.notebook.GetSelection() +## print "Destroy Selection:", selection + self.notebook.DeletePage(selection) + + def bufferNew(self): + """Create new buffer.""" + if self._singlefile and self.bufferHasChanged(): + cancel = self.bufferSuggestSave() + if cancel: + return cancel + self.bufferCreate() + cancel = False + return cancel + + def bufferOpen(self): + """Open file in buffer.""" + if self._singlefile and self.bufferHasChanged(): + cancel = self.bufferSuggestSave() + if cancel: + return cancel + filedir = '' + if self.buffer and self.buffer.doc.filedir: + filedir = self.buffer.doc.filedir + if self._singlefile: + result = openSingle(directory=filedir) + if result.path: + self.bufferCreate(result.path) + else: + result = openMultiple(directory=filedir) + for path in result.paths: + self.bufferCreate(path) + cancel = False + return cancel + + +class EditorShellNotebook(wx.Notebook): + """A notebook containing an editor page and a shell page.""" + + def __init__(self, parent, filename=None): + """Create EditorShellNotebook instance.""" + wx.Notebook.__init__(self, parent, id=-1) + usePanels = True + if usePanels: + editorparent = editorpanel = wx.Panel(self, -1) + shellparent = shellpanel = wx.Panel(self, -1) + else: + editorparent = self + shellparent = self + self.buffer = Buffer() + self.editor = Editor(parent=editorparent) + self.buffer.addEditor(self.editor) + self.buffer.open(filename) + self.shell = Shell(parent=shellparent, locals=self.buffer.interp.locals, + style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER) + self.buffer.interp.locals.clear() + if usePanels: + self.AddPage(page=editorpanel, text='Editor', select=True) + self.AddPage(page=shellpanel, text='Shell') + # Setup sizers + editorsizer = wx.BoxSizer(wx.VERTICAL) + editorsizer.Add(self.editor.window, 1, wx.EXPAND) + editorpanel.SetSizer(editorsizer) + editorpanel.SetAutoLayout(True) + shellsizer = wx.BoxSizer(wx.VERTICAL) + shellsizer.Add(self.shell, 1, wx.EXPAND) + shellpanel.SetSizer(shellsizer) + shellpanel.SetAutoLayout(True) + else: + self.AddPage(page=self.editor.window, text='Editor', select=True) + self.AddPage(page=self.shell, text='Shell') + self.editor.setFocus() + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId()) + + def OnPageChanged(self, event): + """Page changed event handler.""" + selection = event.GetSelection() + if selection == 0: + self.editor.setFocus() + else: + self.shell.SetFocus() + event.Skip() + + def SetFocus(self): + wx.Notebook.SetFocus(self) + selection = self.GetSelection() + if selection == 0: + self.editor.setFocus() + else: + self.shell.SetFocus() + + +class Editor: + """Editor having an EditWindow.""" + + def __init__(self, parent, id=-1, pos=wx.DefaultPosition, + size=wx.DefaultSize, + style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER): + """Create Editor instance.""" + self.window = EditWindow(self, parent, id, pos, size, style) + self.id = self.window.GetId() + self.buffer = None + # Assign handlers for keyboard events. + self.window.Bind(wx.EVT_CHAR, self.OnChar) + self.window.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) + + def _setBuffer(self, buffer, text): + """Set the editor to a buffer. Private callback called by buffer.""" + self.buffer = buffer + self.autoCompleteKeys = buffer.interp.getAutoCompleteKeys() + self.clearAll() + self.setText(text) + self.emptyUndoBuffer() + self.setSavePoint() + + def destroy(self): + """Destroy all editor objects.""" + self.window.Destroy() + + def clearAll(self): + self.window.ClearAll() + + def emptyUndoBuffer(self): + self.window.EmptyUndoBuffer() + + def getStatus(self): + """Return (filepath, line, column) status tuple.""" + if self.window: + pos = self.window.GetCurrentPos() + line = self.window.LineFromPosition(pos) + 1 + col = self.window.GetColumn(pos) + if self.buffer: + name = self.buffer.doc.filepath or self.buffer.name + else: + name = '' + status = (name, line, col) + return status + else: + return ('', 0, 0) + + def getText(self): + """Return contents of editor.""" + return self.window.GetText() + + def hasChanged(self): + """Return True if contents have changed.""" + return self.window.GetModify() + + def setFocus(self): + """Set the input focus to the editor window.""" + self.window.SetFocus() + + def setSavePoint(self): + self.window.SetSavePoint() + + def setText(self, text): + """Set contents of editor.""" + self.window.SetText(text) + + def OnChar(self, event): + """Keypress event handler. + + Only receives an event if OnKeyDown calls event.Skip() for the + corresponding event.""" + + key = event.KeyCode() + if key in self.autoCompleteKeys: + # Usually the dot (period) key activates auto completion. + if self.window.AutoCompActive(): + self.window.AutoCompCancel() + self.window.ReplaceSelection('') + self.window.AddText(chr(key)) + text, pos = self.window.GetCurLine() + text = text[:pos] + if self.window.autoComplete: + self.autoCompleteShow(text) + elif key == ord('('): + # The left paren activates a call tip and cancels an + # active auto completion. + if self.window.AutoCompActive(): + self.window.AutoCompCancel() + self.window.ReplaceSelection('') + self.window.AddText('(') + text, pos = self.window.GetCurLine() + text = text[:pos] + self.autoCallTipShow(text) + else: + # Allow the normal event handling to take place. + event.Skip() + + def OnKeyDown(self, event): + """Key down event handler.""" + + key = event.KeyCode() + # If the auto-complete window is up let it do its thing. + if self.window.AutoCompActive(): + event.Skip() + return + controlDown = event.ControlDown() + altDown = event.AltDown() + shiftDown = event.ShiftDown() + # Let Ctrl-Alt-* get handled normally. + if controlDown and altDown: + event.Skip() + # Increase font size. + elif controlDown and key in (ord(']'),): + dispatcher.send(signal='FontIncrease') + # Decrease font size. + elif controlDown and key in (ord('['),): + dispatcher.send(signal='FontDecrease') + # Default font size. + elif controlDown and key in (ord('='),): + dispatcher.send(signal='FontDefault') + else: + event.Skip() + + def autoCompleteShow(self, command): + """Display auto-completion popup list.""" + list = self.buffer.interp.getAutoCompleteList(command, + includeMagic=self.window.autoCompleteIncludeMagic, + includeSingle=self.window.autoCompleteIncludeSingle, + includeDouble=self.window.autoCompleteIncludeDouble) + if list: + options = ' '.join(list) + offset = 0 + self.window.AutoCompShow(offset, options) + + def autoCallTipShow(self, command): + """Display argument spec and docstring in a popup window.""" + if self.window.CallTipActive(): + self.window.CallTipCancel() + (name, argspec, tip) = self.buffer.interp.getCallTip(command) + if tip: + dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip) + if not self.window.autoCallTip: + return + if argspec: + startpos = self.window.GetCurrentPos() + self.window.AddText(argspec + ')') + endpos = self.window.GetCurrentPos() + self.window.SetSelection(endpos, startpos) + if tip: + curpos = self.window.GetCurrentPos() + size = len(name) + tippos = curpos - (size + 1) + fallback = curpos - self.window.GetColumn(curpos) + # In case there isn't enough room, only go back to the + # fallback. + tippos = max(tippos, fallback) + self.window.CallTipShow(tippos, tip) + self.window.CallTipSetHighlight(0, size) + + +class EditWindow(editwindow.EditWindow): + """EditWindow based on StyledTextCtrl.""" + + def __init__(self, editor, parent, id=-1, pos=wx.DefaultPosition, + size=wx.DefaultSize, + style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER): + """Create EditWindow instance.""" + editwindow.EditWindow.__init__(self, parent, id, pos, size, style) + self.editor = editor + + +class DialogResults: + """DialogResults class.""" + + def __init__(self, returned): + """Create wrapper for results returned by dialog.""" + self.returned = returned + self.positive = returned in (wx.ID_OK, wx.ID_YES) + self.text = self._asString() + + + def __repr__(self): + return str(self.__dict__) + + def _asString(self): + returned = self.returned + if returned == wx.ID_OK: + return "Ok" + elif returned == wx.ID_CANCEL: + return "Cancel" + elif returned == wx.ID_YES: + return "Yes" + elif returned == wx.ID_NO: + return "No" + + +def fileDialog(parent=None, title='Open', directory='', filename='', + wildcard='All Files (*.*)|*.*', + style=wx.OPEN | wx.MULTIPLE): + """File dialog wrapper function.""" + dialog = wx.FileDialog(parent, title, directory, filename, + wildcard, style) + result = DialogResults(dialog.ShowModal()) + if result.positive: + result.paths = dialog.GetPaths() + else: + result.paths = [] + dialog.Destroy() + return result + + +def openSingle(parent=None, title='Open', directory='', filename='', + wildcard='All Files (*.*)|*.*', style=wx.OPEN): + """File dialog wrapper function.""" + dialog = wx.FileDialog(parent, title, directory, filename, + wildcard, style) + result = DialogResults(dialog.ShowModal()) + if result.positive: + result.path = dialog.GetPath() + else: + result.path = None + dialog.Destroy() + return result + + +def openMultiple(parent=None, title='Open', directory='', filename='', + wildcard='All Files (*.*)|*.*', + style=wx.OPEN | wx.MULTIPLE): + """File dialog wrapper function.""" + return fileDialog(parent, title, directory, filename, wildcard, style) + + +def saveSingle(parent=None, title='Save', directory='', filename='', + wildcard='All Files (*.*)|*.*', + style=wx.SAVE | wx.HIDE_READONLY | wx.OVERWRITE_PROMPT): + """File dialog wrapper function.""" + dialog = wx.FileDialog(parent, title, directory, filename, + wildcard, style) + result = DialogResults(dialog.ShowModal()) + if result.positive: + result.path = dialog.GetPath() + else: + result.path = None + dialog.Destroy() + return result + + +def directory(parent=None, message='Choose a directory', path='', style=0, + pos=wx.DefaultPosition, size=wx.DefaultSize): + """Dir dialog wrapper function.""" + dialog = wx.DirDialog(parent, message, path, style, pos, size) + result = DialogResults(dialog.ShowModal()) + if result.positive: + result.path = dialog.GetPath() + else: + result.path = None + dialog.Destroy() + return result + + +def messageDialog(parent=None, message='', title='Message box', + style=wx.YES_NO | wx.CANCEL | wx.CENTRE | wx.ICON_QUESTION, + pos=wx.DefaultPosition): + """Message dialog wrapper function.""" + dialog = wx.MessageDialog(parent, message, title, style, pos) + result = DialogResults(dialog.ShowModal()) + dialog.Destroy() + return result