]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/docview.py
Take src x, y into account when blitting with alpha
[wxWidgets.git] / wxPython / wx / lib / docview.py
1 #----------------------------------------------------------------------------
2 # Name: docview.py
3 # Purpose: Port of the wxWindows docview classes
4 #
5 # Author: Peter Yared
6 #
7 # Created: 5/15/03
8 # CVS-ID: $Id$
9 # Copyright: (c) 2003-2005 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al)
10 # License: wxWindows license
11 #----------------------------------------------------------------------------
12
13
14 import os
15 import os.path
16 import wx
17 import sys
18 _ = wx.GetTranslation
19
20
21 #----------------------------------------------------------------------
22 # docview globals
23 #----------------------------------------------------------------------
24
25 DOC_SDI = 1
26 DOC_MDI = 2
27 DOC_NEW = 4
28 DOC_SILENT = 8
29 DOC_OPEN_ONCE = 16
30 DEFAULT_DOCMAN_FLAGS = DOC_SDI & DOC_OPEN_ONCE
31
32 TEMPLATE_VISIBLE = 1
33 TEMPLATE_INVISIBLE = 2
34 DEFAULT_TEMPLATE_FLAGS = TEMPLATE_VISIBLE
35
36 MAX_FILE_HISTORY = 9
37
38
39 #----------------------------------------------------------------------
40 # Convenience functions from wxWindows used in docview
41 #----------------------------------------------------------------------
42
43
44 def FileNameFromPath(path):
45 """
46 Returns the filename for a full path.
47 """
48 return os.path.split(path)[1]
49
50 def FindExtension(path):
51 """
52 Returns the extension of a filename for a full path.
53 """
54 return os.path.splitext(path)[1].lower()
55
56 def FileExists(path):
57 """
58 Returns True if the path exists.
59 """
60 return os.path.isfile(path)
61
62 def PathOnly(path):
63 """
64 Returns the path of a full path without the filename.
65 """
66 return os.path.split(path)[0]
67
68
69 #----------------------------------------------------------------------
70 # Document/View Classes
71 #----------------------------------------------------------------------
72
73
74 class Document(wx.EvtHandler):
75 """
76 The document class can be used to model an application's file-based data. It
77 is part of the document/view framework supported by wxWindows, and cooperates
78 with the wxView, wxDocTemplate and wxDocManager classes.
79
80 Note this wxPython version also keeps track of the modification date of the
81 document and if it changes on disk outside of the application, we will warn the
82 user before saving to avoid clobbering the file.
83 """
84
85
86 def __init__(self, parent = None):
87 """
88 Constructor. Define your own default constructor to initialize
89 application-specific data.
90 """
91 wx.EvtHandler.__init__(self)
92
93 self._documentParent = parent
94 self._documentTemplate = None
95 self._commandProcessor = None
96 self._savedYet = False
97 self._writeable = True
98
99 self._documentTitle = None
100 self._documentFile = None
101 self._documentTypeName = None
102 self._documentModified = False
103 self._documentModificationDate = None
104 self._documentViews = []
105
106
107 def ProcessEvent(self, event):
108 """
109 Processes an event, searching event tables and calling zero or more
110 suitable event handler function(s). Note that the ProcessEvent
111 method is called from the wxPython docview framework directly since
112 wxPython does not have a virtual ProcessEvent function.
113 """
114 return False
115
116
117 def GetFilename(self):
118 """
119 Gets the filename associated with this document, or "" if none is
120 associated.
121 """
122 return self._documentFile
123
124
125 def GetTitle(self):
126 """
127 Gets the title for this document. The document title is used for an
128 associated frame (if any), and is usually constructed by the framework
129 from the filename.
130 """
131 return self._documentTitle
132
133
134 def SetTitle(self, title):
135 """
136 Sets the title for this document. The document title is used for an
137 associated frame (if any), and is usually constructed by the framework
138 from the filename.
139 """
140 self._documentTitle = title
141
142
143 def GetDocumentName(self):
144 """
145 The document type name given to the wxDocTemplate constructor,
146 copied to this document when the document is created. If several
147 document templates are created that use the same document type, this
148 variable is used in wxDocManager::CreateView to collate a list of
149 alternative view types that can be used on this kind of document.
150 """
151 return self._documentTypeName
152
153
154 def SetDocumentName(self, name):
155 """
156 Sets he document type name given to the wxDocTemplate constructor,
157 copied to this document when the document is created. If several
158 document templates are created that use the same document type, this
159 variable is used in wxDocManager::CreateView to collate a list of
160 alternative view types that can be used on this kind of document. Do
161 not change the value of this variable.
162 """
163 self._documentTypeName = name
164
165
166 def GetDocumentSaved(self):
167 """
168 Returns True if the document has been saved. This method has been
169 added to wxPython and is not in wxWindows.
170 """
171 return self._savedYet
172
173
174 def SetDocumentSaved(self, saved = True):
175 """
176 Sets whether the document has been saved. This method has been
177 added to wxPython and is not in wxWindows.
178 """
179 self._savedYet = saved
180
181
182 def GetCommandProcessor(self):
183 """
184 Returns the command processor associated with this document.
185 """
186 return self._commandProcessor
187
188
189 def SetCommandProcessor(self, processor):
190 """
191 Sets the command processor to be used for this document. The document
192 will then be responsible for its deletion. Normally you should not
193 call this; override OnCreateCommandProcessor instead.
194 """
195 self._commandProcessor = processor
196
197
198 def IsModified(self):
199 """
200 Returns true if the document has been modified since the last save,
201 false otherwise. You may need to override this if your document view
202 maintains its own record of being modified (for example if using
203 wxTextWindow to view and edit the document).
204 """
205 return self._documentModified
206
207
208 def Modify(self, modify):
209 """
210 Call with true to mark the document as modified since the last save,
211 false otherwise. You may need to override this if your document view
212 maintains its own record of being modified (for example if using
213 xTextWindow to view and edit the document).
214 """
215 self._documentModified = modify
216
217
218 def SetDocumentModificationDate(self):
219 """
220 Saves the file's last modification date.
221 This is used to check if the file has been modified outside of the application.
222 This method has been added to wxPython and is not in wxWindows.
223 """
224 self._documentModificationDate = os.path.getmtime(self.GetFilename())
225
226
227 def GetDocumentModificationDate(self):
228 """
229 Returns the file's modification date when it was loaded from disk.
230 This is used to check if the file has been modified outside of the application.
231 This method has been added to wxPython and is not in wxWindows.
232 """
233 return self._documentModificationDate
234
235
236 def GetViews(self):
237 """
238 Returns the list whose elements are the views on the document.
239 """
240 return self._documentViews
241
242
243 def GetDocumentTemplate(self):
244 """
245 Returns the template that created the document.
246 """
247 return self._documentTemplate
248
249
250 def SetDocumentTemplate(self, template):
251 """
252 Sets the template that created the document. Should only be called by
253 the framework.
254 """
255 self._documentTemplate = template
256
257
258 def DeleteContents(self):
259 """
260 Deletes the contents of the document. Override this method as
261 necessary.
262 """
263 return True
264
265
266 def Destroy(self):
267 """
268 Destructor. Removes itself from the document manager.
269 """
270 self.DeleteContents()
271 if self.GetDocumentManager():
272 self.GetDocumentManager().RemoveDocument(self)
273 wx.EvtHandler.Destroy(self)
274
275
276 def Close(self):
277 """
278 Closes the document, by calling OnSaveModified and then (if this true)
279 OnCloseDocument. This does not normally delete the document object:
280 use DeleteAllViews to do this implicitly.
281 """
282 if self.OnSaveModified():
283 if self.OnCloseDocument():
284 return True
285 else:
286 return False
287 else:
288 return False
289
290
291 def OnCloseDocument(self):
292 """
293 The default implementation calls DeleteContents (an empty
294 implementation) sets the modified flag to false. Override this to
295 supply additional behaviour when the document is closed with Close.
296 """
297 self.NotifyClosing()
298 self.DeleteContents()
299 self.Modify(False)
300 return True
301
302
303 def DeleteAllViews(self):
304 """
305 Calls wxView.Close and deletes each view. Deleting the final view will
306 implicitly delete the document itself, because the wxView destructor
307 calls RemoveView. This in turns calls wxDocument::OnChangedViewList,
308 whose default implemention is to save and delete the document if no
309 views exist.
310 """
311 manager = self.GetDocumentManager()
312 for view in self._documentViews:
313 if not view.Close():
314 return False
315 if self in manager.GetDocuments():
316 self.Destroy()
317 return True
318
319
320 def GetFirstView(self):
321 """
322 A convenience function to get the first view for a document, because
323 in many cases a document will only have a single view.
324 """
325 if len(self._documentViews) == 0:
326 return None
327 return self._documentViews[0]
328
329
330 def GetDocumentManager(self):
331 """
332 Returns the associated document manager.
333 """
334 if self._documentTemplate:
335 return self._documentTemplate.GetDocumentManager()
336 return None
337
338
339 def OnNewDocument(self):
340 """
341 The default implementation calls OnSaveModified and DeleteContents,
342 makes a default title for the document, and notifies the views that
343 the filename (in fact, the title) has changed.
344 """
345 if not self.OnSaveModified() or not self.OnCloseDocument():
346 return False
347 self.DeleteContents()
348 self.Modify(False)
349 self.SetDocumentSaved(False)
350 name = self.GetDocumentManager().MakeDefaultName()
351 self.SetTitle(name)
352 self.SetFilename(name, notifyViews = True)
353
354
355 def Save(self):
356 """
357 Saves the document by calling OnSaveDocument if there is an associated
358 filename, or SaveAs if there is no filename.
359 """
360 if not self.IsModified(): # and self._savedYet: This was here, but if it is not modified who cares if it hasn't been saved yet?
361 return True
362
363 """ check for file modification outside of application """
364 if os.path.exists(self.GetFilename()) and os.path.getmtime(self.GetFilename()) != self.GetDocumentModificationDate():
365 msgTitle = wx.GetApp().GetAppName()
366 if not msgTitle:
367 msgTitle = _("Application")
368 res = wx.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()),
369 msgTitle,
370 wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
371 self.GetDocumentWindow())
372
373 if res == wx.NO:
374 return True
375 elif res == wx.YES:
376 pass
377 else: # elif res == wx.CANCEL:
378 return False
379
380 if not self._documentFile or not self._savedYet:
381 return self.SaveAs()
382 return self.OnSaveDocument(self._documentFile)
383
384
385 def SaveAs(self):
386 """
387 Prompts the user for a file to save to, and then calls OnSaveDocument.
388 """
389 docTemplate = self.GetDocumentTemplate()
390 if not docTemplate:
391 return False
392
393 descr = docTemplate.GetDescription() + _(" (") + docTemplate.GetFileFilter() + _(") |") + docTemplate.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
394 filename = wx.FileSelector(_("Save As"),
395 docTemplate.GetDirectory(),
396 FileNameFromPath(self.GetFilename()),
397 docTemplate.GetDefaultExtension(),
398 wildcard = descr,
399 flags = wx.SAVE | wx.OVERWRITE_PROMPT,
400 parent = self.GetDocumentWindow())
401 if filename == "":
402 return False
403
404 name, ext = os.path.splitext(filename)
405 if ext == "":
406 filename += '.' + docTemplate.GetDefaultExtension()
407
408 self.SetFilename(filename)
409 self.SetTitle(FileNameFromPath(filename))
410
411 for view in self._documentViews:
412 view.OnChangeFilename()
413
414 if not self.OnSaveDocument(filename):
415 return False
416
417 if docTemplate.FileMatchesTemplate(filename):
418 self.GetDocumentManager().AddFileToHistory(filename)
419
420 return True
421
422
423 def OnSaveDocument(self, filename):
424 """
425 Constructs an output file for the given filename (which must
426 not be empty), and calls SaveObject. If SaveObject returns true, the
427 document is set to unmodified; otherwise, an error message box is
428 displayed.
429 """
430 if not filename:
431 return False
432
433 msgTitle = wx.GetApp().GetAppName()
434 if not msgTitle:
435 msgTitle = _("File Error")
436
437 backupFilename = None
438 try:
439 # if current file exists, move it to a safe place temporarily
440 if os.path.exists(filename):
441
442 # Check if read-only.
443 if not os.access(filename, os.W_OK):
444 wx.MessageBox("Could not save '%s'. No write permission to overwrite existing file." % FileNameFromPath(filename),
445 msgTitle,
446 wx.OK | wx.ICON_EXCLAMATION,
447 self.GetDocumentWindow())
448 return False
449
450 i = 1
451 backupFilename = "%s.bak%s" % (filename, i)
452 while os.path.exists(backupFilename):
453 i += 1
454 backupFilename = "%s.bak%s" % (filename, i)
455 os.rename(filename, backupFilename)
456
457 fileObject = file(filename, 'w')
458 self.SaveObject(fileObject)
459
460 if backupFilename:
461 os.remove(backupFilename)
462 except:
463 # save failed, restore old file
464 if backupFilename:
465 os.remove(filename)
466 os.rename(backupFilename, filename)
467 self.SetDocumentModificationDate()
468
469 wx.MessageBox("Could not save '%s'. %s" % (FileNameFromPath(filename), sys.exc_value),
470 msgTitle,
471 wx.OK | wx.ICON_EXCLAMATION,
472 self.GetDocumentWindow())
473 return False
474
475 self.SetFilename(filename, True)
476 self.Modify(False)
477 self.SetDocumentModificationDate()
478 self.SetDocumentSaved(True)
479 #if wx.Platform == '__WXMAC__': # Not yet implemented in wxPython
480 # wx.FileName(file).MacSetDefaultTypeAndCreator()
481 return True
482
483
484 def OnOpenDocument(self, filename):
485 """
486 Constructs an input file for the given filename (which must not
487 be empty), and calls LoadObject. If LoadObject returns true, the
488 document is set to unmodified; otherwise, an error message box is
489 displayed. The document's views are notified that the filename has
490 changed, to give windows an opportunity to update their titles. All of
491 the document's views are then updated.
492 """
493 if not self.OnSaveModified():
494 return False
495
496 msgTitle = wx.GetApp().GetAppName()
497 if not msgTitle:
498 msgTitle = _("File Error")
499
500 fileObject = file(filename, 'r')
501 try:
502 self.LoadObject(fileObject)
503 except:
504 wx.MessageBox("Could not open '%s'. %s" % (FileNameFromPath(filename), sys.exc_value),
505 msgTitle,
506 wx.OK | wx.ICON_EXCLAMATION,
507 self.GetDocumentWindow())
508 return False
509
510 self.SetFilename(filename, True)
511 self.Modify(False)
512 self.SetDocumentModificationDate()
513 self.SetDocumentSaved(True)
514 self.UpdateAllViews()
515 return True
516
517
518 def LoadObject(self, file):
519 """
520 Override this function and call it from your own LoadObject before
521 loading your own data. LoadObject is called by the framework
522 automatically when the document contents need to be loaded.
523
524 Note that the wxPython version simply sends you a Python file object,
525 so you can use pickle.
526 """
527 return True
528
529
530 def SaveObject(self, file):
531 """
532 Override this function and call it from your own SaveObject before
533 saving your own data. SaveObject is called by the framework
534 automatically when the document contents need to be saved.
535
536 Note that the wxPython version simply sends you a Python file object,
537 so you can use pickle.
538 """
539 return True
540
541
542 def Revert(self):
543 """
544 Override this function to revert the document to its last saved state.
545 """
546 return False
547
548
549 def GetPrintableName(self):
550 """
551 Copies a suitable document name into the supplied name buffer.
552 The default function uses the title, or if there is no title, uses the
553 filename; or if no filename, the string 'Untitled'.
554 """
555 if self._documentTitle:
556 return self._documentTitle
557 elif self._documentFile:
558 return FileNameFromPath(self._documentFile)
559 else:
560 return _("Untitled")
561
562
563 def GetDocumentWindow(self):
564 """
565 Intended to return a suitable window for using as a parent for
566 document-related dialog boxes. By default, uses the frame associated
567 with the first view.
568 """
569 if len(self._documentViews) > 0:
570 return self._documentViews[0].GetFrame()
571 else:
572 return wx.GetApp().GetTopWindow()
573
574
575 def OnCreateCommandProcessor(self):
576 """
577 Override this function if you want a different (or no) command
578 processor to be created when the document is created. By default, it
579 returns an instance of wxCommandProcessor.
580 """
581 return CommandProcessor()
582
583
584 def OnSaveModified(self):
585 """
586 If the document has been modified, prompts the user to ask if the
587 changes should be changed. If the user replies Yes, the Save function
588 is called. If No, the document is marked as unmodified and the
589 function succeeds. If Cancel, the function fails.
590 """
591 if not self.IsModified():
592 return True
593
594 """ check for file modification outside of application """
595 if os.path.exists(self.GetFilename()) and os.path.getmtime(self.GetFilename()) != self.GetDocumentModificationDate():
596 msgTitle = wx.GetApp().GetAppName()
597 if not msgTitle:
598 msgTitle = _("Warning")
599 res = wx.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()),
600 msgTitle,
601 wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
602 self.GetDocumentWindow())
603
604 if res == wx.NO:
605 self.Modify(False)
606 return True
607 elif res == wx.YES:
608 return wx.lib.docview.Document.Save(self)
609 else: # elif res == wx.CANCEL:
610 return False
611
612 msgTitle = wx.GetApp().GetAppName()
613 if not msgTitle:
614 msgTitle = _("Warning")
615
616 res = wx.MessageBox(_("Save changes to '%s'?") % self.GetPrintableName(),
617 msgTitle,
618 wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
619 self.GetDocumentWindow())
620
621 if res == wx.NO:
622 self.Modify(False)
623 return True
624 elif res == wx.YES:
625 return self.Save()
626 else: # elif res == wx.CANCEL:
627 return False
628
629
630 def Draw(context):
631 """
632 Called by printing framework to draw the view.
633 """
634 return True
635
636
637 def AddView(self, view):
638 """
639 If the view is not already in the list of views, adds the view and
640 calls OnChangedViewList.
641 """
642 if not view in self._documentViews:
643 self._documentViews.append(view)
644 self.OnChangedViewList()
645 return True
646
647
648 def RemoveView(self, view):
649 """
650 Removes the view from the document's list of views, and calls
651 OnChangedViewList.
652 """
653 if view in self._documentViews:
654 self._documentViews.remove(view)
655 self.OnChangedViewList()
656 return True
657
658
659 def OnCreate(self, path, flags):
660 """
661 The default implementation calls DeleteContents (an empty
662 implementation) sets the modified flag to false. Override this to
663 supply additional behaviour when the document is closed with Close.
664 """
665 return self.GetDocumentTemplate().CreateView(self, flags)
666
667
668 def OnChangedViewList(self):
669 """
670 Called when a view is added to or deleted from this document. The
671 default implementation saves and deletes the document if no views
672 exist (the last one has just been removed).
673 """
674 if len(self._documentViews) == 0:
675 if self.OnSaveModified():
676 pass # C version does a delete but Python will garbage collect
677
678
679 def UpdateAllViews(self, sender = None, hint = None):
680 """
681 Updates all views. If sender is non-NULL, does not update this view.
682 hint represents optional information to allow a view to optimize its
683 update.
684 """
685 for view in self._documentViews:
686 if view != sender:
687 view.OnUpdate(sender, hint)
688
689
690 def NotifyClosing(self):
691 """
692 Notifies the views that the document is going to close.
693 """
694 for view in self._documentViews:
695 view.OnClosingDocument()
696
697
698 def SetFilename(self, filename, notifyViews = False):
699 """
700 Sets the filename for this document. Usually called by the framework.
701 If notifyViews is true, wxView.OnChangeFilename is called for all
702 views.
703 """
704 self._documentFile = filename
705 if notifyViews:
706 for view in self._documentViews:
707 view.OnChangeFilename()
708
709
710 def GetWriteable(self):
711 """
712 Returns true if the document can be written to its accociated file path.
713 This method has been added to wxPython and is not in wxWindows.
714 """
715 if not self._writeable:
716 return False
717 if not self._documentFile: # Doesn't exist, do a save as
718 return True
719 else:
720 return os.access(self._documentFile, os.W_OK)
721
722
723 def SetWriteable(self, writeable):
724 """
725 Set to False if the document can not be saved. This will disable the ID_SAVE_AS
726 event and is useful for custom documents that should not be saveable. The ID_SAVE
727 event can be disabled by never Modifying the document. This method has been added
728 to wxPython and is not in wxWindows.
729 """
730 self._writeable = writeable
731
732
733 class View(wx.EvtHandler):
734 """
735 The view class can be used to model the viewing and editing component of
736 an application's file-based data. It is part of the document/view
737 framework supported by wxWindows, and cooperates with the wxDocument,
738 wxDocTemplate and wxDocManager classes.
739 """
740
741 def __init__(self):
742 """
743 Constructor. Define your own default constructor to initialize
744 application-specific data.
745 """
746 wx.EvtHandler.__init__(self)
747 self._viewDocument = None
748 self._viewFrame = None
749
750
751 def Destroy(self):
752 """
753 Destructor. Removes itself from the document's list of views.
754 """
755 if self._viewDocument:
756 self._viewDocument.RemoveView(self)
757 wx.EvtHandler.Destroy(self)
758
759
760 def ProcessEvent(self, event):
761 """
762 Processes an event, searching event tables and calling zero or more
763 suitable event handler function(s). Note that the ProcessEvent
764 method is called from the wxPython docview framework directly since
765 wxPython does not have a virtual ProcessEvent function.
766 """
767 if not self.GetDocument() or not self.GetDocument().ProcessEvent(event):
768 return False
769 else:
770 return True
771
772
773 def ProcessUpdateUIEvent(self, event):
774 """
775 Processes a UI event, searching event tables and calling zero or more
776 suitable event handler function(s). Note that the ProcessEvent
777 method is called from the wxPython docview framework directly since
778 wxPython does not have a virtual ProcessEvent function.
779 """
780 return False
781
782
783 def OnActivateView(self, activate, activeView, deactiveView):
784 """
785 Called when a view is activated by means of wxView::Activate. The
786 default implementation does nothing.
787 """
788 pass
789
790
791 def OnClosingDocument(self):
792 """
793 Override this to clean up the view when the document is being closed.
794 The default implementation does nothing.
795 """
796 pass
797
798
799 def OnDraw(self, dc):
800 """
801 Override this to draw the view for the printing framework. The
802 default implementation does nothing.
803 """
804 pass
805
806
807 def OnPrint(self, dc, info):
808 """
809 Override this to print the view for the printing framework. The
810 default implementation calls View.OnDraw.
811 """
812 self.OnDraw(dc)
813
814
815 def OnUpdate(self, sender, hint):
816 """
817 Called when the view should be updated. sender is a pointer to the
818 view that sent the update request, or NULL if no single view requested
819 the update (for instance, when the document is opened). hint is as yet
820 unused but may in future contain application-specific information for
821 making updating more efficient.
822 """
823 pass
824
825
826 def OnChangeFilename(self):
827 """
828 Called when the filename has changed. The default implementation
829 constructs a suitable title and sets the title of the view frame (if
830 any).
831 """
832 if self.GetFrame():
833 appName = wx.GetApp().GetAppName()
834 if not self.GetDocument():
835 if appName:
836 title = appName
837 else:
838 return
839 else:
840 if appName and isinstance(self.GetFrame(), DocChildFrame): # Only need app name in title for SDI
841 title = appName + _(" - ")
842 else:
843 title = ''
844 self.GetFrame().SetTitle(title + self.GetDocument().GetPrintableName())
845
846
847 def GetDocument(self):
848 """
849 Returns the document associated with the view.
850 """
851 return self._viewDocument
852
853
854 def SetDocument(self, doc):
855 """
856 Associates the given document with the view. Normally called by the
857 framework.
858 """
859 self._viewDocument = doc
860 if doc:
861 doc.AddView(self)
862
863
864 def GetViewName(self):
865 """
866 Gets the name associated with the view (passed to the wxDocTemplate
867 constructor). Not currently used by the framework.
868 """
869 return self._viewTypeName
870
871
872 def SetViewName(self, name):
873 """
874 Sets the view type name. Should only be called by the framework.
875 """
876 self._viewTypeName = name
877
878
879 def Close(self, deleteWindow = True):
880 """
881 Closes the view by calling OnClose. If deleteWindow is true, this
882 function should delete the window associated with the view.
883 """
884 if self.OnClose(deleteWindow = deleteWindow):
885 return True
886 else:
887 return False
888
889
890 def Activate(self, activate = True):
891 """
892 Call this from your view frame's OnActivate member to tell the
893 framework which view is currently active. If your windowing system
894 doesn't call OnActivate, you may need to call this function from
895 OnMenuCommand or any place where you know the view must be active, and
896 the framework will need to get the current view.
897
898 The prepackaged view frame wxDocChildFrame calls wxView.Activate from
899 its OnActivate member and from its OnMenuCommand member.
900 """
901 if self.GetDocument() and self.GetDocumentManager():
902 self.OnActivateView(activate, self, self.GetDocumentManager().GetCurrentView())
903 self.GetDocumentManager().ActivateView(self, activate)
904
905
906 def OnClose(self, deleteWindow = True):
907 """
908 Implements closing behaviour. The default implementation calls
909 wxDocument.Close to close the associated document. Does not delete the
910 view. The application may wish to do some cleaning up operations in
911 this function, if a call to wxDocument::Close succeeded. For example,
912 if your application's all share the same window, you need to
913 disassociate the window from the view and perhaps clear the window. If
914 deleteWindow is true, delete the frame associated with the view.
915 """
916 if self.GetDocument():
917 return self.GetDocument().Close()
918 else:
919 return True
920
921
922 def OnCreate(self, doc, flags):
923 """
924 wxDocManager or wxDocument creates a wxView via a wxDocTemplate. Just
925 after the wxDocTemplate creates the wxView, it calls wxView::OnCreate.
926 In its OnCreate member function, the wxView can create a
927 wxDocChildFrame or a derived class. This wxDocChildFrame provides user
928 interface elements to view and/or edit the contents of the wxDocument.
929
930 By default, simply returns true. If the function returns false, the
931 view will be deleted.
932 """
933 return True
934
935
936 def OnCreatePrintout(self):
937 """
938 Returns a wxPrintout object for the purposes of printing. It should
939 create a new object every time it is called; the framework will delete
940 objects it creates.
941
942 By default, this function returns an instance of wxDocPrintout, which
943 prints and previews one page by calling wxView.OnDraw.
944
945 Override to return an instance of a class other than wxDocPrintout.
946 """
947 return DocPrintout(self)
948
949
950 def GetFrame(self):
951 """
952 Gets the frame associated with the view (if any). Note that this
953 "frame" is not a wxFrame at all in the generic MDI implementation
954 which uses the notebook pages instead of the frames and this is why
955 this method returns a wxWindow and not a wxFrame.
956 """
957 return self._viewFrame
958
959
960 def SetFrame(self, frame):
961 """
962 Sets the frame associated with this view. The application should call
963 this if possible, to tell the view about the frame. See GetFrame for
964 the explanation about the mismatch between the "Frame" in the method
965 name and the type of its parameter.
966 """
967 self._viewFrame = frame
968
969
970 def GetDocumentManager(self):
971 """
972 Returns the document manager instance associated with this view.
973 """
974 if self._viewDocument:
975 return self.GetDocument().GetDocumentManager()
976 else:
977 return None
978
979
980 class DocTemplate(wx.Object):
981 """
982 The wxDocTemplate class is used to model the relationship between a
983 document class and a view class.
984 """
985
986
987 def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags = DEFAULT_TEMPLATE_FLAGS, icon = None):
988 """
989 Constructor. Create instances dynamically near the start of your
990 application after creating a wxDocManager instance, and before doing
991 any document or view operations.
992
993 manager is the document manager object which manages this template.
994
995 description is a short description of what the template is for. This
996 string will be displayed in the file filter list of Windows file
997 selectors.
998
999 filter is an appropriate file filter such as *.txt.
1000
1001 dir is the default directory to use for file selectors.
1002
1003 ext is the default file extension (such as txt).
1004
1005 docTypeName is a name that should be unique for a given type of
1006 document, used for gathering a list of views relevant to a
1007 particular document.
1008
1009 viewTypeName is a name that should be unique for a given view.
1010
1011 docClass is a Python class. If this is not supplied, you will need to
1012 derive a new wxDocTemplate class and override the CreateDocument
1013 member to return a new document instance on demand.
1014
1015 viewClass is a Python class. If this is not supplied, you will need to
1016 derive a new wxDocTemplate class and override the CreateView member to
1017 return a new view instance on demand.
1018
1019 flags is a bit list of the following:
1020 wx.TEMPLATE_VISIBLE The template may be displayed to the user in
1021 dialogs.
1022
1023 wx.TEMPLATE_INVISIBLE The template may not be displayed to the user in
1024 dialogs.
1025
1026 wx.DEFAULT_TEMPLATE_FLAGS Defined as wxTEMPLATE_VISIBLE.
1027 """
1028 self._docManager = manager
1029 self._description = description
1030 self._fileFilter = filter
1031 self._directory = dir
1032 self._defaultExt = ext
1033 self._docTypeName = docTypeName
1034 self._viewTypeName = viewTypeName
1035 self._docType = docType
1036 self._viewType = viewType
1037 self._flags = flags
1038 self._icon = icon
1039
1040 self._docManager.AssociateTemplate(self)
1041
1042
1043 def GetDefaultExtension(self):
1044 """
1045 Returns the default file extension for the document data, as passed to
1046 the document template constructor.
1047 """
1048 return self._defaultExt
1049
1050
1051 def SetDefaultExtension(self, defaultExt):
1052 """
1053 Sets the default file extension.
1054 """
1055 self._defaultExt = defaultExt
1056
1057
1058 def GetDescription(self):
1059 """
1060 Returns the text description of this template, as passed to the
1061 document template constructor.
1062 """
1063 return self._description
1064
1065
1066 def SetDescription(self, description):
1067 """
1068 Sets the template description.
1069 """
1070 self._description = description
1071
1072
1073 def GetDirectory(self):
1074 """
1075 Returns the default directory, as passed to the document template
1076 constructor.
1077 """
1078 return self._directory
1079
1080
1081 def SetDirectory(self, dir):
1082 """
1083 Sets the default directory.
1084 """
1085 self._directory = dir
1086
1087
1088 def GetDocumentManager(self):
1089 """
1090 Returns the document manager instance for which this template was
1091 created.
1092 """
1093 return self._docManager
1094
1095
1096 def SetDocumentManager(self, manager):
1097 """
1098 Sets the document manager instance for which this template was
1099 created. Should not be called by the application.
1100 """
1101 self._docManager = manager
1102
1103
1104 def GetFileFilter(self):
1105 """
1106 Returns the file filter, as passed to the document template
1107 constructor.
1108 """
1109 return self._fileFilter
1110
1111
1112 def SetFileFilter(self, filter):
1113 """
1114 Sets the file filter.
1115 """
1116 self._fileFilter = filter
1117
1118
1119 def GetFlags(self):
1120 """
1121 Returns the flags, as passed to the document template constructor.
1122 (see the constructor description for more details).
1123 """
1124 return self._flags
1125
1126
1127 def SetFlags(self, flags):
1128 """
1129 Sets the internal document template flags (see the constructor
1130 description for more details).
1131 """
1132 self._flags = flags
1133
1134
1135 def GetIcon(self):
1136 """
1137 Returns the icon, as passed to the document template
1138 constructor. This method has been added to wxPython and is
1139 not in wxWindows.
1140 """
1141 return self._icon
1142
1143
1144 def SetIcon(self, flags):
1145 """
1146 Sets the icon. This method has been added to wxPython and is not
1147 in wxWindows.
1148 """
1149 self._icon = icon
1150
1151
1152 def GetDocumentType(self):
1153 """
1154 Returns the Python document class, as passed to the document template
1155 constructor.
1156 """
1157 return self._docType
1158
1159
1160 def GetViewType(self):
1161 """
1162 Returns the Python view class, as passed to the document template
1163 constructor.
1164 """
1165 return self._viewType
1166
1167
1168 def IsVisible(self):
1169 """
1170 Returns true if the document template can be shown in user dialogs,
1171 false otherwise.
1172 """
1173 return (self._flags & TEMPLATE_VISIBLE) == TEMPLATE_VISIBLE
1174
1175
1176 def GetDocumentName(self):
1177 """
1178 Returns the document type name, as passed to the document template
1179 constructor.
1180 """
1181 return self._docTypeName
1182
1183
1184 def GetViewName(self):
1185 """
1186 Returns the view type name, as passed to the document template
1187 constructor.
1188 """
1189 return self._viewTypeName
1190
1191
1192 def CreateDocument(self, path, flags):
1193 """
1194 Creates a new instance of the associated document class. If you have
1195 not supplied a class to the template constructor, you will need to
1196 override this function to return an appropriate document instance.
1197 """
1198 doc = self._docType()
1199 doc.SetFilename(path)
1200 doc.SetDocumentTemplate(self)
1201 self.GetDocumentManager().AddDocument(doc)
1202 doc.SetCommandProcessor(doc.OnCreateCommandProcessor())
1203 if doc.OnCreate(path, flags):
1204 return doc
1205 else:
1206 if doc in self.GetDocumentManager().GetDocuments():
1207 doc.DeleteAllViews()
1208 return None
1209
1210
1211 def CreateView(self, doc, flags):
1212 """
1213 Creates a new instance of the associated document view. If you have
1214 not supplied a class to the template constructor, you will need to
1215 override this function to return an appropriate view instance.
1216 """
1217 view = self._viewType()
1218 view.SetDocument(doc)
1219 if view.OnCreate(doc, flags):
1220 return view
1221 else:
1222 view.Destroy()
1223 return None
1224
1225
1226 def FileMatchesTemplate(self, path):
1227 """
1228 Returns True if the path's extension matches one of this template's
1229 file filter extensions.
1230 """
1231 ext = FindExtension(path)
1232 if not ext: return False
1233 return ext in self.GetFileFilter()
1234 # return self.GetDefaultExtension() == FindExtension(path)
1235
1236
1237 class DocManager(wx.EvtHandler):
1238 """
1239 The wxDocManager class is part of the document/view framework supported by
1240 wxWindows, and cooperates with the wxView, wxDocument and wxDocTemplate
1241 classes.
1242 """
1243
1244 def __init__(self, flags = DEFAULT_DOCMAN_FLAGS, initialize = True):
1245 """
1246 Constructor. Create a document manager instance dynamically near the
1247 start of your application before doing any document or view operations.
1248
1249 flags is used in the Python version to indicate whether the document
1250 manager is in DOC_SDI or DOC_MDI mode.
1251
1252 If initialize is true, the Initialize function will be called to
1253 create a default history list object. If you derive from wxDocManager,
1254 you may wish to call the base constructor with false, and then call
1255 Initialize in your own constructor, to allow your own Initialize or
1256 OnCreateFileHistory functions to be called.
1257 """
1258
1259 wx.EvtHandler.__init__(self)
1260
1261 self._defaultDocumentNameCounter = 1
1262 self._flags = flags
1263 self._currentView = None
1264 self._lastActiveView = None
1265 self._maxDocsOpen = 10000
1266 self._fileHistory = None
1267 self._templates = []
1268 self._docs = []
1269 self._lastDirectory = ""
1270
1271 if initialize:
1272 self.Initialize()
1273
1274 wx.EVT_MENU(self, wx.ID_OPEN, self.OnFileOpen)
1275 wx.EVT_MENU(self, wx.ID_CLOSE, self.OnFileClose)
1276 wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.OnFileCloseAll)
1277 wx.EVT_MENU(self, wx.ID_REVERT, self.OnFileRevert)
1278 wx.EVT_MENU(self, wx.ID_NEW, self.OnFileNew)
1279 wx.EVT_MENU(self, wx.ID_SAVE, self.OnFileSave)
1280 wx.EVT_MENU(self, wx.ID_SAVEAS, self.OnFileSaveAs)
1281 wx.EVT_MENU(self, wx.ID_UNDO, self.OnUndo)
1282 wx.EVT_MENU(self, wx.ID_REDO, self.OnRedo)
1283 wx.EVT_MENU(self, wx.ID_PRINT, self.OnPrint)
1284 wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.OnPrintSetup)
1285 wx.EVT_MENU(self, wx.ID_PREVIEW, self.OnPreview)
1286
1287 wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.OnUpdateFileOpen)
1288 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.OnUpdateFileClose)
1289 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.OnUpdateFileCloseAll)
1290 wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.OnUpdateFileRevert)
1291 wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.OnUpdateFileNew)
1292 wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.OnUpdateFileSave)
1293 wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.OnUpdateFileSaveAs)
1294 wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.OnUpdateUndo)
1295 wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.OnUpdateRedo)
1296 wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.OnUpdatePrint)
1297 wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.OnUpdatePrintSetup)
1298 wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.OnUpdatePreview)
1299
1300
1301 def Destroy(self):
1302 """
1303 Destructor.
1304 """
1305 self.Clear()
1306 wx.EvtHandler.Destroy(self)
1307
1308
1309 def GetFlags(self):
1310 """
1311 Returns the document manager's flags. This method has been
1312 added to wxPython and is not in wxWindows.
1313 """
1314 return self._flags
1315
1316
1317 def CloseDocument(self, doc, force = True):
1318 """
1319 Closes the specified document.
1320 """
1321 if doc.Close() or force:
1322 doc.DeleteAllViews()
1323 if doc in self._docs:
1324 doc.Destroy()
1325 return True
1326 return False
1327
1328
1329 def CloseDocuments(self, force = True):
1330 """
1331 Closes all currently opened documents.
1332 """
1333 for document in self._docs[::-1]: # Close in lifo (reverse) order. We clone the list to make sure we go through all docs even as they are deleted
1334 if not self.CloseDocument(document, force):
1335 return False
1336 document.DeleteAllViews() # Implicitly delete the document when the last view is removed
1337 return True
1338
1339
1340 def Clear(self, force = True):
1341 """
1342 Closes all currently opened document by callling CloseDocuments and
1343 clears the document manager's templates.
1344 """
1345 if not self.CloseDocuments(force):
1346 return False
1347 self._templates = []
1348 return True
1349
1350
1351 def Initialize(self):
1352 """
1353 Initializes data; currently just calls OnCreateFileHistory. Some data
1354 cannot always be initialized in the constructor because the programmer
1355 must be given the opportunity to override functionality. In fact
1356 Initialize is called from the wxDocManager constructor, but this can
1357 be vetoed by passing false to the second argument, allowing the
1358 derived class's constructor to call Initialize, possibly calling a
1359 different OnCreateFileHistory from the default.
1360
1361 The bottom line: if you're not deriving from Initialize, forget it and
1362 construct wxDocManager with no arguments.
1363 """
1364 self.OnCreateFileHistory()
1365 return True
1366
1367
1368 def OnCreateFileHistory(self):
1369 """
1370 A hook to allow a derived class to create a different type of file
1371 history. Called from Initialize.
1372 """
1373 self._fileHistory = wx.FileHistory()
1374
1375
1376 def OnFileClose(self, event):
1377 """
1378 Closes and deletes the currently active document.
1379 """
1380 doc = self.GetCurrentDocument()
1381 if doc:
1382 doc.DeleteAllViews()
1383 if doc in self._docs:
1384 self._docs.remove(doc)
1385
1386
1387 def OnFileCloseAll(self, event):
1388 """
1389 Closes and deletes all the currently opened documents.
1390 """
1391 return self.CloseDocuments(force = False)
1392
1393
1394 def OnFileNew(self, event):
1395 """
1396 Creates a new document and reads in the selected file.
1397 """
1398 self.CreateDocument('', DOC_NEW)
1399
1400
1401 def OnFileOpen(self, event):
1402 """
1403 Creates a new document and reads in the selected file.
1404 """
1405 if not self.CreateDocument('', DEFAULT_DOCMAN_FLAGS):
1406 self.OnOpenFileFailure()
1407
1408
1409 def OnFileRevert(self, event):
1410 """
1411 Reverts the current document by calling wxDocument.Save for the current
1412 document.
1413 """
1414 doc = self.GetCurrentDocument()
1415 if not doc:
1416 return
1417 doc.Revert()
1418
1419
1420 def OnFileSave(self, event):
1421 """
1422 Saves the current document by calling wxDocument.Save for the current
1423 document.
1424 """
1425 doc = self.GetCurrentDocument()
1426 if not doc:
1427 return
1428 doc.Save()
1429
1430
1431 def OnFileSaveAs(self, event):
1432 """
1433 Calls wxDocument.SaveAs for the current document.
1434 """
1435 doc = self.GetCurrentDocument()
1436 if not doc:
1437 return
1438 doc.SaveAs()
1439
1440
1441 def OnPrint(self, event):
1442 """
1443 Prints the current document by calling its View's OnCreatePrintout
1444 method.
1445 """
1446 view = self.GetCurrentView()
1447 if not view:
1448 return
1449
1450 printout = view.OnCreatePrintout()
1451 if printout:
1452 pdd = wx.PrintDialogData()
1453 printer = wx.Printer(pdd)
1454 printer.Print(view.GetFrame(), printout) # , True)
1455
1456
1457 def OnPrintSetup(self, event):
1458 """
1459 Presents the print setup dialog.
1460 """
1461 view = self.GetCurrentView()
1462 if view:
1463 parentWin = view.GetFrame()
1464 else:
1465 parentWin = wx.GetApp().GetTopWindow()
1466
1467 data = wx.PrintDialogData()
1468 printDialog = wx.PrintDialog(parentWin, data)
1469 printDialog.GetPrintDialogData().SetSetupDialog(True)
1470 printDialog.ShowModal()
1471 # TODO: Confirm that we don't have to remember PrintDialogData
1472
1473
1474 def OnPreview(self, event):
1475 """
1476 Previews the current document by calling its View's OnCreatePrintout
1477 method.
1478 """
1479 view = self.GetCurrentView()
1480 if not view:
1481 return
1482
1483 printout = view.OnCreatePrintout()
1484 if printout:
1485 # Pass two printout objects: for preview, and possible printing.
1486 preview = wx.PrintPreview(printout, view.OnCreatePrintout())
1487 # wxWindows source doesn't use base frame's pos, size, and icon, but did it this way so it would work like MS Office etc.
1488 mimicFrame = wx.GetApp().GetTopWindow()
1489 frame = wx.PreviewFrame(preview, mimicFrame, _("Print Preview"), mimicFrame.GetPosition(), mimicFrame.GetSize())
1490 frame.SetIcon(mimicFrame.GetIcon())
1491 frame.SetTitle(mimicFrame.GetTitle() + _(" - Preview"))
1492 frame.Initialize()
1493 frame.Show(True)
1494
1495
1496 def OnUndo(self, event):
1497 """
1498 Issues an Undo command to the current document's command processor.
1499 """
1500 doc = self.GetCurrentDocument()
1501 if not doc:
1502 return
1503 if doc.GetCommandProcessor():
1504 doc.GetCommandProcessor().Undo()
1505
1506
1507 def OnRedo(self, event):
1508 """
1509 Issues a Redo command to the current document's command processor.
1510 """
1511 doc = self.GetCurrentDocument()
1512 if not doc:
1513 return
1514 if doc.GetCommandProcessor():
1515 doc.GetCommandProcessor().Redo()
1516
1517
1518 def OnUpdateFileOpen(self, event):
1519 """
1520 Updates the user interface for the File Open command.
1521 """
1522 event.Enable(True)
1523
1524
1525 def OnUpdateFileClose(self, event):
1526 """
1527 Updates the user interface for the File Close command.
1528 """
1529 event.Enable(self.GetCurrentDocument() != None)
1530
1531
1532 def OnUpdateFileCloseAll(self, event):
1533 """
1534 Updates the user interface for the File Close All command.
1535 """
1536 event.Enable(self.GetCurrentDocument() != None)
1537
1538
1539 def OnUpdateFileRevert(self, event):
1540 """
1541 Updates the user interface for the File Revert command.
1542 """
1543 event.Enable(self.GetCurrentDocument() != None)
1544
1545
1546 def OnUpdateFileNew(self, event):
1547 """
1548 Updates the user interface for the File New command.
1549 """
1550 return True
1551
1552
1553 def OnUpdateFileSave(self, event):
1554 """
1555 Updates the user interface for the File Save command.
1556 """
1557 doc = self.GetCurrentDocument()
1558 event.Enable(doc != None and doc.IsModified())
1559
1560
1561 def OnUpdateFileSaveAs(self, event):
1562 """
1563 Updates the user interface for the File Save As command.
1564 """
1565 event.Enable(self.GetCurrentDocument() != None and self.GetCurrentDocument().GetWriteable())
1566
1567
1568 def OnUpdateUndo(self, event):
1569 """
1570 Updates the user interface for the Undo command.
1571 """
1572 doc = self.GetCurrentDocument()
1573 event.Enable(doc != None and doc.GetCommandProcessor() != None and doc.GetCommandProcessor().CanUndo())
1574 if doc and doc.GetCommandProcessor():
1575 doc.GetCommandProcessor().SetMenuStrings()
1576 else:
1577 event.SetText(_("Undo") + '\t' + _('Ctrl+Z'))
1578
1579
1580 def OnUpdateRedo(self, event):
1581 """
1582 Updates the user interface for the Redo command.
1583 """
1584 doc = self.GetCurrentDocument()
1585 event.Enable(doc != None and doc.GetCommandProcessor() != None and doc.GetCommandProcessor().CanRedo())
1586 if doc and doc.GetCommandProcessor():
1587 doc.GetCommandProcessor().SetMenuStrings()
1588 else:
1589 event.SetText(_("Redo") + '\t' + _('Ctrl+Y'))
1590
1591
1592 def OnUpdatePrint(self, event):
1593 """
1594 Updates the user interface for the Print command.
1595 """
1596 event.Enable(self.GetCurrentDocument() != None)
1597
1598
1599 def OnUpdatePrintSetup(self, event):
1600 """
1601 Updates the user interface for the Print Setup command.
1602 """
1603 return True
1604
1605
1606 def OnUpdatePreview(self, event):
1607 """
1608 Updates the user interface for the Print Preview command.
1609 """
1610 event.Enable(self.GetCurrentDocument() != None)
1611
1612
1613 def GetCurrentView(self):
1614 """
1615 Returns the currently active view.
1616 """
1617 if self._currentView:
1618 return self._currentView
1619 if len(self._docs) == 1:
1620 return self._docs[0].GetFirstView()
1621 return None
1622
1623
1624 def GetLastActiveView(self):
1625 """
1626 Returns the last active view. This is used in the SDI framework where dialogs can be mistaken for a view
1627 and causes the framework to deactivete the current view. This happens when something like a custom dialog box used
1628 to operate on the current view is shown.
1629 """
1630 if len(self._docs) >= 1:
1631 return self._lastActiveView
1632 else:
1633 return None
1634
1635
1636 def ProcessEvent(self, event):
1637 """
1638 Processes an event, searching event tables and calling zero or more
1639 suitable event handler function(s). Note that the ProcessEvent
1640 method is called from the wxPython docview framework directly since
1641 wxPython does not have a virtual ProcessEvent function.
1642 """
1643 view = self.GetCurrentView()
1644 if view:
1645 if view.ProcessEvent(event):
1646 return True
1647 id = event.GetId()
1648 if id == wx.ID_OPEN:
1649 self.OnFileOpen(event)
1650 return True
1651 elif id == wx.ID_CLOSE:
1652 self.OnFileClose(event)
1653 return True
1654 elif id == wx.ID_CLOSE_ALL:
1655 self.OnFileCloseAll(event)
1656 return True
1657 elif id == wx.ID_REVERT:
1658 self.OnFileRevert(event)
1659 return True
1660 elif id == wx.ID_NEW:
1661 self.OnFileNew(event)
1662 return True
1663 elif id == wx.ID_SAVE:
1664 self.OnFileSave(event)
1665 return True
1666 elif id == wx.ID_SAVEAS:
1667 self.OnFileSaveAs(event)
1668 return True
1669 elif id == wx.ID_UNDO:
1670 self.OnUndo(event)
1671 return True
1672 elif id == wx.ID_REDO:
1673 self.OnRedo(event)
1674 return True
1675 elif id == wx.ID_PRINT:
1676 self.OnPrint(event)
1677 return True
1678 elif id == wx.ID_PRINT_SETUP:
1679 self.OnPrintSetup(event)
1680 return True
1681 elif id == wx.ID_PREVIEW:
1682 self.OnPreview(event)
1683 return True
1684 else:
1685 return False
1686
1687
1688 def ProcessUpdateUIEvent(self, event):
1689 """
1690 Processes a UI event, searching event tables and calling zero or more
1691 suitable event handler function(s). Note that the ProcessEvent
1692 method is called from the wxPython docview framework directly since
1693 wxPython does not have a virtual ProcessEvent function.
1694 """
1695 id = event.GetId()
1696 view = self.GetCurrentView()
1697 if view:
1698 if view.ProcessUpdateUIEvent(event):
1699 return True
1700 if id == wx.ID_OPEN:
1701 self.OnUpdateFileOpen(event)
1702 return True
1703 elif id == wx.ID_CLOSE:
1704 self.OnUpdateFileClose(event)
1705 return True
1706 elif id == wx.ID_CLOSE_ALL:
1707 self.OnUpdateFileCloseAll(event)
1708 return True
1709 elif id == wx.ID_REVERT:
1710 self.OnUpdateFileRevert(event)
1711 return True
1712 elif id == wx.ID_NEW:
1713 self.OnUpdateFileNew(event)
1714 return True
1715 elif id == wx.ID_SAVE:
1716 self.OnUpdateFileSave(event)
1717 return True
1718 elif id == wx.ID_SAVEAS:
1719 self.OnUpdateFileSaveAs(event)
1720 return True
1721 elif id == wx.ID_UNDO:
1722 self.OnUpdateUndo(event)
1723 return True
1724 elif id == wx.ID_REDO:
1725 self.OnUpdateRedo(event)
1726 return True
1727 elif id == wx.ID_PRINT:
1728 self.OnUpdatePrint(event)
1729 return True
1730 elif id == wx.ID_PRINT_SETUP:
1731 self.OnUpdatePrintSetup(event)
1732 return True
1733 elif id == wx.ID_PREVIEW:
1734 self.OnUpdatePreview(event)
1735 return True
1736 else:
1737 return False
1738
1739
1740 def CreateDocument(self, path, flags = 0):
1741 """
1742 Creates a new document in a manner determined by the flags parameter,
1743 which can be:
1744
1745 wx.lib.docview.DOC_NEW Creates a fresh document.
1746 wx.lib.docview.DOC_SILENT Silently loads the given document file.
1747
1748 If wx.lib.docview.DOC_NEW is present, a new document will be created and returned,
1749 possibly after asking the user for a template to use if there is more
1750 than one document template. If wx.lib.docview.DOC_SILENT is present, a new document
1751 will be created and the given file loaded into it. If neither of these
1752 flags is present, the user will be presented with a file selector for
1753 the file to load, and the template to use will be determined by the
1754 extension (Windows) or by popping up a template choice list (other
1755 platforms).
1756
1757 If the maximum number of documents has been reached, this function
1758 will delete the oldest currently loaded document before creating a new
1759 one.
1760
1761 wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE flag.
1762 """
1763 templates = []
1764 for temp in self._templates:
1765 if temp.IsVisible():
1766 templates.append(temp)
1767 if len(templates) == 0:
1768 return None
1769
1770 if len(self.GetDocuments()) >= self._maxDocsOpen:
1771 doc = self.GetDocuments()[0]
1772 if not self.CloseDocument(doc, False):
1773 return None
1774
1775 if flags & DOC_NEW:
1776 if len(templates) == 1:
1777 temp = templates[0]
1778 newDoc = temp.CreateDocument(path, flags)
1779 if newDoc:
1780 newDoc.SetDocumentName(temp.GetDocumentName())
1781 newDoc.SetDocumentTemplate(temp)
1782 newDoc.OnNewDocument()
1783 return newDoc
1784
1785 temp = self.SelectDocumentType(templates)
1786 if temp:
1787 newDoc = temp.CreateDocument(path, flags)
1788 if newDoc:
1789 newDoc.SetDocumentName(temp.GetDocumentName())
1790 newDoc.SetDocumentTemplate(temp)
1791 newDoc.OnNewDocument()
1792 return newDoc
1793 else:
1794 return None
1795
1796 if path and flags & DOC_SILENT:
1797 temp = self.FindTemplateForPath(path)
1798 else:
1799 temp, path = self.SelectDocumentPath(templates, path, flags)
1800
1801 # Existing document
1802 if self.GetFlags() & DOC_OPEN_ONCE:
1803 for document in self._docs:
1804 if document.GetFilename() == path:
1805 firstView = document.GetFirstView()
1806 if firstView and firstView.GetFrame():
1807 firstView.GetFrame().SetFocus() # Not in wxWindows code but useful nonetheless
1808 if hasattr(firstView.GetFrame(), "IsIconized") and firstView.GetFrame().IsIconized(): # Not in wxWindows code but useful nonetheless
1809 firstView.GetFrame().Iconize(False)
1810 return None
1811
1812 if temp:
1813 newDoc = temp.CreateDocument(path, flags)
1814 if newDoc:
1815 newDoc.SetDocumentName(temp.GetDocumentName())
1816 newDoc.SetDocumentTemplate(temp)
1817 if not newDoc.OnOpenDocument(path):
1818 newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
1819 newDoc.GetFirstView().GetFrame().Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it.
1820 return None
1821 self.AddFileToHistory(path)
1822 return newDoc
1823
1824 return None
1825
1826
1827 def CreateView(self, document, flags = 0):
1828 """
1829 Creates a new view for the given document. If more than one view is
1830 allowed for the document (by virtue of multiple templates mentioning
1831 the same document type), a choice of view is presented to the user.
1832 """
1833 templates = []
1834 for temp in self._templates:
1835 if temp.IsVisible():
1836 if temp.GetDocumentName() == doc.GetDocumentName():
1837 templates.append(temp)
1838 if len(templates) == 0:
1839 return None
1840
1841 if len(templates) == 1:
1842 temp = templates[0]
1843 view = temp.CreateView(doc, flags)
1844 if view:
1845 view.SetViewName(temp.GetViewName())
1846 return view
1847
1848 temp = SelectViewType(templates)
1849 if temp:
1850 view = temp.CreateView(doc, flags)
1851 if view:
1852 view.SetViewName(temp.GetViewName())
1853 return view
1854 else:
1855 return None
1856
1857
1858 def DeleteTemplate(self, template, flags):
1859 """
1860 Placeholder, not yet implemented in wxWindows.
1861 """
1862 pass
1863
1864
1865 def FlushDoc(self, doc):
1866 """
1867 Placeholder, not yet implemented in wxWindows.
1868 """
1869 return False
1870
1871
1872 def MatchTemplate(self, path):
1873 """
1874 Placeholder, not yet implemented in wxWindows.
1875 """
1876 return None
1877
1878
1879 def GetCurrentDocument(self):
1880 """
1881 Returns the document associated with the currently active view (if any).
1882 """
1883 view = self.GetCurrentView()
1884 if view:
1885 return view.GetDocument()
1886 else:
1887 return None
1888
1889
1890 def MakeDefaultName(self):
1891 """
1892 Returns a suitable default name. This is implemented by appending an
1893 integer counter to the string "Untitled" and incrementing the counter.
1894 """
1895 name = _("Untitled %d") % self._defaultDocumentNameCounter
1896 self._defaultDocumentNameCounter = self._defaultDocumentNameCounter + 1
1897 return name
1898
1899
1900 def MakeFrameTitle(self):
1901 """
1902 Returns a suitable title for a document frame. This is implemented by
1903 appending the document name to the application name.
1904 """
1905 appName = wx.GetApp().GetAppName()
1906 if not doc:
1907 title = appName
1908 else:
1909 docName = doc.GetPrintableName()
1910 title = docName + _(" - ") + appName
1911 return title
1912
1913
1914 def AddFileToHistory(self, fileName):
1915 """
1916 Adds a file to the file history list, if we have a pointer to an
1917 appropriate file menu.
1918 """
1919 if self._fileHistory:
1920 self._fileHistory.AddFileToHistory(fileName)
1921
1922
1923 def RemoveFileFromHistory(self, i):
1924 """
1925 Removes a file from the file history list, if we have a pointer to an
1926 appropriate file menu.
1927 """
1928 if self._fileHistory:
1929 self._fileHistory.RemoveFileFromHistory(i)
1930
1931
1932 def GetFileHistory(self):
1933 """
1934 Returns the file history.
1935 """
1936 return self._fileHistory
1937
1938
1939 def GetHistoryFile(self, i):
1940 """
1941 Returns the file at index i from the file history.
1942 """
1943 if self._fileHistory:
1944 return self._fileHistory.GetHistoryFile(i)
1945 else:
1946 return None
1947
1948
1949 def FileHistoryUseMenu(self, menu):
1950 """
1951 Use this menu for appending recently-visited document filenames, for
1952 convenient access. Calling this function with a valid menu enables the
1953 history list functionality.
1954
1955 Note that you can add multiple menus using this function, to be
1956 managed by the file history object.
1957 """
1958 if self._fileHistory:
1959 self._fileHistory.UseMenu(menu)
1960
1961
1962 def FileHistoryRemoveMenu(self, menu):
1963 """
1964 Removes the given menu from the list of menus managed by the file
1965 history object.
1966 """
1967 if self._fileHistory:
1968 self._fileHistory.RemoveMenu(menu)
1969
1970
1971 def FileHistoryLoad(self, config):
1972 """
1973 Loads the file history from a config object.
1974 """
1975 if self._fileHistory:
1976 self._fileHistory.Load(config)
1977
1978
1979 def FileHistorySave(self, config):
1980 """
1981 Saves the file history into a config object. This must be called
1982 explicitly by the application.
1983 """
1984 if self._fileHistory:
1985 self._fileHistory.Save(config)
1986
1987
1988 def FileHistoryAddFilesToMenu(self, menu = None):
1989 """
1990 Appends the files in the history list, to all menus managed by the
1991 file history object.
1992
1993 If menu is specified, appends the files in the history list to the
1994 given menu only.
1995 """
1996 if self._fileHistory:
1997 if menu:
1998 self._fileHistory.AddFilesToThisMenu(menu)
1999 else:
2000 self._fileHistory.AddFilesToMenu()
2001
2002
2003 def GetHistoryFilesCount(self):
2004 """
2005 Returns the number of files currently stored in the file history.
2006 """
2007 if self._fileHistory:
2008 return self._fileHistory.GetNoHistoryFiles()
2009 else:
2010 return 0
2011
2012
2013 def FindTemplateForPath(self, path):
2014 """
2015 Given a path, try to find template that matches the extension. This is
2016 only an approximate method of finding a template for creating a
2017 document.
2018 """
2019 for temp in self._templates:
2020 if temp.FileMatchesTemplate(path):
2021 return temp
2022 return None
2023
2024
2025 def FindSuitableParent(self):
2026 """
2027 Returns a parent frame or dialog, either the frame with the current
2028 focus or if there is no current focus the application's top frame.
2029 """
2030 parent = wx.GetApp().GetTopWindow()
2031 focusWindow = wx.Window_FindFocus()
2032 if focusWindow:
2033 while focusWindow and not isinstance(focusWindow, wx.Dialog) and not isinstance(focusWindow, wx.Frame):
2034 focusWindow = focusWindow.GetParent()
2035 if focusWindow:
2036 parent = focusWindow
2037 return parent
2038
2039
2040 def SelectDocumentPath(self, templates, flags, save):
2041 """
2042 Under Windows, pops up a file selector with a list of filters
2043 corresponding to document templates. The wxDocTemplate corresponding
2044 to the selected file's extension is returned.
2045
2046 On other platforms, if there is more than one document template a
2047 choice list is popped up, followed by a file selector.
2048
2049 This function is used in wxDocManager.CreateDocument.
2050 """
2051 if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__":
2052 allfilter = ''
2053 descr = ''
2054 for temp in templates:
2055 if temp.IsVisible():
2056 if len(descr) > 0:
2057 descr = descr + _('|')
2058 allfilter = allfilter + _(';')
2059 descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
2060 allfilter = allfilter + temp.GetFileFilter()
2061 descr = _("All") + _(" (") + allfilter + _(") |") + allfilter + _('|') + descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
2062 else:
2063 descr = _("*.*")
2064
2065 path = wx.FileSelector(_("Select a File"),
2066 self._lastDirectory,
2067 _(""),
2068 wildcard = descr,
2069 flags = wx.HIDE_READONLY,
2070 parent = self.FindSuitableParent())
2071 if path:
2072 if not FileExists(path):
2073 msgTitle = wx.GetApp().GetAppName()
2074 if not msgTitle:
2075 msgTitle = _("File Error")
2076 wx.MessageBox("Could not open '%s'." % FileNameFromPath(path),
2077 msgTitle,
2078 wx.OK | wx.ICON_EXCLAMATION,
2079 parent)
2080 return (None, None)
2081 self._lastDirectory = PathOnly(path)
2082
2083 theTemplate = self.FindTemplateForPath(path)
2084 return (theTemplate, path)
2085
2086 return (None, None)
2087
2088
2089 def OnOpenFileFailure(self):
2090 """
2091 Called when there is an error opening a file.
2092 """
2093 pass
2094
2095
2096 def SelectDocumentType(self, temps, sort = False):
2097 """
2098 Returns a document template by asking the user (if there is more than
2099 one template). This function is used in wxDocManager.CreateDocument.
2100
2101 Parameters
2102
2103 templates - list of templates from which to choose a desired template.
2104
2105 sort - If more than one template is passed in in templates, then this
2106 parameter indicates whether the list of templates that the user will
2107 have to choose from is sorted or not when shown the choice box dialog.
2108 Default is false.
2109 """
2110 templates = []
2111 for temp in temps:
2112 if temp.IsVisible():
2113 want = True
2114 for temp2 in templates:
2115 if temp.GetDocumentName() == temp2.GetDocumentName() and temp.GetViewName() == temp2.GetViewName():
2116 want = False
2117 break
2118 if want:
2119 templates.append(temp)
2120
2121 if len(templates) == 0:
2122 return None
2123 elif len(templates) == 1:
2124 return template[0]
2125
2126 if sort:
2127 def tempcmp(a, b):
2128 return cmp(a.GetDescription(), b.GetDescription())
2129 templates.sort(tempcmp)
2130
2131 strings = []
2132 for temp in templates:
2133 strings.append(temp.GetDescription())
2134
2135 res = wx.GetSingleChoiceIndex(_("Select a document type:"),
2136 _("Documents"),
2137 strings,
2138 self.FindSuitableParent())
2139 if res == -1:
2140 return None
2141 return templates[res]
2142
2143
2144 def SelectViewType(self, temps, sort = False):
2145 """
2146 Returns a document template by asking the user (if there is more than one template), displaying a list of valid views. This function is used in wxDocManager::CreateView. The dialog normally will not appear because the array of templates only contains those relevant to the document in question, and often there will only be one such.
2147 """
2148 templates = []
2149 strings = []
2150 for temp in temps:
2151 if temp.IsVisible() and temp.GetViewTypeName():
2152 if temp.GetViewName() not in strings:
2153 templates.append(temp)
2154 strings.append(temp.GetViewTypeName())
2155
2156 if len(templates) == 0:
2157 return None
2158 elif len(templates) == 1:
2159 return templates[0]
2160
2161 if sort:
2162 def tempcmp(a, b):
2163 return cmp(a.GetViewTypeName(), b.GetViewTypeName())
2164 templates.sort(tempcmp)
2165
2166 res = wx.GetSingleChoiceIndex(_("Select a document view:"),
2167 _("Views"),
2168 strings,
2169 self.FindSuitableParent())
2170 if res == -1:
2171 return None
2172 return templates[res]
2173
2174
2175 def GetTemplates(self):
2176 """
2177 Returns the document manager's template list. This method has been added to
2178 wxPython and is not in wxWindows.
2179 """
2180 return self._templates
2181
2182
2183 def AssociateTemplate(self, docTemplate):
2184 """
2185 Adds the template to the document manager's template list.
2186 """
2187 if docTemplate not in self._templates:
2188 self._templates.append(docTemplate)
2189
2190
2191 def DisassociateTemplate(self, docTemplate):
2192 """
2193 Removes the template from the list of templates.
2194 """
2195 self._templates.remove(docTemplate)
2196
2197
2198 def AddDocument(self, document):
2199 """
2200 Adds the document to the list of documents.
2201 """
2202 if document not in self._docs:
2203 self._docs.append(document)
2204
2205
2206 def RemoveDocument(self, doc):
2207 """
2208 Removes the document from the list of documents.
2209 """
2210 if doc in self._docs:
2211 self._docs.remove(doc)
2212
2213
2214 def ActivateView(self, view, activate = True, deleting = False):
2215 """
2216 Sets the current view.
2217 """
2218 if activate:
2219 self._currentView = view
2220 self._lastActiveView = view
2221 else:
2222 self._currentView = None
2223
2224
2225 def GetMaxDocsOpen(self):
2226 """
2227 Returns the number of documents that can be open simultaneously.
2228 """
2229 return self._maxDocsOpen
2230
2231
2232 def SetMaxDocsOpen(self, maxDocsOpen):
2233 """
2234 Sets the maximum number of documents that can be open at a time. By
2235 default, this is 10,000. If you set it to 1, existing documents will
2236 be saved and deleted when the user tries to open or create a new one
2237 (similar to the behaviour of Windows Write, for example). Allowing
2238 multiple documents gives behaviour more akin to MS Word and other
2239 Multiple Document Interface applications.
2240 """
2241 self._maxDocsOpen = maxDocsOpen
2242
2243
2244 def GetDocuments(self):
2245 """
2246 Returns the list of documents.
2247 """
2248 return self._docs
2249
2250
2251 class DocParentFrame(wx.Frame):
2252 """
2253 The wxDocParentFrame class provides a default top-level frame for
2254 applications using the document/view framework. This class can only be
2255 used for SDI (not MDI) parent frames.
2256
2257 It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplates
2258 classes.
2259 """
2260
2261 def __init__(self, manager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"):
2262 """
2263 Constructor. Note that the event table must be rebuilt for the
2264 frame since the EvtHandler is not virtual.
2265 """
2266 wx.Frame.__init__(self, frame, id, title, pos, size, style)
2267 self._docManager = manager
2268
2269 wx.EVT_CLOSE(self, self.OnCloseWindow)
2270
2271 wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
2272 wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
2273
2274 wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
2275 wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
2276 wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
2277 wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
2278 wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
2279 wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
2280 wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
2281 wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
2282 wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
2283 wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
2284 wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
2285 wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
2286
2287 wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
2288 wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
2289 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
2290 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
2291 wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
2292 wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
2293 wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
2294 wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
2295 wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
2296 wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
2297 wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
2298 wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
2299
2300
2301 def ProcessEvent(self, event):
2302 """
2303 Processes an event, searching event tables and calling zero or more
2304 suitable event handler function(s). Note that the ProcessEvent
2305 method is called from the wxPython docview framework directly since
2306 wxPython does not have a virtual ProcessEvent function.
2307 """
2308 return self._docManager and self._docManager.ProcessEvent(event)
2309
2310
2311 def ProcessUpdateUIEvent(self, event):
2312 """
2313 Processes a UI event, searching event tables and calling zero or more
2314 suitable event handler function(s). Note that the ProcessEvent
2315 method is called from the wxPython docview framework directly since
2316 wxPython does not have a virtual ProcessEvent function.
2317 """
2318 return self._docManager and self._docManager.ProcessUpdateUIEvent(event)
2319
2320
2321 def OnExit(self, event):
2322 """
2323 Called when File/Exit is chosen and closes the window.
2324 """
2325 self.Close()
2326
2327
2328 def OnMRUFile(self, event):
2329 """
2330 Opens the appropriate file when it is selected from the file history
2331 menu.
2332 """
2333 n = event.GetId() - wx.ID_FILE1
2334 filename = self._docManager.GetHistoryFile(n)
2335 if filename:
2336 self._docManager.CreateDocument(filename, DOC_SILENT)
2337 else:
2338 self._docManager.RemoveFileFromHistory(n)
2339 msgTitle = wx.GetApp().GetAppName()
2340 if not msgTitle:
2341 msgTitle = _("File Error")
2342 wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % FileNameFromPath(file),
2343 msgTitle,
2344 wx.OK | wx.ICON_EXCLAMATION,
2345 self)
2346
2347
2348 def OnCloseWindow(self, event):
2349 """
2350 Deletes all views and documents. If no user input cancelled the
2351 operation, the frame will be destroyed and the application will exit.
2352 """
2353 if self._docManager.Clear(not event.CanVeto()):
2354 self.Destroy()
2355 else:
2356 event.Veto()
2357
2358
2359 class DocChildFrame(wx.Frame):
2360 """
2361 The wxDocChildFrame class provides a default frame for displaying
2362 documents on separate windows. This class can only be used for SDI (not
2363 MDI) child frames.
2364
2365 The class is part of the document/view framework supported by wxWindows,
2366 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
2367 classes.
2368 """
2369
2370
2371 def __init__(self, doc, view, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"):
2372 """
2373 Constructor. Note that the event table must be rebuilt for the
2374 frame since the EvtHandler is not virtual.
2375 """
2376 wx.Frame.__init__(self, frame, id, title, pos, size, style, name)
2377 wx.EVT_ACTIVATE(self, self.OnActivate)
2378 wx.EVT_CLOSE(self, self.OnCloseWindow)
2379 self._childDocument = doc
2380 self._childView = view
2381 if view:
2382 view.SetFrame(self)
2383
2384 wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
2385 wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
2386 wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
2387 wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
2388 wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
2389 wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
2390 wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
2391 wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
2392 wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
2393 wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
2394 wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
2395 wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
2396
2397 wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
2398 wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
2399 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
2400 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
2401 wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
2402 wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
2403 wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
2404 wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
2405 wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
2406 wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
2407 wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
2408 wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
2409
2410
2411 def ProcessEvent(self, event):
2412 """
2413 Processes an event, searching event tables and calling zero or more
2414 suitable event handler function(s). Note that the ProcessEvent
2415 method is called from the wxPython docview framework directly since
2416 wxPython does not have a virtual ProcessEvent function.
2417 """
2418 if self._childView:
2419 self._childView.Activate(True)
2420 if not self._childView or not self._childView.ProcessEvent(event):
2421 # IsInstance not working, but who cares just send all the commands up since this isn't a real ProcessEvent like wxWindows
2422 # if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
2423 if not self.GetParent() or not self.GetParent().ProcessEvent(event):
2424 return False
2425 else:
2426 return True
2427 else:
2428 return True
2429
2430
2431 def ProcessUpdateUIEvent(self, event):
2432 """
2433 Processes a UI event, searching event tables and calling zero or more
2434 suitable event handler function(s). Note that the ProcessEvent
2435 method is called from the wxPython docview framework directly since
2436 wxPython does not have a virtual ProcessEvent function.
2437 """
2438 if self.GetParent():
2439 self.GetParent().ProcessUpdateUIEvent(event)
2440 else:
2441 return False
2442
2443
2444 def OnActivate(self, event):
2445 """
2446 Activates the current view.
2447 """
2448 # wx.Frame.OnActivate(event) This is in the wxWindows docview demo but there is no such method in wxPython, so do a Raise() instead
2449 if self._childView:
2450 self._childView.Activate(event.GetActive())
2451
2452
2453 def OnCloseWindow(self, event):
2454 """
2455 Closes and deletes the current view and document.
2456 """
2457 if self._childView:
2458 ans = False
2459 if not event.CanVeto():
2460 ans = True
2461 else:
2462 ans = self._childView.Close(deleteWindow = False)
2463
2464 if ans:
2465 self._childView.Activate(False)
2466 self._childView.Destroy()
2467 self._childView = None
2468 if self._childDocument:
2469 self._childDocument.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
2470 self._childDocument = None
2471 self.Destroy()
2472 else:
2473 event.Veto()
2474 else:
2475 event.Veto()
2476
2477
2478 def GetDocument(self):
2479 """
2480 Returns the document associated with this frame.
2481 """
2482 return self._childDocument
2483
2484
2485 def SetDocument(self, document):
2486 """
2487 Sets the document for this frame.
2488 """
2489 self._childDocument = document
2490
2491
2492 def GetView(self):
2493 """
2494 Returns the view associated with this frame.
2495 """
2496 return self._childView
2497
2498
2499 def SetView(self, view):
2500 """
2501 Sets the view for this frame.
2502 """
2503 self._childView = view
2504
2505
2506 class DocMDIParentFrame(wx.MDIParentFrame):
2507 """
2508 The wxDocMDIParentFrame class provides a default top-level frame for
2509 applications using the document/view framework. This class can only be
2510 used for MDI parent frames.
2511
2512 It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
2513 classes.
2514 """
2515
2516
2517 def __init__(self, manager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"):
2518 """
2519 Constructor. Note that the event table must be rebuilt for the
2520 frame since the EvtHandler is not virtual.
2521 """
2522 wx.MDIParentFrame.__init__(self, frame, id, title, pos, size, style, name)
2523 self._docManager = manager
2524
2525 wx.EVT_CLOSE(self, self.OnCloseWindow)
2526
2527 wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
2528 wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
2529
2530 wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
2531 wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
2532 wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
2533 wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
2534 wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
2535 wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
2536 wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
2537 wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
2538 wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
2539 wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
2540 wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
2541 wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
2542
2543 wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
2544 wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
2545 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
2546 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
2547 wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
2548 wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
2549 wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
2550 wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
2551 wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
2552 wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
2553 wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
2554 wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
2555
2556
2557 def ProcessEvent(self, event):
2558 """
2559 Processes an event, searching event tables and calling zero or more
2560 suitable event handler function(s). Note that the ProcessEvent
2561 method is called from the wxPython docview framework directly since
2562 wxPython does not have a virtual ProcessEvent function.
2563 """
2564 return self._docManager and self._docManager.ProcessEvent(event)
2565
2566
2567 def ProcessUpdateUIEvent(self, event):
2568 """
2569 Processes a UI event, searching event tables and calling zero or more
2570 suitable event handler function(s). Note that the ProcessEvent
2571 method is called from the wxPython docview framework directly since
2572 wxPython does not have a virtual ProcessEvent function.
2573 """
2574 return self._docManager and self._docManager.ProcessUpdateUIEvent(event)
2575
2576
2577 def OnExit(self, event):
2578 """
2579 Called when File/Exit is chosen and closes the window.
2580 """
2581 self.Close()
2582
2583
2584 def OnMRUFile(self, event):
2585 """
2586 Opens the appropriate file when it is selected from the file history
2587 menu.
2588 """
2589 n = event.GetId() - wx.ID_FILE1
2590 filename = self._docManager.GetHistoryFile(n)
2591 if filename:
2592 self._docManager.CreateDocument(filename, DOC_SILENT)
2593 else:
2594 self._docManager.RemoveFileFromHistory(n)
2595 msgTitle = wx.GetApp().GetAppName()
2596 if not msgTitle:
2597 msgTitle = _("File Error")
2598 wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % FileNameFromPath(file),
2599 msgTitle,
2600 wx.OK | wx.ICON_EXCLAMATION,
2601 self)
2602
2603
2604 def OnCloseWindow(self, event):
2605 """
2606 Deletes all views and documents. If no user input cancelled the
2607 operation, the frame will be destroyed and the application will exit.
2608 """
2609 if self._docManager.Clear(not event.CanVeto()):
2610 self.Destroy()
2611 else:
2612 event.Veto()
2613
2614
2615 class DocMDIChildFrame(wx.MDIChildFrame):
2616 """
2617 The wxDocMDIChildFrame class provides a default frame for displaying
2618 documents on separate windows. This class can only be used for MDI child
2619 frames.
2620
2621 The class is part of the document/view framework supported by wxWindows,
2622 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
2623 classes.
2624 """
2625
2626
2627 def __init__(self, doc, view, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"):
2628 """
2629 Constructor. Note that the event table must be rebuilt for the
2630 frame since the EvtHandler is not virtual.
2631 """
2632 wx.MDIChildFrame.__init__(self, frame, id, title, pos, size, style, name)
2633 self._childDocument = doc
2634 self._childView = view
2635 if view:
2636 view.SetFrame(self)
2637 # self.Create(doc, view, frame, id, title, pos, size, style, name)
2638 self._activeEvent = None
2639 self._activated = 0
2640 wx.EVT_ACTIVATE(self, self.OnActivate)
2641 wx.EVT_CLOSE(self, self.OnCloseWindow)
2642
2643 if frame: # wxBug: For some reason the EVT_ACTIVATE event is not getting triggered for the first mdi client window that is opened so we have to do it manually
2644 mdiChildren = filter(lambda x: isinstance(x, wx.MDIChildFrame), frame.GetChildren())
2645 if len(mdiChildren) == 1:
2646 self.Activate()
2647
2648
2649 ## # Couldn't get this to work, but seems to work fine with single stage construction
2650 ## def Create(self, doc, view, frame, id, title, pos, size, style, name):
2651 ## self._childDocument = doc
2652 ## self._childView = view
2653 ## if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
2654 ## if view:
2655 ## view.SetFrame(self)
2656 ## return True
2657 ## return False
2658
2659
2660
2661 def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
2662 """
2663 Activates the current view.
2664 """
2665 if self._childView:
2666 self._childView.Activate(True)
2667
2668
2669 def ProcessEvent(event):
2670 """
2671 Processes an event, searching event tables and calling zero or more
2672 suitable event handler function(s). Note that the ProcessEvent
2673 method is called from the wxPython docview framework directly since
2674 wxPython does not have a virtual ProcessEvent function.
2675 """
2676 if self._activeEvent == event:
2677 return False
2678
2679 self._activeEvent = event # Break recursion loops
2680
2681 if self._childView:
2682 self._childView.Activate(True)
2683
2684 if not self._childView or not self._childView.ProcessEvent(event):
2685 if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
2686 ret = False
2687 else:
2688 ret = True
2689 else:
2690 ret = True
2691
2692 self._activeEvent = None
2693 return ret
2694
2695
2696 def OnActivate(self, event):
2697 """
2698 Sets the currently active view to be the frame's view. You may need to
2699 override (but still call) this function in order to set the keyboard
2700 focus for your subwindow.
2701 """
2702 if self._activated != 0:
2703 return True
2704 self._activated += 1
2705 wx.MDIChildFrame.Activate(self)
2706 if event.GetActive() and self._childView:
2707 self._childView.Activate(event.GetActive())
2708 self._activated = 0
2709
2710 def OnCloseWindow(self, event):
2711 """
2712 Closes and deletes the current view and document.
2713 """
2714 if self._childView:
2715 ans = False
2716 if not event.CanVeto():
2717 ans = True
2718 else:
2719 ans = self._childView.Close(deleteWindow = False)
2720
2721 if ans:
2722 self._childView.Activate(False)
2723 self._childView.Destroy()
2724 self._childView = None
2725 if self._childDocument:
2726 self._childDocument.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
2727 self._childDocument = None
2728 self.Destroy()
2729 else:
2730 event.Veto()
2731 else:
2732 event.Veto()
2733
2734
2735 def GetDocument(self):
2736 """
2737 Returns the document associated with this frame.
2738 """
2739 return self._childDocument
2740
2741
2742 def SetDocument(self, document):
2743 """
2744 Sets the document for this frame.
2745 """
2746 self._childDocument = document
2747
2748
2749 def GetView(self):
2750 """
2751 Returns the view associated with this frame.
2752 """
2753 return self._childView
2754
2755
2756 def SetView(self, view):
2757 """
2758 Sets the view for this frame.
2759 """
2760 self._childView = view
2761
2762
2763 class DocPrintout(wx.Printout):
2764 """
2765 DocPrintout is a default Printout that prints the first page of a document
2766 view.
2767 """
2768
2769
2770 def __init__(self, view, title = "Printout"):
2771 """
2772 Constructor.
2773 """
2774 wx.Printout.__init__(self)
2775 self._printoutView = view
2776
2777
2778 def GetView(self):
2779 """
2780 Returns the DocPrintout's view.
2781 """
2782 return self._printoutView
2783
2784
2785 def OnPrintPage(self, page):
2786 """
2787 Prints the first page of the view.
2788 """
2789 dc = self.GetDC()
2790 ppiScreenX, ppiScreenY = self.GetPPIScreen()
2791 ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
2792 scale = ppiPrinterX/ppiScreenX
2793 w, h = dc.GetSize()
2794 pageWidth, pageHeight = self.GetPageSizePixels()
2795 overallScale = scale * w / pageWidth
2796 dc.SetUserScale(overallScale, overallScale)
2797 if self._printoutView:
2798 self._printoutView.OnDraw(dc)
2799 return True
2800
2801
2802 def HasPage(self, pageNum):
2803 """
2804 Indicates that the DocPrintout only has a single page.
2805 """
2806 return pageNum == 1
2807
2808
2809 def OnBeginDocument(self, startPage, endPage):
2810 """
2811 Not quite sure why this was overridden, but it was in wxWindows! :)
2812 """
2813 if not wx.Printout.base_OnBeginDocument(self, startPage, endPage):
2814 return False
2815 return True
2816
2817
2818 def GetPageInfo(self):
2819 """
2820 Indicates that the DocPrintout only has a single page.
2821 """
2822 minPage = 1
2823 maxPage = 1
2824 selPageFrom = 1
2825 selPageTo = 1
2826 return (minPage, maxPage, selPageFrom, selPageTo)
2827
2828
2829 #----------------------------------------------------------------------
2830 # Command Classes
2831 #----------------------------------------------------------------------
2832
2833 class Command(wx.Object):
2834 """
2835 wxCommand is a base class for modelling an application command, which is
2836 an action usually performed by selecting a menu item, pressing a toolbar
2837 button or any other means provided by the application to change the data
2838 or view.
2839 """
2840
2841
2842 def __init__(self, canUndo = False, name = None):
2843 """
2844 Constructor. wxCommand is an abstract class, so you will need to
2845 derive a new class and call this constructor from your own constructor.
2846
2847 canUndo tells the command processor whether this command is undo-able.
2848 You can achieve the same functionality by overriding the CanUndo member
2849 function (if for example the criteria for undoability is context-
2850 dependent).
2851
2852 name must be supplied for the command processor to display the command
2853 name in the application's edit menu.
2854 """
2855 self._canUndo = canUndo
2856 self._name = name
2857
2858
2859 def CanUndo(self):
2860 """
2861 Returns true if the command can be undone, false otherwise.
2862 """
2863 return self._canUndo
2864
2865
2866 def GetName(self):
2867 """
2868 Returns the command name.
2869 """
2870 return self._name
2871
2872
2873 def Do(self):
2874 """
2875 Override this member function to execute the appropriate action when
2876 called. Return true to indicate that the action has taken place, false
2877 otherwise. Returning false will indicate to the command processor that
2878 the action is not undoable and should not be added to the command
2879 history.
2880 """
2881 return True
2882
2883
2884 def Undo(self):
2885 """
2886 Override this member function to un-execute a previous Do. Return true
2887 to indicate that the action has taken place, false otherwise. Returning
2888 false will indicate to the command processor that the action is not
2889 redoable and no change should be made to the command history.
2890
2891 How you implement this command is totally application dependent, but
2892 typical strategies include:
2893
2894 Perform an inverse operation on the last modified piece of data in the
2895 document. When redone, a copy of data stored in command is pasted back
2896 or some operation reapplied. This relies on the fact that you know the
2897 ordering of Undos; the user can never Undo at an arbitrary position in
2898 he command history.
2899
2900 Restore the entire document state (perhaps using document
2901 transactioning). Potentially very inefficient, but possibly easier to
2902 code if the user interface and data are complex, and an 'inverse
2903 execute' operation is hard to write.
2904 """
2905 return True
2906
2907
2908 class CommandProcessor(wx.Object):
2909 """
2910 wxCommandProcessor is a class that maintains a history of wxCommands, with
2911 undo/redo functionality built-in. Derive a new class from this if you want
2912 different behaviour.
2913 """
2914
2915
2916 def __init__(self, maxCommands = -1):
2917 """
2918 Constructor. maxCommands may be set to a positive integer to limit
2919 the number of commands stored to it, otherwise (and by default) the
2920 list of commands can grow arbitrarily.
2921 """
2922 self._maxCommands = maxCommands
2923 self._editMenu = None
2924 self._undoAccelerator = _("Ctrl+Z")
2925 self._redoAccelerator = _("Ctrl+Y")
2926 self.ClearCommands()
2927
2928
2929 def _GetCurrentCommand(self):
2930 if len(self._commands) == 0:
2931 return None
2932 else:
2933 return self._commands[-1]
2934
2935
2936 def _GetCurrentRedoCommand(self):
2937 if len(self._redoCommands) == 0:
2938 return None
2939 else:
2940 return self._redoCommands[-1]
2941
2942
2943 def GetMaxCommands(self):
2944 """
2945 Returns the maximum number of commands that the command processor
2946 stores.
2947
2948 """
2949 return self._maxCommands
2950
2951
2952 def GetCommands(self):
2953 """
2954 Returns the list of commands.
2955 """
2956 return self._commands
2957
2958
2959 def ClearCommands(self):
2960 """
2961 Deletes all the commands in the list and sets the current command
2962 pointer to None.
2963 """
2964 self._commands = []
2965 self._redoCommands = []
2966
2967
2968 def GetEditMenu(self):
2969 """
2970 Returns the edit menu associated with the command processor.
2971 """
2972 return self._editMenu
2973
2974
2975 def SetEditMenu(self, menu):
2976 """
2977 Tells the command processor to update the Undo and Redo items on this
2978 menu as appropriate. Set this to NULL if the menu is about to be
2979 destroyed and command operations may still be performed, or the
2980 command processor may try to access an invalid pointer.
2981 """
2982 self._editMenu = menu
2983
2984
2985 def GetUndoAccelerator(self):
2986 """
2987 Returns the string that will be appended to the Undo menu item.
2988 """
2989 return self._undoAccelerator
2990
2991
2992 def SetUndoAccelerator(self, accel):
2993 """
2994 Sets the string that will be appended to the Redo menu item.
2995 """
2996 self._undoAccelerator = accel
2997
2998
2999 def GetRedoAccelerator(self):
3000 """
3001 Returns the string that will be appended to the Redo menu item.
3002 """
3003 return self._redoAccelerator
3004
3005
3006 def SetRedoAccelerator(self, accel):
3007 """
3008 Sets the string that will be appended to the Redo menu item.
3009 """
3010 self._redoAccelerator = accel
3011
3012
3013 def SetEditMenu(self, menu):
3014 """
3015 Tells the command processor to update the Undo and Redo items on this
3016 menu as appropriate. Set this to NULL if the menu is about to be
3017 destroyed and command operations may still be performed, or the
3018 command processor may try to access an invalid pointer.
3019 """
3020 self._editMenu = menu
3021
3022
3023 def SetMenuStrings(self):
3024 """
3025 Sets the menu labels according to the currently set menu and the
3026 current command state.
3027 """
3028 if self.GetEditMenu() != None:
3029 undoCommand = self._GetCurrentCommand()
3030 redoCommand = self._GetCurrentRedoCommand()
3031 undoItem = self.GetEditMenu().FindItemById(wx.ID_UNDO)
3032 redoItem = self.GetEditMenu().FindItemById(wx.ID_REDO)
3033 if self.GetUndoAccelerator():
3034 undoAccel = '\t' + self.GetUndoAccelerator()
3035 else:
3036 undoAccel = ''
3037 if self.GetRedoAccelerator():
3038 redoAccel = '\t' + self.GetRedoAccelerator()
3039 else:
3040 redoAccel = ''
3041 if undoCommand and undoItem and undoCommand.CanUndo():
3042 undoItem.SetText(_("Undo ") + undoCommand.GetName() + undoAccel)
3043 #elif undoCommand and not undoCommand.CanUndo():
3044 # undoItem.SetText(_("Can't Undo") + undoAccel)
3045 else:
3046 undoItem.SetText(_("Undo" + undoAccel))
3047 if redoCommand and redoItem:
3048 redoItem.SetText(_("Redo ") + redoCommand.GetName() + redoAccel)
3049 else:
3050 redoItem.SetText(_("Redo") + redoAccel)
3051
3052
3053 def CanUndo(self):
3054 """
3055 Returns true if the currently-active command can be undone, false
3056 otherwise.
3057 """
3058 if self._GetCurrentCommand() == None:
3059 return False
3060 return self._GetCurrentCommand().CanUndo()
3061
3062
3063 def CanRedo(self):
3064 """
3065 Returns true if the currently-active command can be redone, false
3066 otherwise.
3067 """
3068 return self._GetCurrentRedoCommand() != None
3069
3070
3071 def Submit(self, command, storeIt = True):
3072 """
3073 Submits a new command to the command processor. The command processor
3074 calls wxCommand::Do to execute the command; if it succeeds, the
3075 command is stored in the history list, and the associated edit menu
3076 (if any) updated appropriately. If it fails, the command is deleted
3077 immediately. Once Submit has been called, the passed command should
3078 not be deleted directly by the application.
3079
3080 storeIt indicates whether the successful command should be stored in
3081 the history list.
3082 """
3083 done = command.Do()
3084 if done and storeIt:
3085 self._commands.append(command)
3086 if self._maxCommands > -1:
3087 if len(self._commands) > self._maxCommands:
3088 del self._commands[0]
3089 return done
3090
3091
3092 def Redo(self):
3093 """
3094 Redoes the command just undone.
3095 """
3096 cmd = self._GetCurrentRedoCommand()
3097 if not cmd:
3098 return False
3099 done = cmd.Do()
3100 if done:
3101 self._commands.append(self._redoCommands.pop())
3102 return done
3103
3104
3105 def Undo(self):
3106 """
3107 Undoes the command just executed.
3108 """
3109 cmd = self._GetCurrentCommand()
3110 if not cmd:
3111 return False
3112 done = cmd.Undo()
3113 if done:
3114 self._redoCommands.append(self._commands.pop())
3115 return done
3116
3117