1 #----------------------------------------------------------------------------
3 # Purpose: Port of the wxWindows docview classes
9 # Copyright: (c) 2003-2005 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al)
10 # License: wxWindows license
11 #----------------------------------------------------------------------------
22 #----------------------------------------------------------------------
24 #----------------------------------------------------------------------
31 DEFAULT_DOCMAN_FLAGS
= DOC_SDI
& DOC_OPEN_ONCE
34 TEMPLATE_INVISIBLE
= 2
35 DEFAULT_TEMPLATE_FLAGS
= TEMPLATE_VISIBLE
40 #----------------------------------------------------------------------
41 # Convenience functions from wxWindows used in docview
42 #----------------------------------------------------------------------
45 def FileNameFromPath(path
):
47 Returns the filename for a full path.
49 return os
.path
.split(path
)[1]
51 def FindExtension(path
):
53 Returns the extension of a filename for a full path.
55 return os
.path
.splitext(path
)[1].lower()
59 Returns True if the path exists.
61 return os
.path
.isfile(path
)
65 Returns the path of a full path without the filename.
67 return os
.path
.split(path
)[0]
70 #----------------------------------------------------------------------
71 # Document/View Classes
72 #----------------------------------------------------------------------
75 class Document(wx
.EvtHandler
):
77 The document class can be used to model an application's file-based data. It
78 is part of the document/view framework supported by wxWindows, and cooperates
79 with the wxView, wxDocTemplate and wxDocManager classes.
81 Note this wxPython version also keeps track of the modification date of the
82 document and if it changes on disk outside of the application, we will warn the
83 user before saving to avoid clobbering the file.
87 def __init__(self
, parent
=None):
89 Constructor. Define your own default constructor to initialize
90 application-specific data.
92 wx
.EvtHandler
.__init
__(self
)
94 self
._documentParent
= parent
95 self
._documentTemplate
= None
96 self
._commandProcessor
= None
97 self
._savedYet
= False
98 self
._writeable
= True
100 self
._documentTitle
= None
101 self
._documentFile
= None
102 self
._documentTypeName
= None
103 self
._documentModified
= False
104 self
._documentModificationDate
= None
105 self
._documentViews
= []
108 def ProcessEvent(self
, event
):
110 Processes an event, searching event tables and calling zero or more
111 suitable event handler function(s). Note that the ProcessEvent
112 method is called from the wxPython docview framework directly since
113 wxPython does not have a virtual ProcessEvent function.
118 def GetFilename(self
):
120 Gets the filename associated with this document, or "" if none is
123 return self
._documentFile
128 Gets the title for this document. The document title is used for an
129 associated frame (if any), and is usually constructed by the framework
132 return self
._documentTitle
135 def SetTitle(self
, title
):
137 Sets the title for this document. The document title is used for an
138 associated frame (if any), and is usually constructed by the framework
141 self
._documentTitle
= title
144 def GetDocumentName(self
):
146 The document type name given to the wxDocTemplate constructor,
147 copied to this document when the document is created. If several
148 document templates are created that use the same document type, this
149 variable is used in wxDocManager::CreateView to collate a list of
150 alternative view types that can be used on this kind of document.
152 return self
._documentTypeName
155 def SetDocumentName(self
, name
):
157 Sets he document type name given to the wxDocTemplate constructor,
158 copied to this document when the document is created. If several
159 document templates are created that use the same document type, this
160 variable is used in wxDocManager::CreateView to collate a list of
161 alternative view types that can be used on this kind of document. Do
162 not change the value of this variable.
164 self
._documentTypeName
= name
167 def GetDocumentSaved(self
):
169 Returns True if the document has been saved. This method has been
170 added to wxPython and is not in wxWindows.
172 return self
._savedYet
175 def SetDocumentSaved(self
, saved
=True):
177 Sets whether the document has been saved. This method has been
178 added to wxPython and is not in wxWindows.
180 self
._savedYet
= saved
183 def GetCommandProcessor(self
):
185 Returns the command processor associated with this document.
187 return self
._commandProcessor
190 def SetCommandProcessor(self
, processor
):
192 Sets the command processor to be used for this document. The document
193 will then be responsible for its deletion. Normally you should not
194 call this; override OnCreateCommandProcessor instead.
196 self
._commandProcessor
= processor
199 def IsModified(self
):
201 Returns true if the document has been modified since the last save,
202 false otherwise. You may need to override this if your document view
203 maintains its own record of being modified (for example if using
204 wxTextWindow to view and edit the document).
206 return self
._documentModified
209 def Modify(self
, modify
):
211 Call with true to mark the document as modified since the last save,
212 false otherwise. You may need to override this if your document view
213 maintains its own record of being modified (for example if using
214 xTextWindow to view and edit the document).
216 self
._documentModified
= modify
219 def SetDocumentModificationDate(self
):
221 Saves the file's last modification date.
222 This is used to check if the file has been modified outside of the application.
223 This method has been added to wxPython and is not in wxWindows.
225 self
._documentModificationDate
= os
.path
.getmtime(self
.GetFilename())
228 def GetDocumentModificationDate(self
):
230 Returns the file's modification date when it was loaded from disk.
231 This is used to check if the file has been modified outside of the application.
232 This method has been added to wxPython and is not in wxWindows.
234 return self
._documentModificationDate
239 Returns the list whose elements are the views on the document.
241 return self
._documentViews
244 def GetDocumentTemplate(self
):
246 Returns the template that created the document.
248 return self
._documentTemplate
251 def SetDocumentTemplate(self
, template
):
253 Sets the template that created the document. Should only be called by
256 self
._documentTemplate
= template
259 def DeleteContents(self
):
261 Deletes the contents of the document. Override this method as
269 Destructor. Removes itself from the document manager.
271 self
.DeleteContents()
272 if self
.GetDocumentManager():
273 self
.GetDocumentManager().RemoveDocument(self
)
274 wx
.EvtHandler
.Destroy(self
)
279 Closes the document, by calling OnSaveModified and then (if this true)
280 OnCloseDocument. This does not normally delete the document object:
281 use DeleteAllViews to do this implicitly.
283 if self
.OnSaveModified():
284 if self
.OnCloseDocument():
292 def OnCloseDocument(self
):
294 The default implementation calls DeleteContents (an empty
295 implementation) sets the modified flag to false. Override this to
296 supply additional behaviour when the document is closed with Close.
299 self
.DeleteContents()
304 def DeleteAllViews(self
):
306 Calls wxView.Close and deletes each view. Deleting the final view will
307 implicitly delete the document itself, because the wxView destructor
308 calls RemoveView. This in turns calls wxDocument::OnChangedViewList,
309 whose default implemention is to save and delete the document if no
312 manager
= self
.GetDocumentManager()
313 for view
in self
._documentViews
:
316 if self
in manager
.GetDocuments():
321 def GetFirstView(self
):
323 A convenience function to get the first view for a document, because
324 in many cases a document will only have a single view.
326 if len(self
._documentViews
) == 0:
328 return self
._documentViews
[0]
331 def GetDocumentManager(self
):
333 Returns the associated document manager.
335 if self
._documentTemplate
:
336 return self
._documentTemplate
.GetDocumentManager()
340 def OnNewDocument(self
):
342 The default implementation calls OnSaveModified and DeleteContents,
343 makes a default title for the document, and notifies the views that
344 the filename (in fact, the title) has changed.
346 if not self
.OnSaveModified() or not self
.OnCloseDocument():
348 self
.DeleteContents()
350 self
.SetDocumentSaved(False)
351 name
= self
.GetDocumentManager().MakeDefaultName()
353 self
.SetFilename(name
, notifyViews
= True)
358 Saves the document by calling OnSaveDocument if there is an associated
359 filename, or SaveAs if there is no filename.
361 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?
364 """ check for file modification outside of application """
365 if os
.path
.exists(self
.GetFilename()) and os
.path
.getmtime(self
.GetFilename()) != self
.GetDocumentModificationDate():
366 msgTitle
= wx
.GetApp().GetAppName()
368 msgTitle
= _("Application")
369 res
= wx
.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self
.GetPrintableName(), msgTitle
, self
.GetPrintableName()),
371 wx
.YES_NO | wx
.CANCEL | wx
.ICON_QUESTION
,
372 self
.GetDocumentWindow())
378 else: # elif res == wx.CANCEL:
381 if not self
._documentFile
or not self
._savedYet
:
383 return self
.OnSaveDocument(self
._documentFile
)
388 Prompts the user for a file to save to, and then calls OnSaveDocument.
390 docTemplate
= self
.GetDocumentTemplate()
394 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
395 filename
= wx
.FileSelector(_("Save As"),
396 docTemplate
.GetDirectory(),
397 FileNameFromPath(self
.GetFilename()),
398 docTemplate
.GetDefaultExtension(),
400 flags
= wx
.SAVE | wx
.OVERWRITE_PROMPT
,
401 parent
= self
.GetDocumentWindow())
405 name
, ext
= os
.path
.splitext(filename
)
407 filename
+= '.' + docTemplate
.GetDefaultExtension()
409 self
.SetFilename(filename
)
410 self
.SetTitle(FileNameFromPath(filename
))
412 for view
in self
._documentViews
:
413 view
.OnChangeFilename()
415 if not self
.OnSaveDocument(filename
):
418 if docTemplate
.FileMatchesTemplate(filename
):
419 self
.GetDocumentManager().AddFileToHistory(filename
)
424 def OnSaveDocument(self
, filename
):
426 Constructs an output file for the given filename (which must
427 not be empty), and calls SaveObject. If SaveObject returns true, the
428 document is set to unmodified; otherwise, an error message box is
434 msgTitle
= wx
.GetApp().GetAppName()
436 msgTitle
= _("File Error")
438 backupFilename
= None
442 # if current file exists, move it to a safe place temporarily
443 if os
.path
.exists(filename
):
445 # Check if read-only.
446 if not os
.access(filename
, os
.W_OK
):
447 wx
.MessageBox("Could not save '%s'. No write permission to overwrite existing file." % FileNameFromPath(filename
),
449 wx
.OK | wx
.ICON_EXCLAMATION
,
450 self
.GetDocumentWindow())
454 backupFilename
= "%s.bak%s" % (filename
, i
)
455 while os
.path
.exists(backupFilename
):
457 backupFilename
= "%s.bak%s" % (filename
, i
)
458 shutil
.copy(filename
, backupFilename
)
461 fileObject
= file(filename
, 'w')
462 self
.SaveObject(fileObject
)
467 os
.remove(backupFilename
)
469 # for debugging purposes
471 traceback
.print_exc()
474 fileObject
.close() # file is still open, close it, need to do this before removal
476 # save failed, remove copied file
477 if backupFilename
and copied
:
478 os
.remove(backupFilename
)
480 wx
.MessageBox("Could not save '%s'. %s" % (FileNameFromPath(filename
), sys
.exc_value
),
482 wx
.OK | wx
.ICON_EXCLAMATION
,
483 self
.GetDocumentWindow())
486 self
.SetFilename(filename
, True)
488 self
.SetDocumentModificationDate()
489 self
.SetDocumentSaved(True)
490 #if wx.Platform == '__WXMAC__': # Not yet implemented in wxPython
491 # wx.FileName(file).MacSetDefaultTypeAndCreator()
495 def OnOpenDocument(self
, filename
):
497 Constructs an input file for the given filename (which must not
498 be empty), and calls LoadObject. If LoadObject returns true, the
499 document is set to unmodified; otherwise, an error message box is
500 displayed. The document's views are notified that the filename has
501 changed, to give windows an opportunity to update their titles. All of
502 the document's views are then updated.
504 if not self
.OnSaveModified():
507 msgTitle
= wx
.GetApp().GetAppName()
509 msgTitle
= _("File Error")
511 fileObject
= file(filename
, 'r')
513 self
.LoadObject(fileObject
)
517 # for debugging purposes
519 traceback
.print_exc()
522 fileObject
.close() # file is still open, close it
524 wx
.MessageBox("Could not open '%s'. %s" % (FileNameFromPath(filename
), sys
.exc_value
),
526 wx
.OK | wx
.ICON_EXCLAMATION
,
527 self
.GetDocumentWindow())
530 self
.SetFilename(filename
, True)
532 self
.SetDocumentModificationDate()
533 self
.SetDocumentSaved(True)
534 self
.UpdateAllViews()
538 def LoadObject(self
, file):
540 Override this function and call it from your own LoadObject before
541 loading your own data. LoadObject is called by the framework
542 automatically when the document contents need to be loaded.
544 Note that the wxPython version simply sends you a Python file object,
545 so you can use pickle.
550 def SaveObject(self
, file):
552 Override this function and call it from your own SaveObject before
553 saving your own data. SaveObject is called by the framework
554 automatically when the document contents need to be saved.
556 Note that the wxPython version simply sends you a Python file object,
557 so you can use pickle.
564 Override this function to revert the document to its last saved state.
569 def GetPrintableName(self
):
571 Copies a suitable document name into the supplied name buffer.
572 The default function uses the title, or if there is no title, uses the
573 filename; or if no filename, the string 'Untitled'.
575 if self
._documentTitle
:
576 return self
._documentTitle
577 elif self
._documentFile
:
578 return FileNameFromPath(self
._documentFile
)
583 def GetDocumentWindow(self
):
585 Intended to return a suitable window for using as a parent for
586 document-related dialog boxes. By default, uses the frame associated
589 if len(self
._documentViews
) > 0:
590 return self
._documentViews
[0].GetFrame()
592 return wx
.GetApp().GetTopWindow()
595 def OnCreateCommandProcessor(self
):
597 Override this function if you want a different (or no) command
598 processor to be created when the document is created. By default, it
599 returns an instance of wxCommandProcessor.
601 return CommandProcessor()
604 def OnSaveModified(self
):
606 If the document has been modified, prompts the user to ask if the
607 changes should be changed. If the user replies Yes, the Save function
608 is called. If No, the document is marked as unmodified and the
609 function succeeds. If Cancel, the function fails.
611 if not self
.IsModified():
614 """ check for file modification outside of application """
615 if os
.path
.exists(self
.GetFilename()) and os
.path
.getmtime(self
.GetFilename()) != self
.GetDocumentModificationDate():
616 msgTitle
= wx
.GetApp().GetAppName()
618 msgTitle
= _("Warning")
619 res
= wx
.MessageBox(_("'%s' has been modified outside of %s. Overwrite '%s' with current changes?") % (self
.GetPrintableName(), msgTitle
, self
.GetPrintableName()),
621 wx
.YES_NO | wx
.CANCEL | wx
.ICON_QUESTION
,
622 self
.GetDocumentWindow())
628 return wx
.lib
.docview
.Document
.Save(self
)
629 else: # elif res == wx.CANCEL:
632 msgTitle
= wx
.GetApp().GetAppName()
634 msgTitle
= _("Warning")
636 res
= wx
.MessageBox(_("Save changes to '%s'?") % self
.GetPrintableName(),
638 wx
.YES_NO | wx
.CANCEL | wx
.ICON_QUESTION
,
639 self
.GetDocumentWindow())
646 else: # elif res == wx.CANCEL:
652 Called by printing framework to draw the view.
657 def AddView(self
, view
):
659 If the view is not already in the list of views, adds the view and
660 calls OnChangedViewList.
662 if not view
in self
._documentViews
:
663 self
._documentViews
.append(view
)
664 self
.OnChangedViewList()
668 def RemoveView(self
, view
):
670 Removes the view from the document's list of views, and calls
673 if view
in self
._documentViews
:
674 self
._documentViews
.remove(view
)
675 self
.OnChangedViewList()
679 def OnCreate(self
, path
, flags
):
681 The default implementation calls DeleteContents (an empty
682 implementation) sets the modified flag to false. Override this to
683 supply additional behaviour when the document is closed with Close.
685 return self
.GetDocumentTemplate().CreateView(self
, flags
)
688 def OnChangedViewList(self
):
690 Called when a view is added to or deleted from this document. The
691 default implementation saves and deletes the document if no views
692 exist (the last one has just been removed).
694 if len(self
._documentViews
) == 0:
695 if self
.OnSaveModified():
696 pass # C version does a delete but Python will garbage collect
699 def UpdateAllViews(self
, sender
= None, hint
= None):
701 Updates all views. If sender is non-NULL, does not update this view.
702 hint represents optional information to allow a view to optimize its
705 for view
in self
._documentViews
:
707 view
.OnUpdate(sender
, hint
)
710 def NotifyClosing(self
):
712 Notifies the views that the document is going to close.
714 for view
in self
._documentViews
:
715 view
.OnClosingDocument()
718 def SetFilename(self
, filename
, notifyViews
= False):
720 Sets the filename for this document. Usually called by the framework.
721 If notifyViews is true, wxView.OnChangeFilename is called for all
724 self
._documentFile
= filename
726 for view
in self
._documentViews
:
727 view
.OnChangeFilename()
730 def GetWriteable(self
):
732 Returns true if the document can be written to its accociated file path.
733 This method has been added to wxPython and is not in wxWindows.
735 if not self
._writeable
:
737 if not self
._documentFile
: # Doesn't exist, do a save as
740 return os
.access(self
._documentFile
, os
.W_OK
)
743 def SetWriteable(self
, writeable
):
745 Set to False if the document can not be saved. This will disable the ID_SAVE_AS
746 event and is useful for custom documents that should not be saveable. The ID_SAVE
747 event can be disabled by never Modifying the document. This method has been added
748 to wxPython and is not in wxWindows.
750 self
._writeable
= writeable
753 class View(wx
.EvtHandler
):
755 The view class can be used to model the viewing and editing component of
756 an application's file-based data. It is part of the document/view
757 framework supported by wxWindows, and cooperates with the wxDocument,
758 wxDocTemplate and wxDocManager classes.
763 Constructor. Define your own default constructor to initialize
764 application-specific data.
766 wx
.EvtHandler
.__init
__(self
)
767 self
._viewDocument
= None
768 self
._viewFrame
= None
773 Destructor. Removes itself from the document's list of views.
775 if self
._viewDocument
:
776 self
._viewDocument
.RemoveView(self
)
777 wx
.EvtHandler
.Destroy(self
)
780 def ProcessEvent(self
, event
):
782 Processes an event, searching event tables and calling zero or more
783 suitable event handler function(s). Note that the ProcessEvent
784 method is called from the wxPython docview framework directly since
785 wxPython does not have a virtual ProcessEvent function.
787 if not self
.GetDocument() or not self
.GetDocument().ProcessEvent(event
):
793 def ProcessUpdateUIEvent(self
, event
):
795 Processes a UI event, searching event tables and calling zero or more
796 suitable event handler function(s). Note that the ProcessEvent
797 method is called from the wxPython docview framework directly since
798 wxPython does not have a virtual ProcessEvent function.
803 def OnActivateView(self
, activate
, activeView
, deactiveView
):
805 Called when a view is activated by means of wxView::Activate. The
806 default implementation does nothing.
811 def OnClosingDocument(self
):
813 Override this to clean up the view when the document is being closed.
814 The default implementation does nothing.
819 def OnDraw(self
, dc
):
821 Override this to draw the view for the printing framework. The
822 default implementation does nothing.
827 def OnPrint(self
, dc
, info
):
829 Override this to print the view for the printing framework. The
830 default implementation calls View.OnDraw.
835 def OnUpdate(self
, sender
, hint
):
837 Called when the view should be updated. sender is a pointer to the
838 view that sent the update request, or NULL if no single view requested
839 the update (for instance, when the document is opened). hint is as yet
840 unused but may in future contain application-specific information for
841 making updating more efficient.
846 def OnChangeFilename(self
):
848 Called when the filename has changed. The default implementation
849 constructs a suitable title and sets the title of the view frame (if
853 appName
= wx
.GetApp().GetAppName()
854 if not self
.GetDocument():
860 if appName
and isinstance(self
.GetFrame(), DocChildFrame
): # Only need app name in title for SDI
861 title
= appName
+ _(" - ")
864 self
.GetFrame().SetTitle(title
+ self
.GetDocument().GetPrintableName())
867 def GetDocument(self
):
869 Returns the document associated with the view.
871 return self
._viewDocument
874 def SetDocument(self
, doc
):
876 Associates the given document with the view. Normally called by the
879 self
._viewDocument
= doc
884 def GetViewName(self
):
886 Gets the name associated with the view (passed to the wxDocTemplate
887 constructor). Not currently used by the framework.
889 return self
._viewTypeName
892 def SetViewName(self
, name
):
894 Sets the view type name. Should only be called by the framework.
896 self
._viewTypeName
= name
899 def Close(self
, deleteWindow
=True):
901 Closes the view by calling OnClose. If deleteWindow is true, this
902 function should delete the window associated with the view.
904 if self
.OnClose(deleteWindow
= deleteWindow
):
910 def Activate(self
, activate
=True):
912 Call this from your view frame's OnActivate member to tell the
913 framework which view is currently active. If your windowing system
914 doesn't call OnActivate, you may need to call this function from
915 OnMenuCommand or any place where you know the view must be active, and
916 the framework will need to get the current view.
918 The prepackaged view frame wxDocChildFrame calls wxView.Activate from
919 its OnActivate member and from its OnMenuCommand member.
921 if self
.GetDocument() and self
.GetDocumentManager():
922 self
.OnActivateView(activate
, self
, self
.GetDocumentManager().GetCurrentView())
923 self
.GetDocumentManager().ActivateView(self
, activate
)
926 def OnClose(self
, deleteWindow
=True):
928 Implements closing behaviour. The default implementation calls
929 wxDocument.Close to close the associated document. Does not delete the
930 view. The application may wish to do some cleaning up operations in
931 this function, if a call to wxDocument::Close succeeded. For example,
932 if your application's all share the same window, you need to
933 disassociate the window from the view and perhaps clear the window. If
934 deleteWindow is true, delete the frame associated with the view.
936 if self
.GetDocument():
937 return self
.GetDocument().Close()
942 def OnCreate(self
, doc
, flags
):
944 wxDocManager or wxDocument creates a wxView via a wxDocTemplate. Just
945 after the wxDocTemplate creates the wxView, it calls wxView::OnCreate.
946 In its OnCreate member function, the wxView can create a
947 wxDocChildFrame or a derived class. This wxDocChildFrame provides user
948 interface elements to view and/or edit the contents of the wxDocument.
950 By default, simply returns true. If the function returns false, the
951 view will be deleted.
956 def OnCreatePrintout(self
):
958 Returns a wxPrintout object for the purposes of printing. It should
959 create a new object every time it is called; the framework will delete
962 By default, this function returns an instance of wxDocPrintout, which
963 prints and previews one page by calling wxView.OnDraw.
965 Override to return an instance of a class other than wxDocPrintout.
967 return DocPrintout(self
, self
.GetDocument().GetPrintableName())
972 Gets the frame associated with the view (if any). Note that this
973 "frame" is not a wxFrame at all in the generic MDI implementation
974 which uses the notebook pages instead of the frames and this is why
975 this method returns a wxWindow and not a wxFrame.
977 return self
._viewFrame
980 def SetFrame(self
, frame
):
982 Sets the frame associated with this view. The application should call
983 this if possible, to tell the view about the frame. See GetFrame for
984 the explanation about the mismatch between the "Frame" in the method
985 name and the type of its parameter.
987 self
._viewFrame
= frame
990 def GetDocumentManager(self
):
992 Returns the document manager instance associated with this view.
994 if self
._viewDocument
:
995 return self
.GetDocument().GetDocumentManager()
1000 class DocTemplate(wx
.Object
):
1002 The wxDocTemplate class is used to model the relationship between a
1003 document class and a view class.
1007 def __init__(self
, manager
, description
, filter, dir, ext
, docTypeName
, viewTypeName
, docType
, viewType
, flags
=DEFAULT_TEMPLATE_FLAGS
, icon
=None):
1009 Constructor. Create instances dynamically near the start of your
1010 application after creating a wxDocManager instance, and before doing
1011 any document or view operations.
1013 manager is the document manager object which manages this template.
1015 description is a short description of what the template is for. This
1016 string will be displayed in the file filter list of Windows file
1019 filter is an appropriate file filter such as *.txt.
1021 dir is the default directory to use for file selectors.
1023 ext is the default file extension (such as txt).
1025 docTypeName is a name that should be unique for a given type of
1026 document, used for gathering a list of views relevant to a
1027 particular document.
1029 viewTypeName is a name that should be unique for a given view.
1031 docClass is a Python class. If this is not supplied, you will need to
1032 derive a new wxDocTemplate class and override the CreateDocument
1033 member to return a new document instance on demand.
1035 viewClass is a Python class. If this is not supplied, you will need to
1036 derive a new wxDocTemplate class and override the CreateView member to
1037 return a new view instance on demand.
1039 flags is a bit list of the following:
1040 wx.TEMPLATE_VISIBLE The template may be displayed to the user in
1043 wx.TEMPLATE_INVISIBLE The template may not be displayed to the user in
1046 wx.DEFAULT_TEMPLATE_FLAGS Defined as wxTEMPLATE_VISIBLE.
1048 self
._docManager
= manager
1049 self
._description
= description
1050 self
._fileFilter
= filter
1051 self
._directory
= dir
1052 self
._defaultExt
= ext
1053 self
._docTypeName
= docTypeName
1054 self
._viewTypeName
= viewTypeName
1055 self
._docType
= docType
1056 self
._viewType
= viewType
1060 self
._docManager
.AssociateTemplate(self
)
1063 def GetDefaultExtension(self
):
1065 Returns the default file extension for the document data, as passed to
1066 the document template constructor.
1068 return self
._defaultExt
1071 def SetDefaultExtension(self
, defaultExt
):
1073 Sets the default file extension.
1075 self
._defaultExt
= defaultExt
1078 def GetDescription(self
):
1080 Returns the text description of this template, as passed to the
1081 document template constructor.
1083 return self
._description
1086 def SetDescription(self
, description
):
1088 Sets the template description.
1090 self
._description
= description
1093 def GetDirectory(self
):
1095 Returns the default directory, as passed to the document template
1098 return self
._directory
1101 def SetDirectory(self
, dir):
1103 Sets the default directory.
1105 self
._directory
= dir
1108 def GetDocumentManager(self
):
1110 Returns the document manager instance for which this template was
1113 return self
._docManager
1116 def SetDocumentManager(self
, manager
):
1118 Sets the document manager instance for which this template was
1119 created. Should not be called by the application.
1121 self
._docManager
= manager
1124 def GetFileFilter(self
):
1126 Returns the file filter, as passed to the document template
1129 return self
._fileFilter
1132 def SetFileFilter(self
, filter):
1134 Sets the file filter.
1136 self
._fileFilter
= filter
1141 Returns the flags, as passed to the document template constructor.
1142 (see the constructor description for more details).
1147 def SetFlags(self
, flags
):
1149 Sets the internal document template flags (see the constructor
1150 description for more details).
1157 Returns the icon, as passed to the document template
1158 constructor. This method has been added to wxPython and is
1164 def SetIcon(self
, flags
):
1166 Sets the icon. This method has been added to wxPython and is not
1172 def GetDocumentType(self
):
1174 Returns the Python document class, as passed to the document template
1177 return self
._docType
1180 def GetViewType(self
):
1182 Returns the Python view class, as passed to the document template
1185 return self
._viewType
1188 def IsVisible(self
):
1190 Returns true if the document template can be shown in user dialogs,
1193 return (self
._flags
& TEMPLATE_VISIBLE
) == TEMPLATE_VISIBLE
1196 def GetDocumentName(self
):
1198 Returns the document type name, as passed to the document template
1201 return self
._docTypeName
1204 def GetViewName(self
):
1206 Returns the view type name, as passed to the document template
1209 return self
._viewTypeName
1212 def CreateDocument(self
, path
, flags
):
1214 Creates a new instance of the associated document class. If you have
1215 not supplied a class to the template constructor, you will need to
1216 override this function to return an appropriate document instance.
1218 doc
= self
._docType
()
1219 doc
.SetFilename(path
)
1220 doc
.SetDocumentTemplate(self
)
1221 self
.GetDocumentManager().AddDocument(doc
)
1222 doc
.SetCommandProcessor(doc
.OnCreateCommandProcessor())
1223 if doc
.OnCreate(path
, flags
):
1226 if doc
in self
.GetDocumentManager().GetDocuments():
1227 doc
.DeleteAllViews()
1231 def CreateView(self
, doc
, flags
):
1233 Creates a new instance of the associated document view. If you have
1234 not supplied a class to the template constructor, you will need to
1235 override this function to return an appropriate view instance.
1237 view
= self
._viewType
()
1238 view
.SetDocument(doc
)
1239 if view
.OnCreate(doc
, flags
):
1246 def FileMatchesTemplate(self
, path
):
1248 Returns True if the path's extension matches one of this template's
1249 file filter extensions.
1251 ext
= FindExtension(path
)
1252 if not ext
: return False
1253 return ext
in self
.GetFileFilter()
1254 # return self.GetDefaultExtension() == FindExtension(path)
1257 class DocManager(wx
.EvtHandler
):
1259 The wxDocManager class is part of the document/view framework supported by
1260 wxWindows, and cooperates with the wxView, wxDocument and wxDocTemplate
1264 def __init__(self
, flags
=DEFAULT_DOCMAN_FLAGS
, initialize
=True):
1266 Constructor. Create a document manager instance dynamically near the
1267 start of your application before doing any document or view operations.
1269 flags is used in the Python version to indicate whether the document
1270 manager is in DOC_SDI or DOC_MDI mode.
1272 If initialize is true, the Initialize function will be called to
1273 create a default history list object. If you derive from wxDocManager,
1274 you may wish to call the base constructor with false, and then call
1275 Initialize in your own constructor, to allow your own Initialize or
1276 OnCreateFileHistory functions to be called.
1279 wx
.EvtHandler
.__init
__(self
)
1281 self
._defaultDocumentNameCounter
= 1
1283 self
._currentView
= None
1284 self
._lastActiveView
= None
1285 self
._maxDocsOpen
= 10000
1286 self
._fileHistory
= None
1287 self
._templates
= []
1289 self
._lastDirectory
= ""
1294 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.OnFileOpen
)
1295 wx
.EVT_MENU(self
, wx
.ID_CLOSE
, self
.OnFileClose
)
1296 wx
.EVT_MENU(self
, wx
.ID_CLOSE_ALL
, self
.OnFileCloseAll
)
1297 wx
.EVT_MENU(self
, wx
.ID_REVERT
, self
.OnFileRevert
)
1298 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.OnFileNew
)
1299 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.OnFileSave
)
1300 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.OnFileSaveAs
)
1301 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.OnUndo
)
1302 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.OnRedo
)
1303 wx
.EVT_MENU(self
, wx
.ID_PRINT
, self
.OnPrint
)
1304 wx
.EVT_MENU(self
, wx
.ID_PRINT_SETUP
, self
.OnPrintSetup
)
1305 wx
.EVT_MENU(self
, wx
.ID_PREVIEW
, self
.OnPreview
)
1307 wx
.EVT_UPDATE_UI(self
, wx
.ID_OPEN
, self
.OnUpdateFileOpen
)
1308 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE
, self
.OnUpdateFileClose
)
1309 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE_ALL
, self
.OnUpdateFileCloseAll
)
1310 wx
.EVT_UPDATE_UI(self
, wx
.ID_REVERT
, self
.OnUpdateFileRevert
)
1311 wx
.EVT_UPDATE_UI(self
, wx
.ID_NEW
, self
.OnUpdateFileNew
)
1312 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.OnUpdateFileSave
)
1313 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVEAS
, self
.OnUpdateFileSaveAs
)
1314 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.OnUpdateUndo
)
1315 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.OnUpdateRedo
)
1316 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT
, self
.OnUpdatePrint
)
1317 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT_SETUP
, self
.OnUpdatePrintSetup
)
1318 wx
.EVT_UPDATE_UI(self
, wx
.ID_PREVIEW
, self
.OnUpdatePreview
)
1326 wx
.EvtHandler
.Destroy(self
)
1331 Returns the document manager's flags. This method has been
1332 added to wxPython and is not in wxWindows.
1337 def CloseDocument(self
, doc
, force
=True):
1339 Closes the specified document.
1341 if doc
.Close() or force
:
1342 doc
.DeleteAllViews()
1343 if doc
in self
._docs
:
1349 def CloseDocuments(self
, force
=True):
1351 Closes all currently opened documents.
1353 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
1354 if not self
.CloseDocument(document
, force
):
1356 document
.DeleteAllViews() # Implicitly delete the document when the last view is removed
1360 def Clear(self
, force
=True):
1362 Closes all currently opened document by callling CloseDocuments and
1363 clears the document manager's templates.
1365 if not self
.CloseDocuments(force
):
1367 self
._templates
= []
1371 def Initialize(self
):
1373 Initializes data; currently just calls OnCreateFileHistory. Some data
1374 cannot always be initialized in the constructor because the programmer
1375 must be given the opportunity to override functionality. In fact
1376 Initialize is called from the wxDocManager constructor, but this can
1377 be vetoed by passing false to the second argument, allowing the
1378 derived class's constructor to call Initialize, possibly calling a
1379 different OnCreateFileHistory from the default.
1381 The bottom line: if you're not deriving from Initialize, forget it and
1382 construct wxDocManager with no arguments.
1384 self
.OnCreateFileHistory()
1388 def OnCreateFileHistory(self
):
1390 A hook to allow a derived class to create a different type of file
1391 history. Called from Initialize.
1393 self
._fileHistory
= wx
.FileHistory()
1396 def OnFileClose(self
, event
):
1398 Closes and deletes the currently active document.
1400 doc
= self
.GetCurrentDocument()
1402 doc
.DeleteAllViews()
1403 if doc
in self
._docs
:
1404 self
._docs
.remove(doc
)
1407 def OnFileCloseAll(self
, event
):
1409 Closes and deletes all the currently opened documents.
1411 return self
.CloseDocuments(force
= False)
1414 def OnFileNew(self
, event
):
1416 Creates a new document and reads in the selected file.
1418 self
.CreateDocument('', DOC_NEW
)
1421 def OnFileOpen(self
, event
):
1423 Creates a new document and reads in the selected file.
1425 if not self
.CreateDocument('', DEFAULT_DOCMAN_FLAGS
):
1426 self
.OnOpenFileFailure()
1429 def OnFileRevert(self
, event
):
1431 Reverts the current document by calling wxDocument.Save for the current
1434 doc
= self
.GetCurrentDocument()
1440 def OnFileSave(self
, event
):
1442 Saves the current document by calling wxDocument.Save for the current
1445 doc
= self
.GetCurrentDocument()
1451 def OnFileSaveAs(self
, event
):
1453 Calls wxDocument.SaveAs for the current document.
1455 doc
= self
.GetCurrentDocument()
1461 def OnPrint(self
, event
):
1463 Prints the current document by calling its View's OnCreatePrintout
1466 view
= self
.GetCurrentView()
1470 printout
= view
.OnCreatePrintout()
1472 if not hasattr(self
, "printData"):
1473 self
.printData
= wx
.PrintData()
1474 self
.printData
.SetPaperId(wx
.PAPER_LETTER
)
1475 self
.printData
.SetPrintMode(wx
.PRINT_MODE_PRINTER
)
1477 pdd
= wx
.PrintDialogData(self
.printData
)
1478 printer
= wx
.Printer(pdd
)
1479 printer
.Print(view
.GetFrame(), printout
)
1482 def OnPrintSetup(self
, event
):
1484 Presents the print setup dialog.
1486 view
= self
.GetCurrentView()
1488 parentWin
= view
.GetFrame()
1490 parentWin
= wx
.GetApp().GetTopWindow()
1492 if not hasattr(self
, "printData"):
1493 self
.printData
= wx
.PrintData()
1494 self
.printData
.SetPaperId(wx
.PAPER_LETTER
)
1496 data
= wx
.PrintDialogData(self
.printData
)
1497 printDialog
= wx
.PrintDialog(parentWin
, data
)
1498 printDialog
.GetPrintDialogData().SetSetupDialog(True)
1499 printDialog
.ShowModal()
1501 # this makes a copy of the wx.PrintData instead of just saving
1502 # a reference to the one inside the PrintDialogData that will
1503 # be destroyed when the dialog is destroyed
1504 self
.printData
= wx
.PrintData(printDialog
.GetPrintDialogData().GetPrintData())
1506 printDialog
.Destroy()
1509 def OnPreview(self
, event
):
1511 Previews the current document by calling its View's OnCreatePrintout
1514 view
= self
.GetCurrentView()
1518 printout
= view
.OnCreatePrintout()
1520 if not hasattr(self
, "printData"):
1521 self
.printData
= wx
.PrintData()
1522 self
.printData
.SetPaperId(wx
.PAPER_LETTER
)
1523 self
.printData
.SetPrintMode(wx
.PRINT_MODE_PREVIEW
)
1525 data
= wx
.PrintDialogData(self
.printData
)
1526 # Pass two printout objects: for preview, and possible printing.
1527 preview
= wx
.PrintPreview(printout
, view
.OnCreatePrintout(), data
)
1528 if not preview
.Ok():
1529 wx
.MessageBox(_("Unable to display print preview."))
1531 # 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.
1532 mimicFrame
= wx
.GetApp().GetTopWindow()
1533 frame
= wx
.PreviewFrame(preview
, mimicFrame
, _("Print Preview"), mimicFrame
.GetPosition(), mimicFrame
.GetSize())
1534 frame
.SetIcon(mimicFrame
.GetIcon())
1535 frame
.SetTitle(_("%s - %s - Preview") % (mimicFrame
.GetTitle(), view
.GetDocument().GetPrintableName()))
1540 def OnUndo(self
, event
):
1542 Issues an Undo command to the current document's command processor.
1544 doc
= self
.GetCurrentDocument()
1547 if doc
.GetCommandProcessor():
1548 doc
.GetCommandProcessor().Undo()
1551 def OnRedo(self
, event
):
1553 Issues a Redo command to the current document's command processor.
1555 doc
= self
.GetCurrentDocument()
1558 if doc
.GetCommandProcessor():
1559 doc
.GetCommandProcessor().Redo()
1562 def OnUpdateFileOpen(self
, event
):
1564 Updates the user interface for the File Open command.
1569 def OnUpdateFileClose(self
, event
):
1571 Updates the user interface for the File Close command.
1573 event
.Enable(self
.GetCurrentDocument() != None)
1576 def OnUpdateFileCloseAll(self
, event
):
1578 Updates the user interface for the File Close All command.
1580 event
.Enable(self
.GetCurrentDocument() != None)
1583 def OnUpdateFileRevert(self
, event
):
1585 Updates the user interface for the File Revert command.
1587 event
.Enable(self
.GetCurrentDocument() != None)
1590 def OnUpdateFileNew(self
, event
):
1592 Updates the user interface for the File New command.
1597 def OnUpdateFileSave(self
, event
):
1599 Updates the user interface for the File Save command.
1601 doc
= self
.GetCurrentDocument()
1602 event
.Enable(doc
!= None and doc
.IsModified())
1605 def OnUpdateFileSaveAs(self
, event
):
1607 Updates the user interface for the File Save As command.
1609 event
.Enable(self
.GetCurrentDocument() != None and self
.GetCurrentDocument().GetWriteable())
1612 def OnUpdateUndo(self
, event
):
1614 Updates the user interface for the Undo command.
1616 doc
= self
.GetCurrentDocument()
1617 event
.Enable(doc
!= None and doc
.GetCommandProcessor() != None and doc
.GetCommandProcessor().CanUndo())
1618 if doc
and doc
.GetCommandProcessor():
1619 doc
.GetCommandProcessor().SetMenuStrings()
1621 event
.SetText(_("&Undo\tCtrl+Z"))
1624 def OnUpdateRedo(self
, event
):
1626 Updates the user interface for the Redo command.
1628 doc
= self
.GetCurrentDocument()
1629 event
.Enable(doc
!= None and doc
.GetCommandProcessor() != None and doc
.GetCommandProcessor().CanRedo())
1630 if doc
and doc
.GetCommandProcessor():
1631 doc
.GetCommandProcessor().SetMenuStrings()
1633 event
.SetText(_("&Redo\tCtrl+Y"))
1636 def OnUpdatePrint(self
, event
):
1638 Updates the user interface for the Print command.
1640 event
.Enable(self
.GetCurrentDocument() != None)
1643 def OnUpdatePrintSetup(self
, event
):
1645 Updates the user interface for the Print Setup command.
1650 def OnUpdatePreview(self
, event
):
1652 Updates the user interface for the Print Preview command.
1654 event
.Enable(self
.GetCurrentDocument() != None)
1657 def GetCurrentView(self
):
1659 Returns the currently active view.
1661 if self
._currentView
:
1662 return self
._currentView
1663 if len(self
._docs
) == 1:
1664 return self
._docs
[0].GetFirstView()
1668 def GetLastActiveView(self
):
1670 Returns the last active view. This is used in the SDI framework where dialogs can be mistaken for a view
1671 and causes the framework to deactivete the current view. This happens when something like a custom dialog box used
1672 to operate on the current view is shown.
1674 if len(self
._docs
) >= 1:
1675 return self
._lastActiveView
1680 def ProcessEvent(self
, event
):
1682 Processes an event, searching event tables and calling zero or more
1683 suitable event handler function(s). Note that the ProcessEvent
1684 method is called from the wxPython docview framework directly since
1685 wxPython does not have a virtual ProcessEvent function.
1687 view
= self
.GetCurrentView()
1689 if view
.ProcessEvent(event
):
1692 if id == wx
.ID_OPEN
:
1693 self
.OnFileOpen(event
)
1695 elif id == wx
.ID_CLOSE
:
1696 self
.OnFileClose(event
)
1698 elif id == wx
.ID_CLOSE_ALL
:
1699 self
.OnFileCloseAll(event
)
1701 elif id == wx
.ID_REVERT
:
1702 self
.OnFileRevert(event
)
1704 elif id == wx
.ID_NEW
:
1705 self
.OnFileNew(event
)
1707 elif id == wx
.ID_SAVE
:
1708 self
.OnFileSave(event
)
1710 elif id == wx
.ID_SAVEAS
:
1711 self
.OnFileSaveAs(event
)
1713 elif id == wx
.ID_UNDO
:
1716 elif id == wx
.ID_REDO
:
1719 elif id == wx
.ID_PRINT
:
1722 elif id == wx
.ID_PRINT_SETUP
:
1723 self
.OnPrintSetup(event
)
1725 elif id == wx
.ID_PREVIEW
:
1726 self
.OnPreview(event
)
1732 def ProcessUpdateUIEvent(self
, event
):
1734 Processes a UI event, searching event tables and calling zero or more
1735 suitable event handler function(s). Note that the ProcessEvent
1736 method is called from the wxPython docview framework directly since
1737 wxPython does not have a virtual ProcessEvent function.
1740 view
= self
.GetCurrentView()
1742 if view
.ProcessUpdateUIEvent(event
):
1744 if id == wx
.ID_OPEN
:
1745 self
.OnUpdateFileOpen(event
)
1747 elif id == wx
.ID_CLOSE
:
1748 self
.OnUpdateFileClose(event
)
1750 elif id == wx
.ID_CLOSE_ALL
:
1751 self
.OnUpdateFileCloseAll(event
)
1753 elif id == wx
.ID_REVERT
:
1754 self
.OnUpdateFileRevert(event
)
1756 elif id == wx
.ID_NEW
:
1757 self
.OnUpdateFileNew(event
)
1759 elif id == wx
.ID_SAVE
:
1760 self
.OnUpdateFileSave(event
)
1762 elif id == wx
.ID_SAVEAS
:
1763 self
.OnUpdateFileSaveAs(event
)
1765 elif id == wx
.ID_UNDO
:
1766 self
.OnUpdateUndo(event
)
1768 elif id == wx
.ID_REDO
:
1769 self
.OnUpdateRedo(event
)
1771 elif id == wx
.ID_PRINT
:
1772 self
.OnUpdatePrint(event
)
1774 elif id == wx
.ID_PRINT_SETUP
:
1775 self
.OnUpdatePrintSetup(event
)
1777 elif id == wx
.ID_PREVIEW
:
1778 self
.OnUpdatePreview(event
)
1784 def CreateDocument(self
, path
, flags
=0):
1786 Creates a new document in a manner determined by the flags parameter,
1789 wx.lib.docview.DOC_NEW Creates a fresh document.
1790 wx.lib.docview.DOC_SILENT Silently loads the given document file.
1792 If wx.lib.docview.DOC_NEW is present, a new document will be created and returned,
1793 possibly after asking the user for a template to use if there is more
1794 than one document template. If wx.lib.docview.DOC_SILENT is present, a new document
1795 will be created and the given file loaded into it. If neither of these
1796 flags is present, the user will be presented with a file selector for
1797 the file to load, and the template to use will be determined by the
1798 extension (Windows) or by popping up a template choice list (other
1801 If the maximum number of documents has been reached, this function
1802 will delete the oldest currently loaded document before creating a new
1805 wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE flag.
1808 for temp
in self
._templates
:
1809 if temp
.IsVisible():
1810 templates
.append(temp
)
1811 if len(templates
) == 0:
1814 if len(self
.GetDocuments()) >= self
._maxDocsOpen
:
1815 doc
= self
.GetDocuments()[0]
1816 if not self
.CloseDocument(doc
, False):
1820 if len(templates
) == 1:
1822 newDoc
= temp
.CreateDocument(path
, flags
)
1824 newDoc
.SetDocumentName(temp
.GetDocumentName())
1825 newDoc
.SetDocumentTemplate(temp
)
1826 newDoc
.OnNewDocument()
1829 temp
= self
.SelectDocumentType(templates
)
1831 newDoc
= temp
.CreateDocument(path
, flags
)
1833 newDoc
.SetDocumentName(temp
.GetDocumentName())
1834 newDoc
.SetDocumentTemplate(temp
)
1835 newDoc
.OnNewDocument()
1840 if path
and flags
& DOC_SILENT
:
1841 temp
= self
.FindTemplateForPath(path
)
1843 temp
, path
= self
.SelectDocumentPath(templates
, path
, flags
)
1846 if path
and self
.GetFlags() & DOC_OPEN_ONCE
:
1847 for document
in self
._docs
:
1848 if document
.GetFilename() and os
.path
.normcase(document
.GetFilename()) == os
.path
.normcase(path
):
1849 """ check for file modification outside of application """
1850 if os
.path
.exists(path
) and os
.path
.getmtime(path
) != document
.GetDocumentModificationDate():
1851 msgTitle
= wx
.GetApp().GetAppName()
1853 msgTitle
= _("Warning")
1854 shortName
= document
.GetPrintableName()
1855 res
= wx
.MessageBox(_("'%s' has been modified outside of %s. Reload '%s' from file system?") % (shortName
, msgTitle
, shortName
),
1857 wx
.YES_NO | wx
.ICON_QUESTION
,
1858 self
.FindSuitableParent())
1860 if not self
.CloseDocument(document
, False):
1861 wx
.MessageBox(_("Couldn't reload '%s'. Unable to close current '%s'.") % (shortName
, shortName
))
1863 return self
.CreateDocument(path
, flags
)
1864 elif res
== wx
.NO
: # don't ask again
1865 document
.SetDocumentModificationDate()
1867 firstView
= document
.GetFirstView()
1868 if firstView
and firstView
.GetFrame():
1869 firstView
.GetFrame().SetFocus() # Not in wxWindows code but useful nonetheless
1870 if hasattr(firstView
.GetFrame(), "IsIconized") and firstView
.GetFrame().IsIconized(): # Not in wxWindows code but useful nonetheless
1871 firstView
.GetFrame().Iconize(False)
1875 newDoc
= temp
.CreateDocument(path
, flags
)
1877 newDoc
.SetDocumentName(temp
.GetDocumentName())
1878 newDoc
.SetDocumentTemplate(temp
)
1879 if not newDoc
.OnOpenDocument(path
):
1880 newDoc
.DeleteAllViews() # Implicitly deleted by DeleteAllViews
1881 newDoc
.GetFirstView().GetFrame().Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it.
1883 self
.AddFileToHistory(path
)
1889 def CreateView(self
, doc
, flags
=0):
1891 Creates a new view for the given document. If more than one view is
1892 allowed for the document (by virtue of multiple templates mentioning
1893 the same document type), a choice of view is presented to the user.
1896 for temp
in self
._templates
:
1897 if temp
.IsVisible():
1898 if temp
.GetDocumentName() == doc
.GetDocumentName():
1899 templates
.append(temp
)
1900 if len(templates
) == 0:
1903 if len(templates
) == 1:
1905 view
= temp
.CreateView(doc
, flags
)
1907 view
.SetViewName(temp
.GetViewName())
1910 temp
= SelectViewType(templates
)
1912 view
= temp
.CreateView(doc
, flags
)
1914 view
.SetViewName(temp
.GetViewName())
1920 def DeleteTemplate(self
, template
, flags
):
1922 Placeholder, not yet implemented in wxWindows.
1927 def FlushDoc(self
, doc
):
1929 Placeholder, not yet implemented in wxWindows.
1934 def MatchTemplate(self
, path
):
1936 Placeholder, not yet implemented in wxWindows.
1941 def GetCurrentDocument(self
):
1943 Returns the document associated with the currently active view (if any).
1945 view
= self
.GetCurrentView()
1947 return view
.GetDocument()
1952 def MakeDefaultName(self
):
1954 Returns a suitable default name. This is implemented by appending an
1955 integer counter to the string "Untitled" and incrementing the counter.
1957 name
= _("Untitled %d") % self
._defaultDocumentNameCounter
1958 self
._defaultDocumentNameCounter
= self
._defaultDocumentNameCounter
+ 1
1962 def MakeFrameTitle(self
):
1964 Returns a suitable title for a document frame. This is implemented by
1965 appending the document name to the application name.
1967 appName
= wx
.GetApp().GetAppName()
1971 docName
= doc
.GetPrintableName()
1972 title
= docName
+ _(" - ") + appName
1976 def AddFileToHistory(self
, fileName
):
1978 Adds a file to the file history list, if we have a pointer to an
1979 appropriate file menu.
1981 if self
._fileHistory
:
1982 self
._fileHistory
.AddFileToHistory(fileName
)
1985 def RemoveFileFromHistory(self
, i
):
1987 Removes a file from the file history list, if we have a pointer to an
1988 appropriate file menu.
1990 if self
._fileHistory
:
1991 self
._fileHistory
.RemoveFileFromHistory(i
)
1994 def GetFileHistory(self
):
1996 Returns the file history.
1998 return self
._fileHistory
2001 def GetHistoryFile(self
, i
):
2003 Returns the file at index i from the file history.
2005 if self
._fileHistory
:
2006 return self
._fileHistory
.GetHistoryFile(i
)
2011 def FileHistoryUseMenu(self
, menu
):
2013 Use this menu for appending recently-visited document filenames, for
2014 convenient access. Calling this function with a valid menu enables the
2015 history list functionality.
2017 Note that you can add multiple menus using this function, to be
2018 managed by the file history object.
2020 if self
._fileHistory
:
2021 self
._fileHistory
.UseMenu(menu
)
2024 def FileHistoryRemoveMenu(self
, menu
):
2026 Removes the given menu from the list of menus managed by the file
2029 if self
._fileHistory
:
2030 self
._fileHistory
.RemoveMenu(menu
)
2033 def FileHistoryLoad(self
, config
):
2035 Loads the file history from a config object.
2037 if self
._fileHistory
:
2038 self
._fileHistory
.Load(config
)
2041 def FileHistorySave(self
, config
):
2043 Saves the file history into a config object. This must be called
2044 explicitly by the application.
2046 if self
._fileHistory
:
2047 self
._fileHistory
.Save(config
)
2050 def FileHistoryAddFilesToMenu(self
, menu
=None):
2052 Appends the files in the history list, to all menus managed by the
2053 file history object.
2055 If menu is specified, appends the files in the history list to the
2058 if self
._fileHistory
:
2060 self
._fileHistory
.AddFilesToThisMenu(menu
)
2062 self
._fileHistory
.AddFilesToMenu()
2065 def GetHistoryFilesCount(self
):
2067 Returns the number of files currently stored in the file history.
2069 if self
._fileHistory
:
2070 return self
._fileHistory
.GetNoHistoryFiles()
2075 def FindTemplateForPath(self
, path
):
2077 Given a path, try to find template that matches the extension. This is
2078 only an approximate method of finding a template for creating a
2081 Note this wxPython verson looks for and returns a default template if no specific template is found.
2084 for temp
in self
._templates
:
2085 if temp
.FileMatchesTemplate(path
):
2088 if "*.*" in temp
.GetFileFilter():
2093 def FindSuitableParent(self
):
2095 Returns a parent frame or dialog, either the frame with the current
2096 focus or if there is no current focus the application's top frame.
2098 parent
= wx
.GetApp().GetTopWindow()
2099 focusWindow
= wx
.Window_FindFocus()
2101 while focusWindow
and not isinstance(focusWindow
, wx
.Dialog
) and not isinstance(focusWindow
, wx
.Frame
):
2102 focusWindow
= focusWindow
.GetParent()
2104 parent
= focusWindow
2108 def SelectDocumentPath(self
, templates
, flags
, save
):
2110 Under Windows, pops up a file selector with a list of filters
2111 corresponding to document templates. The wxDocTemplate corresponding
2112 to the selected file's extension is returned.
2114 On other platforms, if there is more than one document template a
2115 choice list is popped up, followed by a file selector.
2117 This function is used in wxDocManager.CreateDocument.
2119 if wx
.Platform
== "__WXMSW__" or wx
.Platform
== "__WXGTK__" or wx
.Platform
== "__WXMAC__":
2122 for temp
in templates
:
2123 if temp
.IsVisible():
2125 descr
= descr
+ _('|')
2126 allfilter
= allfilter
+ _(';')
2127 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
2128 allfilter
= allfilter
+ temp
.GetFileFilter()
2129 descr
= _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter
, allfilter
, descr
) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
2133 path
= wx
.FileSelector(_("Select a File"),
2134 self
._lastDirectory
,
2137 flags
= wx
.HIDE_READONLY
,
2138 parent
= self
.FindSuitableParent())
2140 if not FileExists(path
):
2141 msgTitle
= wx
.GetApp().GetAppName()
2143 msgTitle
= _("File Error")
2144 wx
.MessageBox("Could not open '%s'." % FileNameFromPath(path
),
2146 wx
.OK | wx
.ICON_EXCLAMATION
,
2149 self
._lastDirectory
= PathOnly(path
)
2151 theTemplate
= self
.FindTemplateForPath(path
)
2152 return (theTemplate
, path
)
2157 def OnOpenFileFailure(self
):
2159 Called when there is an error opening a file.
2164 def SelectDocumentType(self
, temps
, sort
=False):
2166 Returns a document template by asking the user (if there is more than
2167 one template). This function is used in wxDocManager.CreateDocument.
2171 templates - list of templates from which to choose a desired template.
2173 sort - If more than one template is passed in in templates, then this
2174 parameter indicates whether the list of templates that the user will
2175 have to choose from is sorted or not when shown the choice box dialog.
2180 if temp
.IsVisible():
2182 for temp2
in templates
:
2183 if temp
.GetDocumentName() == temp2
.GetDocumentName() and temp
.GetViewName() == temp2
.GetViewName():
2187 templates
.append(temp
)
2189 if len(templates
) == 0:
2191 elif len(templates
) == 1:
2196 return cmp(a
.GetDescription(), b
.GetDescription())
2197 templates
.sort(tempcmp
)
2200 for temp
in templates
:
2201 strings
.append(temp
.GetDescription())
2203 res
= wx
.GetSingleChoiceIndex(_("Select a document type:"),
2206 self
.FindSuitableParent())
2209 return templates
[res
]
2212 def SelectViewType(self
, temps
, sort
=False):
2214 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.
2219 if temp
.IsVisible() and temp
.GetViewTypeName():
2220 if temp
.GetViewName() not in strings
:
2221 templates
.append(temp
)
2222 strings
.append(temp
.GetViewTypeName())
2224 if len(templates
) == 0:
2226 elif len(templates
) == 1:
2231 return cmp(a
.GetViewTypeName(), b
.GetViewTypeName())
2232 templates
.sort(tempcmp
)
2234 res
= wx
.GetSingleChoiceIndex(_("Select a document view:"),
2237 self
.FindSuitableParent())
2240 return templates
[res
]
2243 def GetTemplates(self
):
2245 Returns the document manager's template list. This method has been added to
2246 wxPython and is not in wxWindows.
2248 return self
._templates
2251 def AssociateTemplate(self
, docTemplate
):
2253 Adds the template to the document manager's template list.
2255 if docTemplate
not in self
._templates
:
2256 self
._templates
.append(docTemplate
)
2259 def DisassociateTemplate(self
, docTemplate
):
2261 Removes the template from the list of templates.
2263 self
._templates
.remove(docTemplate
)
2266 def AddDocument(self
, document
):
2268 Adds the document to the list of documents.
2270 if document
not in self
._docs
:
2271 self
._docs
.append(document
)
2274 def RemoveDocument(self
, doc
):
2276 Removes the document from the list of documents.
2278 if doc
in self
._docs
:
2279 self
._docs
.remove(doc
)
2282 def ActivateView(self
, view
, activate
=True, deleting
=False):
2284 Sets the current view.
2287 self
._currentView
= view
2288 self
._lastActiveView
= view
2290 self
._currentView
= None
2293 def GetMaxDocsOpen(self
):
2295 Returns the number of documents that can be open simultaneously.
2297 return self
._maxDocsOpen
2300 def SetMaxDocsOpen(self
, maxDocsOpen
):
2302 Sets the maximum number of documents that can be open at a time. By
2303 default, this is 10,000. If you set it to 1, existing documents will
2304 be saved and deleted when the user tries to open or create a new one
2305 (similar to the behaviour of Windows Write, for example). Allowing
2306 multiple documents gives behaviour more akin to MS Word and other
2307 Multiple Document Interface applications.
2309 self
._maxDocsOpen
= maxDocsOpen
2312 def GetDocuments(self
):
2314 Returns the list of documents.
2319 class DocParentFrame(wx
.Frame
):
2321 The wxDocParentFrame class provides a default top-level frame for
2322 applications using the document/view framework. This class can only be
2323 used for SDI (not MDI) parent frames.
2325 It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplates
2329 def __init__(self
, manager
, frame
, id, title
, pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
, style
=wx
.DEFAULT_FRAME_STYLE
, name
="frame"):
2331 Constructor. Note that the event table must be rebuilt for the
2332 frame since the EvtHandler is not virtual.
2334 wx
.Frame
.__init
__(self
, frame
, id, title
, pos
, size
, style
)
2335 self
._docManager
= manager
2337 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
2339 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
2340 wx
.EVT_MENU_RANGE(self
, wx
.ID_FILE1
, wx
.ID_FILE9
, self
.OnMRUFile
)
2342 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.ProcessEvent
)
2343 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.ProcessEvent
)
2344 wx
.EVT_MENU(self
, wx
.ID_CLOSE_ALL
, self
.ProcessEvent
)
2345 wx
.EVT_MENU(self
, wx
.ID_CLOSE
, self
.ProcessEvent
)
2346 wx
.EVT_MENU(self
, wx
.ID_REVERT
, self
.ProcessEvent
)
2347 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.ProcessEvent
)
2348 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.ProcessEvent
)
2349 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.ProcessEvent
)
2350 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.ProcessEvent
)
2351 wx
.EVT_MENU(self
, wx
.ID_PRINT
, self
.ProcessEvent
)
2352 wx
.EVT_MENU(self
, wx
.ID_PRINT_SETUP
, self
.ProcessEvent
)
2353 wx
.EVT_MENU(self
, wx
.ID_PREVIEW
, self
.ProcessEvent
)
2355 wx
.EVT_UPDATE_UI(self
, wx
.ID_NEW
, self
.ProcessUpdateUIEvent
)
2356 wx
.EVT_UPDATE_UI(self
, wx
.ID_OPEN
, self
.ProcessUpdateUIEvent
)
2357 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE_ALL
, self
.ProcessUpdateUIEvent
)
2358 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE
, self
.ProcessUpdateUIEvent
)
2359 wx
.EVT_UPDATE_UI(self
, wx
.ID_REVERT
, self
.ProcessUpdateUIEvent
)
2360 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.ProcessUpdateUIEvent
)
2361 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVEAS
, self
.ProcessUpdateUIEvent
)
2362 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.ProcessUpdateUIEvent
)
2363 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.ProcessUpdateUIEvent
)
2364 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT
, self
.ProcessUpdateUIEvent
)
2365 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT_SETUP
, self
.ProcessUpdateUIEvent
)
2366 wx
.EVT_UPDATE_UI(self
, wx
.ID_PREVIEW
, self
.ProcessUpdateUIEvent
)
2369 def ProcessEvent(self
, event
):
2371 Processes an event, searching event tables and calling zero or more
2372 suitable event handler function(s). Note that the ProcessEvent
2373 method is called from the wxPython docview framework directly since
2374 wxPython does not have a virtual ProcessEvent function.
2376 return self
._docManager
and self
._docManager
.ProcessEvent(event
)
2379 def ProcessUpdateUIEvent(self
, event
):
2381 Processes a UI event, searching event tables and calling zero or more
2382 suitable event handler function(s). Note that the ProcessEvent
2383 method is called from the wxPython docview framework directly since
2384 wxPython does not have a virtual ProcessEvent function.
2386 return self
._docManager
and self
._docManager
.ProcessUpdateUIEvent(event
)
2389 def OnExit(self
, event
):
2391 Called when File/Exit is chosen and closes the window.
2396 def OnMRUFile(self
, event
):
2398 Opens the appropriate file when it is selected from the file history
2401 n
= event
.GetId() - wx
.ID_FILE1
2402 filename
= self
._docManager
.GetHistoryFile(n
)
2404 self
._docManager
.CreateDocument(filename
, DOC_SILENT
)
2406 self
._docManager
.RemoveFileFromHistory(n
)
2407 msgTitle
= wx
.GetApp().GetAppName()
2409 msgTitle
= _("File Error")
2410 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),
2412 wx
.OK | wx
.ICON_EXCLAMATION
,
2416 def OnCloseWindow(self
, event
):
2418 Deletes all views and documents. If no user input cancelled the
2419 operation, the frame will be destroyed and the application will exit.
2421 if self
._docManager
.Clear(not event
.CanVeto()):
2427 class DocChildFrame(wx
.Frame
):
2429 The wxDocChildFrame class provides a default frame for displaying
2430 documents on separate windows. This class can only be used for SDI (not
2433 The class is part of the document/view framework supported by wxWindows,
2434 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
2439 def __init__(self
, doc
, view
, frame
, id, title
, pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
, style
=wx
.DEFAULT_FRAME_STYLE
, name
="frame"):
2441 Constructor. Note that the event table must be rebuilt for the
2442 frame since the EvtHandler is not virtual.
2444 wx
.Frame
.__init
__(self
, frame
, id, title
, pos
, size
, style
, name
)
2445 wx
.EVT_ACTIVATE(self
, self
.OnActivate
)
2446 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
2447 self
._childDocument
= doc
2448 self
._childView
= view
2452 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.ProcessEvent
)
2453 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.ProcessEvent
)
2454 wx
.EVT_MENU(self
, wx
.ID_CLOSE_ALL
, self
.ProcessEvent
)
2455 wx
.EVT_MENU(self
, wx
.ID_CLOSE
, self
.ProcessEvent
)
2456 wx
.EVT_MENU(self
, wx
.ID_REVERT
, self
.ProcessEvent
)
2457 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.ProcessEvent
)
2458 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.ProcessEvent
)
2459 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.ProcessEvent
)
2460 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.ProcessEvent
)
2461 wx
.EVT_MENU(self
, wx
.ID_PRINT
, self
.ProcessEvent
)
2462 wx
.EVT_MENU(self
, wx
.ID_PRINT_SETUP
, self
.ProcessEvent
)
2463 wx
.EVT_MENU(self
, wx
.ID_PREVIEW
, self
.ProcessEvent
)
2465 wx
.EVT_UPDATE_UI(self
, wx
.ID_NEW
, self
.ProcessUpdateUIEvent
)
2466 wx
.EVT_UPDATE_UI(self
, wx
.ID_OPEN
, self
.ProcessUpdateUIEvent
)
2467 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE_ALL
, self
.ProcessUpdateUIEvent
)
2468 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE
, self
.ProcessUpdateUIEvent
)
2469 wx
.EVT_UPDATE_UI(self
, wx
.ID_REVERT
, self
.ProcessUpdateUIEvent
)
2470 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.ProcessUpdateUIEvent
)
2471 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVEAS
, self
.ProcessUpdateUIEvent
)
2472 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.ProcessUpdateUIEvent
)
2473 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.ProcessUpdateUIEvent
)
2474 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT
, self
.ProcessUpdateUIEvent
)
2475 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT_SETUP
, self
.ProcessUpdateUIEvent
)
2476 wx
.EVT_UPDATE_UI(self
, wx
.ID_PREVIEW
, self
.ProcessUpdateUIEvent
)
2479 def ProcessEvent(self
, event
):
2481 Processes an event, searching event tables and calling zero or more
2482 suitable event handler function(s). Note that the ProcessEvent
2483 method is called from the wxPython docview framework directly since
2484 wxPython does not have a virtual ProcessEvent function.
2487 self
._childView
.Activate(True)
2488 if not self
._childView
or not self
._childView
.ProcessEvent(event
):
2489 # IsInstance not working, but who cares just send all the commands up since this isn't a real ProcessEvent like wxWindows
2490 # if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
2491 if not self
.GetParent() or not self
.GetParent().ProcessEvent(event
):
2499 def ProcessUpdateUIEvent(self
, event
):
2501 Processes a UI event, searching event tables and calling zero or more
2502 suitable event handler function(s). Note that the ProcessEvent
2503 method is called from the wxPython docview framework directly since
2504 wxPython does not have a virtual ProcessEvent function.
2506 if self
.GetParent():
2507 self
.GetParent().ProcessUpdateUIEvent(event
)
2512 def OnActivate(self
, event
):
2514 Activates the current view.
2516 # wx.Frame.OnActivate(event) This is in the wxWindows docview demo but there is no such method in wxPython, so do a Raise() instead
2518 self
._childView
.Activate(event
.GetActive())
2521 def OnCloseWindow(self
, event
):
2523 Closes and deletes the current view and document.
2527 if not event
.CanVeto():
2530 ans
= self
._childView
.Close(deleteWindow
= False)
2533 self
._childView
.Activate(False)
2534 self
._childView
.Destroy()
2535 self
._childView
= None
2536 if self
._childDocument
:
2537 self
._childDocument
.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
2538 self
._childDocument
= None
2546 def GetDocument(self
):
2548 Returns the document associated with this frame.
2550 return self
._childDocument
2553 def SetDocument(self
, document
):
2555 Sets the document for this frame.
2557 self
._childDocument
= document
2562 Returns the view associated with this frame.
2564 return self
._childView
2567 def SetView(self
, view
):
2569 Sets the view for this frame.
2571 self
._childView
= view
2574 class DocMDIParentFrame(wx
.MDIParentFrame
):
2576 The wxDocMDIParentFrame class provides a default top-level frame for
2577 applications using the document/view framework. This class can only be
2578 used for MDI parent frames.
2580 It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
2585 def __init__(self
, manager
, frame
, id, title
, pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
, style
=wx
.DEFAULT_FRAME_STYLE
, name
="frame"):
2587 Constructor. Note that the event table must be rebuilt for the
2588 frame since the EvtHandler is not virtual.
2590 wx
.MDIParentFrame
.__init
__(self
, frame
, id, title
, pos
, size
, style
, name
)
2591 self
._docManager
= manager
2593 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
2595 wx
.EVT_MENU(self
, wx
.ID_EXIT
, self
.OnExit
)
2596 wx
.EVT_MENU_RANGE(self
, wx
.ID_FILE1
, wx
.ID_FILE9
, self
.OnMRUFile
)
2598 wx
.EVT_MENU(self
, wx
.ID_NEW
, self
.ProcessEvent
)
2599 wx
.EVT_MENU(self
, wx
.ID_OPEN
, self
.ProcessEvent
)
2600 wx
.EVT_MENU(self
, wx
.ID_CLOSE_ALL
, self
.ProcessEvent
)
2601 wx
.EVT_MENU(self
, wx
.ID_CLOSE
, self
.ProcessEvent
)
2602 wx
.EVT_MENU(self
, wx
.ID_REVERT
, self
.ProcessEvent
)
2603 wx
.EVT_MENU(self
, wx
.ID_SAVE
, self
.ProcessEvent
)
2604 wx
.EVT_MENU(self
, wx
.ID_SAVEAS
, self
.ProcessEvent
)
2605 wx
.EVT_MENU(self
, wx
.ID_UNDO
, self
.ProcessEvent
)
2606 wx
.EVT_MENU(self
, wx
.ID_REDO
, self
.ProcessEvent
)
2607 wx
.EVT_MENU(self
, wx
.ID_PRINT
, self
.ProcessEvent
)
2608 wx
.EVT_MENU(self
, wx
.ID_PRINT_SETUP
, self
.ProcessEvent
)
2609 wx
.EVT_MENU(self
, wx
.ID_PREVIEW
, self
.ProcessEvent
)
2611 wx
.EVT_UPDATE_UI(self
, wx
.ID_NEW
, self
.ProcessUpdateUIEvent
)
2612 wx
.EVT_UPDATE_UI(self
, wx
.ID_OPEN
, self
.ProcessUpdateUIEvent
)
2613 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE_ALL
, self
.ProcessUpdateUIEvent
)
2614 wx
.EVT_UPDATE_UI(self
, wx
.ID_CLOSE
, self
.ProcessUpdateUIEvent
)
2615 wx
.EVT_UPDATE_UI(self
, wx
.ID_REVERT
, self
.ProcessUpdateUIEvent
)
2616 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVE
, self
.ProcessUpdateUIEvent
)
2617 wx
.EVT_UPDATE_UI(self
, wx
.ID_SAVEAS
, self
.ProcessUpdateUIEvent
)
2618 wx
.EVT_UPDATE_UI(self
, wx
.ID_UNDO
, self
.ProcessUpdateUIEvent
)
2619 wx
.EVT_UPDATE_UI(self
, wx
.ID_REDO
, self
.ProcessUpdateUIEvent
)
2620 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT
, self
.ProcessUpdateUIEvent
)
2621 wx
.EVT_UPDATE_UI(self
, wx
.ID_PRINT_SETUP
, self
.ProcessUpdateUIEvent
)
2622 wx
.EVT_UPDATE_UI(self
, wx
.ID_PREVIEW
, self
.ProcessUpdateUIEvent
)
2625 def ProcessEvent(self
, event
):
2627 Processes an event, searching event tables and calling zero or more
2628 suitable event handler function(s). Note that the ProcessEvent
2629 method is called from the wxPython docview framework directly since
2630 wxPython does not have a virtual ProcessEvent function.
2632 return self
._docManager
and self
._docManager
.ProcessEvent(event
)
2635 def ProcessUpdateUIEvent(self
, event
):
2637 Processes a UI event, searching event tables and calling zero or more
2638 suitable event handler function(s). Note that the ProcessEvent
2639 method is called from the wxPython docview framework directly since
2640 wxPython does not have a virtual ProcessEvent function.
2642 return self
._docManager
and self
._docManager
.ProcessUpdateUIEvent(event
)
2645 def OnExit(self
, event
):
2647 Called when File/Exit is chosen and closes the window.
2652 def OnMRUFile(self
, event
):
2654 Opens the appropriate file when it is selected from the file history
2657 n
= event
.GetId() - wx
.ID_FILE1
2658 filename
= self
._docManager
.GetHistoryFile(n
)
2660 self
._docManager
.CreateDocument(filename
, DOC_SILENT
)
2662 self
._docManager
.RemoveFileFromHistory(n
)
2663 msgTitle
= wx
.GetApp().GetAppName()
2665 msgTitle
= _("File Error")
2666 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),
2668 wx
.OK | wx
.ICON_EXCLAMATION
,
2672 def OnCloseWindow(self
, event
):
2674 Deletes all views and documents. If no user input cancelled the
2675 operation, the frame will be destroyed and the application will exit.
2677 if self
._docManager
.Clear(not event
.CanVeto()):
2683 class DocMDIChildFrame(wx
.MDIChildFrame
):
2685 The wxDocMDIChildFrame class provides a default frame for displaying
2686 documents on separate windows. This class can only be used for MDI child
2689 The class is part of the document/view framework supported by wxWindows,
2690 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
2695 def __init__(self
, doc
, view
, frame
, id, title
, pos
=wx
.DefaultPosition
, size
=wx
.DefaultSize
, style
=wx
.DEFAULT_FRAME_STYLE
, name
="frame"):
2697 Constructor. Note that the event table must be rebuilt for the
2698 frame since the EvtHandler is not virtual.
2700 wx
.MDIChildFrame
.__init
__(self
, frame
, id, title
, pos
, size
, style
, name
)
2701 self
._childDocument
= doc
2702 self
._childView
= view
2705 # self.Create(doc, view, frame, id, title, pos, size, style, name)
2706 self
._activeEvent
= None
2708 wx
.EVT_ACTIVATE(self
, self
.OnActivate
)
2709 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
2711 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
2712 mdiChildren
= filter(lambda x
: isinstance(x
, wx
.MDIChildFrame
), frame
.GetChildren())
2713 if len(mdiChildren
) == 1:
2717 ## # Couldn't get this to work, but seems to work fine with single stage construction
2718 ## def Create(self, doc, view, frame, id, title, pos, size, style, name):
2719 ## self._childDocument = doc
2720 ## self._childView = view
2721 ## if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
2723 ## view.SetFrame(self)
2729 def Activate(self
): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
2731 Activates the current view.
2734 self
._childView
.Activate(True)
2737 def ProcessEvent(event
):
2739 Processes an event, searching event tables and calling zero or more
2740 suitable event handler function(s). Note that the ProcessEvent
2741 method is called from the wxPython docview framework directly since
2742 wxPython does not have a virtual ProcessEvent function.
2744 if self
._activeEvent
== event
:
2747 self
._activeEvent
= event
# Break recursion loops
2750 self
._childView
.Activate(True)
2752 if not self
._childView
or not self
._childView
.ProcessEvent(event
):
2753 if not isinstance(event
, wx
.CommandEvent
) or not self
.GetParent() or not self
.GetParent().ProcessEvent(event
):
2760 self
._activeEvent
= None
2764 def OnActivate(self
, event
):
2766 Sets the currently active view to be the frame's view. You may need to
2767 override (but still call) this function in order to set the keyboard
2768 focus for your subwindow.
2770 if self
._activated
!= 0:
2772 self
._activated
+= 1
2773 wx
.MDIChildFrame
.Activate(self
)
2774 if event
.GetActive() and self
._childView
:
2775 self
._childView
.Activate(event
.GetActive())
2778 def OnCloseWindow(self
, event
):
2780 Closes and deletes the current view and document.
2784 if not event
.CanVeto():
2787 ans
= self
._childView
.Close(deleteWindow
= False)
2790 self
._childView
.Activate(False)
2791 self
._childView
.Destroy()
2792 self
._childView
= None
2793 if self
._childDocument
: # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
2794 self
._childDocument
.DeleteContents()
2795 if self
._childDocument
.GetDocumentManager():
2796 self
._childDocument
.GetDocumentManager().RemoveDocument(self
._childDocument
)
2797 self
._childDocument
= None
2805 def GetDocument(self
):
2807 Returns the document associated with this frame.
2809 return self
._childDocument
2812 def SetDocument(self
, document
):
2814 Sets the document for this frame.
2816 self
._childDocument
= document
2821 Returns the view associated with this frame.
2823 return self
._childView
2826 def SetView(self
, view
):
2828 Sets the view for this frame.
2830 self
._childView
= view
2833 class DocPrintout(wx
.Printout
):
2835 DocPrintout is a default Printout that prints the first page of a document
2840 def __init__(self
, view
, title
="Printout"):
2844 wx
.Printout
.__init
__(self
, title
)
2845 self
._printoutView
= view
2850 Returns the DocPrintout's view.
2852 return self
._printoutView
2855 def OnPrintPage(self
, page
):
2857 Prints the first page of the view.
2860 ppiScreenX
, ppiScreenY
= self
.GetPPIScreen()
2861 ppiPrinterX
, ppiPrinterY
= self
.GetPPIPrinter()
2862 scale
= ppiPrinterX
/ppiScreenX
2864 pageWidth
, pageHeight
= self
.GetPageSizePixels()
2865 overallScale
= scale
* w
/ pageWidth
2866 dc
.SetUserScale(overallScale
, overallScale
)
2867 if self
._printoutView
:
2868 self
._printoutView
.OnDraw(dc
)
2872 def HasPage(self
, pageNum
):
2874 Indicates that the DocPrintout only has a single page.
2879 def OnBeginDocument(self
, startPage
, endPage
):
2881 Not quite sure why this was overridden, but it was in wxWindows! :)
2883 if not wx
.Printout
.base_OnBeginDocument(self
, startPage
, endPage
):
2888 def GetPageInfo(self
):
2890 Indicates that the DocPrintout only has a single page.
2896 return (minPage
, maxPage
, selPageFrom
, selPageTo
)
2899 #----------------------------------------------------------------------
2901 #----------------------------------------------------------------------
2903 class Command(wx
.Object
):
2905 wxCommand is a base class for modelling an application command, which is
2906 an action usually performed by selecting a menu item, pressing a toolbar
2907 button or any other means provided by the application to change the data
2912 def __init__(self
, canUndo
= False, name
= None):
2914 Constructor. wxCommand is an abstract class, so you will need to
2915 derive a new class and call this constructor from your own constructor.
2917 canUndo tells the command processor whether this command is undo-able.
2918 You can achieve the same functionality by overriding the CanUndo member
2919 function (if for example the criteria for undoability is context-
2922 name must be supplied for the command processor to display the command
2923 name in the application's edit menu.
2925 self
._canUndo
= canUndo
2931 Returns true if the command can be undone, false otherwise.
2933 return self
._canUndo
2938 Returns the command name.
2945 Override this member function to execute the appropriate action when
2946 called. Return true to indicate that the action has taken place, false
2947 otherwise. Returning false will indicate to the command processor that
2948 the action is not undoable and should not be added to the command
2956 Override this member function to un-execute a previous Do. Return true
2957 to indicate that the action has taken place, false otherwise. Returning
2958 false will indicate to the command processor that the action is not
2959 redoable and no change should be made to the command history.
2961 How you implement this command is totally application dependent, but
2962 typical strategies include:
2964 Perform an inverse operation on the last modified piece of data in the
2965 document. When redone, a copy of data stored in command is pasted back
2966 or some operation reapplied. This relies on the fact that you know the
2967 ordering of Undos; the user can never Undo at an arbitrary position in
2970 Restore the entire document state (perhaps using document
2971 transactioning). Potentially very inefficient, but possibly easier to
2972 code if the user interface and data are complex, and an 'inverse
2973 execute' operation is hard to write.
2978 class CommandProcessor(wx
.Object
):
2980 wxCommandProcessor is a class that maintains a history of wxCommands, with
2981 undo/redo functionality built-in. Derive a new class from this if you want
2982 different behaviour.
2986 def __init__(self
, maxCommands
=-1):
2988 Constructor. maxCommands may be set to a positive integer to limit
2989 the number of commands stored to it, otherwise (and by default) the
2990 list of commands can grow arbitrarily.
2992 self
._maxCommands
= maxCommands
2993 self
._editMenu
= None
2994 self
._undoAccelerator
= _("Ctrl+Z")
2995 self
._redoAccelerator
= _("Ctrl+Y")
2996 self
.ClearCommands()
2999 def _GetCurrentCommand(self
):
3000 if len(self
._commands
) == 0:
3003 return self
._commands
[-1]
3006 def _GetCurrentRedoCommand(self
):
3007 if len(self
._redoCommands
) == 0:
3010 return self
._redoCommands
[-1]
3013 def GetMaxCommands(self
):
3015 Returns the maximum number of commands that the command processor
3019 return self
._maxCommands
3022 def GetCommands(self
):
3024 Returns the list of commands.
3026 return self
._commands
3029 def ClearCommands(self
):
3031 Deletes all the commands in the list and sets the current command
3035 self
._redoCommands
= []
3038 def GetEditMenu(self
):
3040 Returns the edit menu associated with the command processor.
3042 return self
._editMenu
3045 def SetEditMenu(self
, menu
):
3047 Tells the command processor to update the Undo and Redo items on this
3048 menu as appropriate. Set this to NULL if the menu is about to be
3049 destroyed and command operations may still be performed, or the
3050 command processor may try to access an invalid pointer.
3052 self
._editMenu
= menu
3055 def GetUndoAccelerator(self
):
3057 Returns the string that will be appended to the Undo menu item.
3059 return self
._undoAccelerator
3062 def SetUndoAccelerator(self
, accel
):
3064 Sets the string that will be appended to the Redo menu item.
3066 self
._undoAccelerator
= accel
3069 def GetRedoAccelerator(self
):
3071 Returns the string that will be appended to the Redo menu item.
3073 return self
._redoAccelerator
3076 def SetRedoAccelerator(self
, accel
):
3078 Sets the string that will be appended to the Redo menu item.
3080 self
._redoAccelerator
= accel
3083 def SetEditMenu(self
, menu
):
3085 Tells the command processor to update the Undo and Redo items on this
3086 menu as appropriate. Set this to NULL if the menu is about to be
3087 destroyed and command operations may still be performed, or the
3088 command processor may try to access an invalid pointer.
3090 self
._editMenu
= menu
3093 def SetMenuStrings(self
):
3095 Sets the menu labels according to the currently set menu and the
3096 current command state.
3098 if self
.GetEditMenu() != None:
3099 undoCommand
= self
._GetCurrentCommand
()
3100 redoCommand
= self
._GetCurrentRedoCommand
()
3101 undoItem
= self
.GetEditMenu().FindItemById(wx
.ID_UNDO
)
3102 redoItem
= self
.GetEditMenu().FindItemById(wx
.ID_REDO
)
3103 if self
.GetUndoAccelerator():
3104 undoAccel
= '\t' + self
.GetUndoAccelerator()
3107 if self
.GetRedoAccelerator():
3108 redoAccel
= '\t' + self
.GetRedoAccelerator()
3111 if undoCommand
and undoItem
and undoCommand
.CanUndo():
3112 undoItem
.SetText(_("&Undo ") + undoCommand
.GetName() + undoAccel
)
3113 #elif undoCommand and not undoCommand.CanUndo():
3114 # undoItem.SetText(_("Can't Undo") + undoAccel)
3116 undoItem
.SetText(_("&Undo" + undoAccel
))
3117 if redoCommand
and redoItem
:
3118 redoItem
.SetText(_("&Redo ") + redoCommand
.GetName() + redoAccel
)
3120 redoItem
.SetText(_("&Redo") + redoAccel
)
3125 Returns true if the currently-active command can be undone, false
3128 if self
._GetCurrentCommand
() == None:
3130 return self
._GetCurrentCommand
().CanUndo()
3135 Returns true if the currently-active command can be redone, false
3138 return self
._GetCurrentRedoCommand
() != None
3141 def Submit(self
, command
, storeIt
=True):
3143 Submits a new command to the command processor. The command processor
3144 calls wxCommand::Do to execute the command; if it succeeds, the
3145 command is stored in the history list, and the associated edit menu
3146 (if any) updated appropriately. If it fails, the command is deleted
3147 immediately. Once Submit has been called, the passed command should
3148 not be deleted directly by the application.
3150 storeIt indicates whether the successful command should be stored in
3154 if done
and storeIt
:
3155 self
._commands
.append(command
)
3156 if self
._maxCommands
> -1:
3157 if len(self
._commands
) > self
._maxCommands
:
3158 del self
._commands
[0]
3164 Redoes the command just undone.
3166 cmd
= self
._GetCurrentRedoCommand
()
3171 self
._commands
.append(self
._redoCommands
.pop())
3177 Undoes the command just executed.
3179 cmd
= self
._GetCurrentCommand
()
3184 self
._redoCommands
.append(self
._commands
.pop())