]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/py/editor.py
72b356f31ec68f520f8b396f4ae63d53e398950c
[wxWidgets.git] / wxPython / wxPython / py / editor.py
1 """PyAlaCarte and PyAlaMode editors."""
2
3 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
4 __cvsid__ = "$Id$"
5 __revision__ = "$Revision$"[11:-2]
6
7 import wx
8
9 from buffer import Buffer
10 import crust
11 import dispatcher
12 import editwindow
13 import frame
14 from shell import Shell
15 import version
16
17 try:
18 True
19 except NameError:
20 True = 1==1
21 False = 1==0
22
23
24 class EditorFrame(frame.Frame):
25 """Frame containing one editor."""
26
27 def __init__(self, parent=None, id=-1, title='PyAlaCarte',
28 pos=wx.DefaultPosition, size=(800, 600),
29 style=wx.DEFAULT_FRAME_STYLE, filename=None):
30 """Create EditorFrame instance."""
31 frame.Frame.__init__(self, parent, id, title, pos, size, style)
32 self.buffers = {}
33 self.buffer = None # Current buffer.
34 self.editor = None
35 self._defaultText = title + ' - the tastiest Python editor.'
36 self._statusText = self._defaultText
37 self.SetStatusText(self._statusText)
38 wx.EVT_IDLE(self, self.OnIdle)
39 self._setup()
40 if filename:
41 self.bufferCreate(filename)
42
43 def _setup(self):
44 """Setup prior to first buffer creation.
45
46 Useful for subclasses."""
47 pass
48
49 def setEditor(self, editor):
50 self.editor = editor
51 self.buffer = self.editor.buffer
52 self.buffers[self.buffer.id] = self.buffer
53
54 def OnAbout(self, event):
55 """Display an About window."""
56 title = 'About PyAlaCarte'
57 text = 'Another fine, flaky program.'
58 dialog = wx.MessageDialog(self, text, title,
59 wx.OK | wx.ICON_INFORMATION)
60 dialog.ShowModal()
61 dialog.Destroy()
62
63 def OnClose(self, event):
64 """Event handler for closing."""
65 for buffer in self.buffers.values():
66 self.buffer = buffer
67 if buffer.hasChanged():
68 cancel = self.bufferSuggestSave()
69 if cancel and event.CanVeto():
70 event.Veto()
71 return
72 self.Destroy()
73
74 def OnIdle(self, event):
75 """Event handler for idle time."""
76 self._updateStatus()
77 if hasattr(self, 'notebook'):
78 self._updateTabText()
79 self._updateTitle()
80 event.Skip()
81
82 def _updateStatus(self):
83 """Show current status information."""
84 if self.editor and hasattr(self.editor, 'getStatus'):
85 status = self.editor.getStatus()
86 text = 'File: %s | Line: %d | Column: %d' % status
87 else:
88 text = self._defaultText
89 if text != self._statusText:
90 self.SetStatusText(text)
91 self._statusText = text
92
93 def _updateTabText(self):
94 """Show current buffer information on notebook tab."""
95 ## suffix = ' **'
96 ## notebook = self.notebook
97 ## selection = notebook.GetSelection()
98 ## if selection == -1:
99 ## return
100 ## text = notebook.GetPageText(selection)
101 ## window = notebook.GetPage(selection)
102 ## if window.editor and window.editor.buffer.hasChanged():
103 ## if text.endswith(suffix):
104 ## pass
105 ## else:
106 ## notebook.SetPageText(selection, text + suffix)
107 ## else:
108 ## if text.endswith(suffix):
109 ## notebook.SetPageText(selection, text[:len(suffix)])
110
111 def _updateTitle(self):
112 """Show current title information."""
113 title = self.GetTitle()
114 if self.bufferHasChanged():
115 if title.startswith('* '):
116 pass
117 else:
118 self.SetTitle('* ' + title)
119 else:
120 if title.startswith('* '):
121 self.SetTitle(title[2:])
122
123 def hasBuffer(self):
124 """Return True if there is a current buffer."""
125 if self.buffer:
126 return True
127 else:
128 return False
129
130 def bufferClose(self):
131 """Close buffer."""
132 if self.bufferHasChanged():
133 cancel = self.bufferSuggestSave()
134 if cancel:
135 return cancel
136 self.bufferDestroy()
137 cancel = False
138 return cancel
139
140 def bufferCreate(self, filename=None):
141 """Create new buffer."""
142 self.bufferDestroy()
143 buffer = Buffer()
144 self.panel = panel = wx.Panel(parent=self, id=-1)
145 editor = Editor(parent=panel)
146 panel.editor = editor
147 sizer = wx.BoxSizer(wx.VERTICAL)
148 sizer.Add(editor.window, 1, wx.EXPAND)
149 panel.SetSizer(sizer)
150 panel.SetAutoLayout(True)
151 sizer.Layout()
152 buffer.addEditor(editor)
153 buffer.open(filename)
154 self.setEditor(editor)
155 self.editor.setFocus()
156
157 def bufferDestroy(self):
158 """Destroy the current buffer."""
159 if self.buffer:
160 for editor in self.buffer.editors.values():
161 editor.destroy()
162 self.editor = None
163 del self.buffers[self.buffer.id]
164 self.buffer = None
165 self.panel.Destroy()
166
167 def bufferHasChanged(self):
168 """Return True if buffer has changed since last save."""
169 if self.buffer:
170 return self.buffer.hasChanged()
171 else:
172 return False
173
174 def bufferNew(self):
175 """Create new buffer."""
176 if self.bufferHasChanged():
177 cancel = self.bufferSuggestSave()
178 if cancel:
179 return cancel
180 self.bufferCreate()
181 cancel = False
182 return cancel
183
184 def bufferOpen(self):
185 """Open file in buffer."""
186 if self.bufferHasChanged():
187 cancel = self.bufferSuggestSave()
188 if cancel:
189 return cancel
190 filedir = ''
191 if self.buffer and self.buffer.doc.filedir:
192 filedir = self.buffer.doc.filedir
193 result = openSingle(directory=filedir)
194 if result.path:
195 self.bufferCreate(result.path)
196 cancel = False
197 return cancel
198
199 ## def bufferPrint(self):
200 ## """Print buffer."""
201 ## pass
202
203 ## def bufferRevert(self):
204 ## """Revert buffer to version of file on disk."""
205 ## pass
206
207 def bufferSave(self):
208 """Save buffer to its file."""
209 if self.buffer.doc.filepath:
210 self.buffer.save()
211 cancel = False
212 else:
213 cancel = self.bufferSaveAs()
214 return cancel
215
216 def bufferSaveAs(self):
217 """Save buffer to a new filename."""
218 if self.bufferHasChanged() and self.buffer.doc.filepath:
219 cancel = self.bufferSuggestSave()
220 if cancel:
221 return cancel
222 filedir = ''
223 if self.buffer and self.buffer.doc.filedir:
224 filedir = self.buffer.doc.filedir
225 result = saveSingle(directory=filedir)
226 if result.path:
227 self.buffer.saveAs(result.path)
228 cancel = False
229 else:
230 cancel = True
231 return cancel
232
233 def bufferSuggestSave(self):
234 """Suggest saving changes. Return True if user selected Cancel."""
235 result = messageDialog(parent=None,
236 message='%s has changed.\n'
237 'Would you like to save it first'
238 '?' % self.buffer.name,
239 title='Save current file?')
240 if result.positive:
241 cancel = self.bufferSave()
242 else:
243 cancel = result.text == 'Cancel'
244 return cancel
245
246 def updateNamespace(self):
247 """Update the buffer namespace for autocompletion and calltips."""
248 if self.buffer.updateNamespace():
249 self.SetStatusText('Namespace updated')
250 else:
251 self.SetStatusText('Error executing, unable to update namespace')
252
253
254 class EditorNotebookFrame(EditorFrame):
255 """Frame containing one or more editors in a notebook."""
256
257 def __init__(self, parent=None, id=-1, title='PyAlaMode',
258 pos=wx.DefaultPosition, size=(800, 600),
259 style=wx.DEFAULT_FRAME_STYLE, filename=None):
260 """Create EditorNotebookFrame instance."""
261 self.notebook = None
262 EditorFrame.__init__(self, parent, id, title, pos,
263 size, style, filename)
264 if self.notebook:
265 dispatcher.connect(receiver=self._editorChange,
266 signal='EditorChange', sender=self.notebook)
267
268 def _setup(self):
269 """Setup prior to first buffer creation.
270
271 Called automatically by base class during init."""
272 self.notebook = EditorNotebook(parent=self)
273 intro = 'Py %s' % version.VERSION
274 import imp
275 module = imp.new_module('__main__')
276 import __builtin__
277 module.__dict__['__builtins__'] = __builtin__
278 namespace = module.__dict__.copy()
279 self.crust = crust.Crust(parent=self.notebook, intro=intro, locals=namespace)
280 self.shell = self.crust.shell
281 # Override the filling so that status messages go to the status bar.
282 self.crust.filling.tree.setStatusText = self.SetStatusText
283 # Override the shell so that status messages go to the status bar.
284 self.shell.setStatusText = self.SetStatusText
285 # Fix a problem with the sash shrinking to nothing.
286 self.crust.filling.SetSashPosition(200)
287 self.notebook.AddPage(page=self.crust, text='*Shell*', select=True)
288 self.setEditor(self.crust.editor)
289 self.crust.editor.SetFocus()
290
291 def _editorChange(self, editor):
292 """Editor change signal receiver."""
293 self.setEditor(editor)
294
295 def OnAbout(self, event):
296 """Display an About window."""
297 title = 'About PyAlaMode'
298 text = 'Another fine, flaky program.'
299 dialog = wx.MessageDialog(self, text, title,
300 wx.OK | wx.ICON_INFORMATION)
301 dialog.ShowModal()
302 dialog.Destroy()
303
304 def _updateTitle(self):
305 """Show current title information."""
306 pass
307 ## title = self.GetTitle()
308 ## if self.bufferHasChanged():
309 ## if title.startswith('* '):
310 ## pass
311 ## else:
312 ## self.SetTitle('* ' + title)
313 ## else:
314 ## if title.startswith('* '):
315 ## self.SetTitle(title[2:])
316
317 def bufferCreate(self, filename=None):
318 """Create new buffer."""
319 buffer = Buffer()
320 panel = wx.Panel(parent=self.notebook, id=-1)
321 editor = Editor(parent=panel)
322 panel.editor = editor
323 sizer = wx.BoxSizer(wx.VERTICAL)
324 sizer.Add(editor.window, 1, wx.EXPAND)
325 panel.SetSizer(sizer)
326 panel.SetAutoLayout(True)
327 sizer.Layout()
328 buffer.addEditor(editor)
329 buffer.open(filename)
330 self.setEditor(editor)
331 self.notebook.AddPage(page=panel, text=self.buffer.name, select=True)
332 self.editor.setFocus()
333
334 def bufferDestroy(self):
335 """Destroy the current buffer."""
336 selection = self.notebook.GetSelection()
337 ## print "Destroy Selection:", selection
338 if selection > 0: # Don't destroy the PyCrust tab.
339 if self.buffer:
340 del self.buffers[self.buffer.id]
341 self.buffer = None # Do this before DeletePage().
342 self.notebook.DeletePage(selection)
343
344 def bufferNew(self):
345 """Create new buffer."""
346 self.bufferCreate()
347 cancel = False
348 return cancel
349
350 def bufferOpen(self):
351 """Open file in buffer."""
352 filedir = ''
353 if self.buffer and self.buffer.doc.filedir:
354 filedir = self.buffer.doc.filedir
355 result = openMultiple(directory=filedir)
356 for path in result.paths:
357 self.bufferCreate(path)
358 cancel = False
359 return cancel
360
361
362 class EditorNotebook(wx.Notebook):
363 """A notebook containing a page for each editor."""
364
365 def __init__(self, parent):
366 """Create EditorNotebook instance."""
367 wx.Notebook.__init__(self, parent, id=-1)
368 wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(),
369 self.OnPageChanging)
370 wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(),
371 self.OnPageChanged)
372 wx.EVT_IDLE(self, self.OnIdle)
373
374 def OnIdle(self, event):
375 """Event handler for idle time."""
376 self._updateTabText()
377 event.Skip()
378
379 def _updateTabText(self):
380 """Show current buffer display name on all but first tab."""
381 size = 3
382 changed = ' **'
383 unchanged = ' --'
384 selection = self.GetSelection()
385 if selection < 1:
386 return
387 text = self.GetPageText(selection)
388 window = self.GetPage(selection)
389 if not window.editor:
390 return
391 if text.endswith(changed) or text.endswith(unchanged):
392 name = text[:-size]
393 else:
394 name = text
395 if name != window.editor.buffer.name:
396 text = window.editor.buffer.name
397 if window.editor.buffer.hasChanged():
398 if text.endswith(changed):
399 text = None
400 elif text.endswith(unchanged):
401 text = text[:-size] + changed
402 else:
403 text += changed
404 else:
405 if text.endswith(changed):
406 text = text[:-size] + unchanged
407 elif text.endswith(unchanged):
408 text = None
409 else:
410 text += unchanged
411 if text is not None:
412 self.SetPageText(selection, text)
413 self.Refresh() # Needed on Win98.
414
415 def OnPageChanging(self, event):
416 """Page changing event handler."""
417 event.Skip()
418
419 def OnPageChanged(self, event):
420 """Page changed event handler."""
421 new = event.GetSelection()
422 window = self.GetPage(new)
423 dispatcher.send(signal='EditorChange', sender=self,
424 editor=window.editor)
425 window.SetFocus()
426 event.Skip()
427
428
429 class EditorShellNotebookFrame(EditorNotebookFrame):
430 """Frame containing a notebook containing EditorShellNotebooks."""
431
432 def __init__(self, parent=None, id=-1, title='PyAlaModeTest',
433 pos=wx.DefaultPosition, size=(600, 400),
434 style=wx.DEFAULT_FRAME_STYLE,
435 filename=None, singlefile=False):
436 """Create EditorShellNotebookFrame instance."""
437 self._singlefile = singlefile
438 EditorNotebookFrame.__init__(self, parent, id, title, pos,
439 size, style, filename)
440
441 def _setup(self):
442 """Setup prior to first buffer creation.
443
444 Called automatically by base class during init."""
445 if not self._singlefile:
446 self.notebook = EditorNotebook(parent=self)
447
448 def OnAbout(self, event):
449 """Display an About window."""
450 title = 'About PyAlaModePlus'
451 text = 'Another fine, flaky program.'
452 dialog = wx.MessageDialog(self, text, title,
453 wx.OK | wx.ICON_INFORMATION)
454 dialog.ShowModal()
455 dialog.Destroy()
456
457 def bufferCreate(self, filename=None):
458 """Create new buffer."""
459 if self._singlefile:
460 self.bufferDestroy()
461 notebook = EditorShellNotebook(parent=self,
462 filename=filename)
463 self.notebook = notebook
464 else:
465 notebook = EditorShellNotebook(parent=self.notebook,
466 filename=filename)
467 self.setEditor(notebook.editor)
468 if not self._singlefile:
469 self.notebook.AddPage(page=notebook, text=self.buffer.name,
470 select=True)
471 self.editor.setFocus()
472
473 def bufferDestroy(self):
474 """Destroy the current buffer."""
475 if self.buffer:
476 self.editor = None
477 del self.buffers[self.buffer.id]
478 self.buffer = None # Do this before DeletePage().
479 if self._singlefile:
480 self.notebook.Destroy()
481 self.notebook = None
482 else:
483 selection = self.notebook.GetSelection()
484 ## print "Destroy Selection:", selection
485 self.notebook.DeletePage(selection)
486
487 def bufferNew(self):
488 """Create new buffer."""
489 if self._singlefile and self.bufferHasChanged():
490 cancel = self.bufferSuggestSave()
491 if cancel:
492 return cancel
493 self.bufferCreate()
494 cancel = False
495 return cancel
496
497 def bufferOpen(self):
498 """Open file in buffer."""
499 if self._singlefile and self.bufferHasChanged():
500 cancel = self.bufferSuggestSave()
501 if cancel:
502 return cancel
503 filedir = ''
504 if self.buffer and self.buffer.doc.filedir:
505 filedir = self.buffer.doc.filedir
506 if self._singlefile:
507 result = openSingle(directory=filedir)
508 if result.path:
509 self.bufferCreate(result.path)
510 else:
511 result = openMultiple(directory=filedir)
512 for path in result.paths:
513 self.bufferCreate(path)
514 cancel = False
515 return cancel
516
517
518 class EditorShellNotebook(wx.Notebook):
519 """A notebook containing an editor page and a shell page."""
520
521 def __init__(self, parent, filename=None):
522 """Create EditorShellNotebook instance."""
523 wx.Notebook.__init__(self, parent, id=-1)
524 usePanels = True
525 if usePanels:
526 editorparent = editorpanel = wx.Panel(self, -1)
527 shellparent = shellpanel = wx.Panel(self, -1)
528 else:
529 editorparent = self
530 shellparent = self
531 self.buffer = Buffer()
532 self.editor = Editor(parent=editorparent)
533 self.buffer.addEditor(self.editor)
534 self.buffer.open(filename)
535 self.shell = Shell(parent=shellparent, locals=self.buffer.interp.locals,
536 style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER)
537 self.buffer.interp.locals.clear()
538 if usePanels:
539 self.AddPage(page=editorpanel, text='Editor', select=True)
540 self.AddPage(page=shellpanel, text='Shell')
541 # Setup sizers
542 editorsizer = wx.BoxSizer(wx.VERTICAL)
543 editorsizer.Add(self.editor.window, 1, wx.EXPAND)
544 editorpanel.SetSizer(editorsizer)
545 editorpanel.SetAutoLayout(True)
546 shellsizer = wx.BoxSizer(wx.VERTICAL)
547 shellsizer.Add(self.shell, 1, wx.EXPAND)
548 shellpanel.SetSizer(shellsizer)
549 shellpanel.SetAutoLayout(True)
550 else:
551 self.AddPage(page=self.editor.window, text='Editor', select=True)
552 self.AddPage(page=self.shell, text='Shell')
553 self.editor.setFocus()
554 wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged)
555
556 def OnPageChanged(self, event):
557 """Page changed event handler."""
558 selection = event.GetSelection()
559 if selection == 0:
560 self.editor.setFocus()
561 else:
562 self.shell.SetFocus()
563 event.Skip()
564
565 def SetFocus(self):
566 wx.Notebook.SetFocus(self)
567 selection = self.GetSelection()
568 if selection == 0:
569 self.editor.setFocus()
570 else:
571 self.shell.SetFocus()
572
573
574 class Editor:
575 """Editor having an EditWindow."""
576
577 def __init__(self, parent, id=-1, pos=wx.DefaultPosition,
578 size=wx.DefaultSize,
579 style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
580 """Create Editor instance."""
581 self.window = EditWindow(self, parent, id, pos, size, style)
582 self.id = self.window.GetId()
583 self.buffer = None
584 # Assign handlers for keyboard events.
585 wx.EVT_CHAR(self.window, self.OnChar)
586 wx.EVT_KEY_DOWN(self.window, self.OnKeyDown)
587
588 def _setBuffer(self, buffer, text):
589 """Set the editor to a buffer. Private callback called by buffer."""
590 self.buffer = buffer
591 self.autoCompleteKeys = buffer.interp.getAutoCompleteKeys()
592 self.clearAll()
593 self.setText(text)
594 self.emptyUndoBuffer()
595 self.setSavePoint()
596
597 def destroy(self):
598 """Destroy all editor objects."""
599 self.window.Destroy()
600
601 def clearAll(self):
602 self.window.ClearAll()
603
604 def emptyUndoBuffer(self):
605 self.window.EmptyUndoBuffer()
606
607 def getStatus(self):
608 """Return (filepath, line, column) status tuple."""
609 pos = self.window.GetCurrentPos()
610 line = self.window.LineFromPosition(pos) + 1
611 col = self.window.GetColumn(pos)
612 if self.buffer:
613 name = self.buffer.doc.filepath or self.buffer.name
614 else:
615 name = ''
616 status = (name, line, col)
617 return status
618
619 def getText(self):
620 """Return contents of editor."""
621 return self.window.GetText()
622
623 def hasChanged(self):
624 """Return True if contents have changed."""
625 return self.window.GetModify()
626
627 def setFocus(self):
628 """Set the input focus to the editor window."""
629 self.window.SetFocus()
630
631 def setSavePoint(self):
632 self.window.SetSavePoint()
633
634 def setText(self, text):
635 """Set contents of editor."""
636 self.window.SetText(text)
637
638 def OnChar(self, event):
639 """Keypress event handler.
640
641 Only receives an event if OnKeyDown calls event.Skip() for the
642 corresponding event."""
643
644 key = event.KeyCode()
645 if key in self.autoCompleteKeys:
646 # Usually the dot (period) key activates auto completion.
647 if self.window.AutoCompActive():
648 self.window.AutoCompCancel()
649 self.window.ReplaceSelection('')
650 self.window.AddText(chr(key))
651 text, pos = self.window.GetCurLine()
652 text = text[:pos]
653 if self.window.autoComplete:
654 self.autoCompleteShow(text)
655 elif key == ord('('):
656 # The left paren activates a call tip and cancels an
657 # active auto completion.
658 if self.window.AutoCompActive():
659 self.window.AutoCompCancel()
660 self.window.ReplaceSelection('')
661 self.window.AddText('(')
662 text, pos = self.window.GetCurLine()
663 text = text[:pos]
664 self.autoCallTipShow(text)
665 else:
666 # Allow the normal event handling to take place.
667 event.Skip()
668
669 def OnKeyDown(self, event):
670 """Key down event handler."""
671
672 key = event.KeyCode()
673 # If the auto-complete window is up let it do its thing.
674 if self.window.AutoCompActive():
675 event.Skip()
676 return
677 controlDown = event.ControlDown()
678 altDown = event.AltDown()
679 shiftDown = event.ShiftDown()
680 # Let Ctrl-Alt-* get handled normally.
681 if controlDown and altDown:
682 event.Skip()
683 # Increase font size.
684 elif controlDown and key in (ord(']'),):
685 dispatcher.send(signal='FontIncrease')
686 # Decrease font size.
687 elif controlDown and key in (ord('['),):
688 dispatcher.send(signal='FontDecrease')
689 # Default font size.
690 elif controlDown and key in (ord('='),):
691 dispatcher.send(signal='FontDefault')
692 else:
693 event.Skip()
694
695 def autoCompleteShow(self, command):
696 """Display auto-completion popup list."""
697 list = self.buffer.interp.getAutoCompleteList(command,
698 includeMagic=self.window.autoCompleteIncludeMagic,
699 includeSingle=self.window.autoCompleteIncludeSingle,
700 includeDouble=self.window.autoCompleteIncludeDouble)
701 if list:
702 options = ' '.join(list)
703 offset = 0
704 self.window.AutoCompShow(offset, options)
705
706 def autoCallTipShow(self, command):
707 """Display argument spec and docstring in a popup window."""
708 if self.window.CallTipActive():
709 self.window.CallTipCancel()
710 (name, argspec, tip) = self.buffer.interp.getCallTip(command)
711 if tip:
712 dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip)
713 if not self.window.autoCallTip:
714 return
715 if argspec:
716 startpos = self.window.GetCurrentPos()
717 self.window.AddText(argspec + ')')
718 endpos = self.window.GetCurrentPos()
719 self.window.SetSelection(endpos, startpos)
720 if tip:
721 curpos = self.window.GetCurrentPos()
722 size = len(name)
723 tippos = curpos - (size + 1)
724 fallback = curpos - self.window.GetColumn(curpos)
725 # In case there isn't enough room, only go back to the
726 # fallback.
727 tippos = max(tippos, fallback)
728 self.window.CallTipShow(tippos, tip)
729 self.window.CallTipSetHighlight(0, size)
730
731
732 class EditWindow(editwindow.EditWindow):
733 """EditWindow based on StyledTextCtrl."""
734
735 def __init__(self, editor, parent, id=-1, pos=wx.DefaultPosition,
736 size=wx.DefaultSize,
737 style=wx.CLIP_CHILDREN | wx.SUNKEN_BORDER):
738 """Create EditWindow instance."""
739 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
740 self.editor = editor
741
742
743 class DialogResults:
744 """DialogResults class."""
745
746 def __init__(self, returned):
747 """Create wrapper for results returned by dialog."""
748 self.returned = returned
749 self.positive = returned in (wx.ID_OK, wx.ID_YES)
750 self.text = self._asString()
751
752
753 def __repr__(self):
754 return str(self.__dict__)
755
756 def _asString(self):
757 returned = self.returned
758 if returned == wx.ID_OK:
759 return "Ok"
760 elif returned == wx.ID_CANCEL:
761 return "Cancel"
762 elif returned == wx.ID_YES:
763 return "Yes"
764 elif returned == wx.ID_NO:
765 return "No"
766
767
768 def fileDialog(parent=None, title='Open', directory='', filename='',
769 wildcard='All Files (*.*)|*.*',
770 style=wx.OPEN | wx.MULTIPLE):
771 """File dialog wrapper function."""
772 dialog = wx.FileDialog(parent, title, directory, filename,
773 wildcard, style)
774 result = DialogResults(dialog.ShowModal())
775 if result.positive:
776 result.paths = dialog.GetPaths()
777 else:
778 result.paths = []
779 dialog.Destroy()
780 return result
781
782
783 def openSingle(parent=None, title='Open', directory='', filename='',
784 wildcard='All Files (*.*)|*.*', style=wx.OPEN):
785 """File dialog wrapper function."""
786 dialog = wx.FileDialog(parent, title, directory, filename,
787 wildcard, style)
788 result = DialogResults(dialog.ShowModal())
789 if result.positive:
790 result.path = dialog.GetPath()
791 else:
792 result.path = None
793 dialog.Destroy()
794 return result
795
796
797 def openMultiple(parent=None, title='Open', directory='', filename='',
798 wildcard='All Files (*.*)|*.*',
799 style=wx.OPEN | wx.MULTIPLE):
800 """File dialog wrapper function."""
801 return fileDialog(parent, title, directory, filename, wildcard, style)
802
803
804 def saveSingle(parent=None, title='Save', directory='', filename='',
805 wildcard='All Files (*.*)|*.*',
806 style=wx.SAVE | wx.HIDE_READONLY | wx.OVERWRITE_PROMPT):
807 """File dialog wrapper function."""
808 dialog = wx.FileDialog(parent, title, directory, filename,
809 wildcard, style)
810 result = DialogResults(dialog.ShowModal())
811 if result.positive:
812 result.path = dialog.GetPath()
813 else:
814 result.path = None
815 dialog.Destroy()
816 return result
817
818
819 def directory(parent=None, message='Choose a directory', path='', style=0,
820 pos=wx.DefaultPosition, size=wx.DefaultSize):
821 """Dir dialog wrapper function."""
822 dialog = wx.DirDialog(parent, message, path, style, pos, size)
823 result = DialogResults(dialog.ShowModal())
824 if result.positive:
825 result.path = dialog.GetPath()
826 else:
827 result.path = None
828 dialog.Destroy()
829 return result
830
831
832 def messageDialog(parent=None, message='', title='Message box',
833 style=wx.YES_NO | wx.CANCEL | wx.CENTRE | wx.ICON_QUESTION,
834 pos=wx.DefaultPosition):
835 """Message dialog wrapper function."""
836 dialog = wx.MessageDialog(parent, message, title, style, pos)
837 result = DialogResults(dialog.ShowModal())
838 dialog.Destroy()
839 return result