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