git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@43452 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			3240 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			3240 lines
		
	
	
		
			107 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #----------------------------------------------------------------------------
 | |
| # Name:         docview.py
 | |
| # Purpose:      Port of the wxWindows docview classes
 | |
| #
 | |
| # Author:       Peter Yared
 | |
| #
 | |
| # Created:      5/15/03
 | |
| # CVS-ID:       $Id$
 | |
| # Copyright:    (c) 2003-2006 ActiveGrid, Inc. (Port of wxWindows classes by Julian Smart et al)
 | |
| # License:      wxWindows license
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| import os
 | |
| import os.path
 | |
| import shutil
 | |
| import wx
 | |
| import sys
 | |
| _ = wx.GetTranslation
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| # docview globals
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| DOC_SDI = 1
 | |
| DOC_MDI = 2
 | |
| DOC_NEW = 4
 | |
| DOC_SILENT = 8
 | |
| DOC_OPEN_ONCE = 16
 | |
| DOC_NO_VIEW = 32
 | |
| DEFAULT_DOCMAN_FLAGS = DOC_SDI & DOC_OPEN_ONCE
 | |
| 
 | |
| TEMPLATE_VISIBLE = 1
 | |
| TEMPLATE_INVISIBLE = 2
 | |
| TEMPLATE_NO_CREATE = (4 | TEMPLATE_VISIBLE)
 | |
| DEFAULT_TEMPLATE_FLAGS = TEMPLATE_VISIBLE
 | |
| 
 | |
| MAX_FILE_HISTORY = 9
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| # Convenience functions from wxWindows used in docview
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| def FileNameFromPath(path):
 | |
|     """
 | |
|     Returns the filename for a full path.
 | |
|     """
 | |
|     return os.path.split(path)[1]
 | |
| 
 | |
| def FindExtension(path):
 | |
|     """
 | |
|     Returns the extension of a filename for a full path.
 | |
|     """
 | |
|     return os.path.splitext(path)[1].lower()
 | |
| 
 | |
| def FileExists(path):
 | |
|     """
 | |
|     Returns True if the path exists.
 | |
|     """
 | |
|     return os.path.isfile(path)
 | |
| 
 | |
| def PathOnly(path):
 | |
|     """
 | |
|     Returns the path of a full path without the filename.
 | |
|     """
 | |
|     return os.path.split(path)[0]
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| # Document/View Classes
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| class Document(wx.EvtHandler):
 | |
|     """
 | |
|     The document class can be used to model an application's file-based data. It
 | |
|     is part of the document/view framework supported by wxWindows, and cooperates
 | |
|     with the wxView, wxDocTemplate and wxDocManager classes.
 | |
|     
 | |
|     Note this wxPython version also keeps track of the modification date of the
 | |
|     document and if it changes on disk outside of the application, we will warn the
 | |
|     user before saving to avoid clobbering the file.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, parent=None):
 | |
|         """
 | |
|         Constructor.  Define your own default constructor to initialize
 | |
|         application-specific data.
 | |
|         """
 | |
|         wx.EvtHandler.__init__(self)
 | |
| 
 | |
|         self._documentParent = parent
 | |
|         self._documentTemplate = None
 | |
|         self._commandProcessor = None
 | |
|         self._savedYet = False
 | |
|         self._writeable = True
 | |
| 
 | |
|         self._documentTitle = None
 | |
|         self._documentFile = None
 | |
|         self._documentTypeName = None
 | |
|         self._documentModified = False
 | |
|         self._documentModificationDate = None
 | |
|         self._documentViews = []
 | |
| 
 | |
| 
 | |
|     def ProcessEvent(self, event):
 | |
|         """
 | |
|         Processes an event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         return False
 | |
| 
 | |
| 
 | |
|     def GetFilename(self):
 | |
|         """
 | |
|         Gets the filename associated with this document, or "" if none is
 | |
|         associated.
 | |
|         """
 | |
|         return self._documentFile
 | |
| 
 | |
| 
 | |
|     def GetTitle(self):
 | |
|         """
 | |
|         Gets the title for this document. The document title is used for an
 | |
|         associated frame (if any), and is usually constructed by the framework
 | |
|         from the filename.
 | |
|         """
 | |
|         return self._documentTitle
 | |
| 
 | |
| 
 | |
|     def SetTitle(self, title):
 | |
|         """
 | |
|         Sets the title for this document. The document title is used for an
 | |
|         associated frame (if any), and is usually constructed by the framework
 | |
|         from the filename.
 | |
|         """
 | |
|         self._documentTitle = title
 | |
| 
 | |
| 
 | |
|     def GetDocumentName(self):
 | |
|         """
 | |
|         The document type name given to the wxDocTemplate constructor,
 | |
|         copied to this document when the document is created. If several
 | |
|         document templates are created that use the same document type, this
 | |
|         variable is used in wxDocManager::CreateView to collate a list of
 | |
|         alternative view types that can be used on this kind of document.
 | |
|         """
 | |
|         return self._documentTypeName
 | |
| 
 | |
| 
 | |
|     def SetDocumentName(self, name):
 | |
|         """
 | |
|         Sets he document type name given to the wxDocTemplate constructor,
 | |
|         copied to this document when the document is created. If several
 | |
|         document templates are created that use the same document type, this
 | |
|         variable is used in wxDocManager::CreateView to collate a list of
 | |
|         alternative view types that can be used on this kind of document. Do
 | |
|         not change the value of this variable.
 | |
|         """
 | |
|         self._documentTypeName = name
 | |
| 
 | |
| 
 | |
|     def GetDocumentSaved(self):
 | |
|         """
 | |
|         Returns True if the document has been saved.  This method has been
 | |
|         added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         return self._savedYet
 | |
| 
 | |
| 
 | |
|     def SetDocumentSaved(self, saved=True):
 | |
|         """
 | |
|         Sets whether the document has been saved.  This method has been
 | |
|         added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         self._savedYet = saved
 | |
| 
 | |
| 
 | |
|     def GetCommandProcessor(self):
 | |
|         """
 | |
|         Returns the command processor associated with this document.
 | |
|         """
 | |
|         return self._commandProcessor
 | |
| 
 | |
| 
 | |
|     def SetCommandProcessor(self, processor):
 | |
|         """
 | |
|         Sets the command processor to be used for this document. The document
 | |
|         will then be responsible for its deletion. Normally you should not
 | |
|         call this; override OnCreateCommandProcessor instead.
 | |
|         """
 | |
|         self._commandProcessor = processor
 | |
| 
 | |
| 
 | |
|     def IsModified(self):
 | |
|         """
 | |
|         Returns true if the document has been modified since the last save,
 | |
|         false otherwise. You may need to override this if your document view
 | |
|         maintains its own record of being modified (for example if using
 | |
|         wxTextWindow to view and edit the document).
 | |
|         """
 | |
|         return self._documentModified
 | |
| 
 | |
| 
 | |
|     def Modify(self, modify):
 | |
|         """
 | |
|         Call with true to mark the document as modified since the last save,
 | |
|         false otherwise. You may need to override this if your document view
 | |
|         maintains its own record of being modified (for example if using
 | |
|         xTextWindow to view and edit the document).
 | |
|         This method has been extended to notify its views that the dirty flag has changed.
 | |
|         """
 | |
|         self._documentModified = modify
 | |
|         self.UpdateAllViews(hint=("modify", self, self._documentModified))
 | |
| 
 | |
| 
 | |
|     def SetDocumentModificationDate(self):
 | |
|         """
 | |
|         Saves the file's last modification date.
 | |
|         This is used to check if the file has been modified outside of the application.
 | |
|         This method has been added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         self._documentModificationDate = os.path.getmtime(self.GetFilename())
 | |
| 
 | |
| 
 | |
|     def GetDocumentModificationDate(self):
 | |
|         """
 | |
|         Returns the file's modification date when it was loaded from disk.
 | |
|         This is used to check if the file has been modified outside of the application.        
 | |
|         This method has been added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         return self._documentModificationDate
 | |
| 
 | |
| 
 | |
|     def IsDocumentModificationDateCorrect(self):
 | |
|         """
 | |
|         Returns False if the file has been modified outside of the application.
 | |
|         This method has been added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         if not os.path.exists(self.GetFilename()):  # document must be in memory only and can't be out of date
 | |
|             return True
 | |
|         return self._documentModificationDate == os.path.getmtime(self.GetFilename())
 | |
| 
 | |
| 
 | |
|     def GetViews(self):
 | |
|         """
 | |
|         Returns the list whose elements are the views on the document.
 | |
|         """
 | |
|         return self._documentViews
 | |
| 
 | |
| 
 | |
|     def GetDocumentTemplate(self):
 | |
|         """
 | |
|         Returns the template that created the document.
 | |
|         """
 | |
|         return self._documentTemplate
 | |
| 
 | |
| 
 | |
|     def SetDocumentTemplate(self, template):
 | |
|         """
 | |
|         Sets the template that created the document. Should only be called by
 | |
|         the framework.
 | |
|         """
 | |
|         self._documentTemplate = template
 | |
| 
 | |
| 
 | |
|     def DeleteContents(self):
 | |
|         """
 | |
|         Deletes the contents of the document.  Override this method as
 | |
|         necessary.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def Destroy(self):
 | |
|         """
 | |
|         Destructor. Removes itself from the document manager.
 | |
|         """
 | |
|         self.DeleteContents()
 | |
|         self._documentModificationDate = None
 | |
|         if self.GetDocumentManager():
 | |
|             self.GetDocumentManager().RemoveDocument(self)
 | |
|         wx.EvtHandler.Destroy(self)
 | |
| 
 | |
| 
 | |
|     def Close(self):
 | |
|         """
 | |
|         Closes the document, by calling OnSaveModified and then (if this true)
 | |
|         OnCloseDocument. This does not normally delete the document object:
 | |
|         use DeleteAllViews to do this implicitly.
 | |
|         """
 | |
|         if self.OnSaveModified():
 | |
|             if self.OnCloseDocument():
 | |
|                 return True
 | |
|             else:
 | |
|                 return False
 | |
|         else:
 | |
|             return False
 | |
| 
 | |
| 
 | |
|     def OnCloseDocument(self):
 | |
|         """
 | |
|         The default implementation calls DeleteContents (an empty
 | |
|         implementation) sets the modified flag to false. Override this to
 | |
|         supply additional behaviour when the document is closed with Close.
 | |
|         """
 | |
|         self.NotifyClosing()
 | |
|         self.DeleteContents()
 | |
|         self.Modify(False)
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def DeleteAllViews(self):
 | |
|         """
 | |
|         Calls wxView.Close and deletes each view. Deleting the final view will
 | |
|         implicitly delete the document itself, because the wxView destructor
 | |
|         calls RemoveView. This in turns calls wxDocument::OnChangedViewList,
 | |
|         whose default implemention is to save and delete the document if no
 | |
|         views exist.
 | |
|         """
 | |
|         manager = self.GetDocumentManager()
 | |
|         for view in self._documentViews:
 | |
|             if not view.Close():
 | |
|                 return False
 | |
|         if self in manager.GetDocuments():
 | |
|             self.Destroy()
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def GetFirstView(self):
 | |
|         """
 | |
|         A convenience function to get the first view for a document, because
 | |
|         in many cases a document will only have a single view.
 | |
|         """
 | |
|         if len(self._documentViews) == 0:
 | |
|             return None
 | |
|         return self._documentViews[0]
 | |
| 
 | |
| 
 | |
|     def GetDocumentManager(self):
 | |
|         """
 | |
|         Returns the associated document manager.
 | |
|         """
 | |
|         if self._documentTemplate:
 | |
|             return self._documentTemplate.GetDocumentManager()
 | |
|         return None
 | |
| 
 | |
| 
 | |
|     def OnNewDocument(self):
 | |
|         """
 | |
|         The default implementation calls OnSaveModified and DeleteContents,
 | |
|         makes a default title for the document, and notifies the views that
 | |
|         the filename (in fact, the title) has changed.
 | |
|         """
 | |
|         if not self.OnSaveModified() or not self.OnCloseDocument():
 | |
|             return False
 | |
|         self.DeleteContents()
 | |
|         self.Modify(False)
 | |
|         self.SetDocumentSaved(False)
 | |
|         name = self.GetDocumentManager().MakeDefaultName()
 | |
|         self.SetTitle(name)
 | |
|         self.SetFilename(name, notifyViews = True)
 | |
| 
 | |
| 
 | |
|     def Save(self):
 | |
|         """
 | |
|         Saves the document by calling OnSaveDocument if there is an associated
 | |
|         filename, or SaveAs if there is no filename.
 | |
|         """
 | |
|         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?
 | |
|             return True
 | |
| 
 | |
|         """ check for file modification outside of application """
 | |
|         if not self.IsDocumentModificationDateCorrect():
 | |
|             msgTitle = wx.GetApp().GetAppName()
 | |
|             if not msgTitle:
 | |
|                 msgTitle = _("Application")
 | |
|             res = wx.MessageBox(_("'%s' has been modified outside of %s.  Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()),
 | |
|                                 msgTitle,
 | |
|                                 wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
 | |
|                                 self.GetDocumentWindow())
 | |
|     
 | |
|             if res == wx.NO:
 | |
|                 return True
 | |
|             elif res == wx.YES:
 | |
|                 pass
 | |
|             else: # elif res == wx.CANCEL:
 | |
|                 return False
 | |
|         
 | |
|         if not self._documentFile or not self._savedYet:
 | |
|             return self.SaveAs()
 | |
|         return self.OnSaveDocument(self._documentFile)
 | |
| 
 | |
| 
 | |
|     def SaveAs(self):
 | |
|         """
 | |
|         Prompts the user for a file to save to, and then calls OnSaveDocument.
 | |
|         """
 | |
|         docTemplate = self.GetDocumentTemplate()
 | |
|         if not docTemplate:
 | |
|             return False
 | |
| 
 | |
|         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
 | |
|         filename = wx.FileSelector(_("Save As"),
 | |
|                                    docTemplate.GetDirectory(),
 | |
|                                    FileNameFromPath(self.GetFilename()),
 | |
|                                    docTemplate.GetDefaultExtension(),
 | |
|                                    wildcard = descr,
 | |
|                                    flags = wx.SAVE | wx.OVERWRITE_PROMPT,
 | |
|                                    parent = self.GetDocumentWindow())
 | |
|         if filename == "":
 | |
|             return False
 | |
| 
 | |
|         name, ext = os.path.splitext(filename)
 | |
|         if ext == "":
 | |
|             filename += '.' + docTemplate.GetDefaultExtension()
 | |
| 
 | |
|         self.SetFilename(filename)
 | |
|         self.SetTitle(FileNameFromPath(filename))
 | |
| 
 | |
|         for view in self._documentViews:
 | |
|             view.OnChangeFilename()
 | |
| 
 | |
|         if not self.OnSaveDocument(filename):
 | |
|             return False
 | |
| 
 | |
|         if docTemplate.FileMatchesTemplate(filename):
 | |
|             self.GetDocumentManager().AddFileToHistory(filename)
 | |
|             
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def OnSaveDocument(self, filename):
 | |
|         """
 | |
|         Constructs an output file for the given filename (which must
 | |
|         not be empty), and calls SaveObject. If SaveObject returns true, the
 | |
|         document is set to unmodified; otherwise, an error message box is
 | |
|         displayed.
 | |
|         """
 | |
|         if not filename:
 | |
|             return False
 | |
| 
 | |
|         msgTitle = wx.GetApp().GetAppName()
 | |
|         if not msgTitle:
 | |
|             msgTitle = _("File Error")
 | |
| 
 | |
|         backupFilename = None
 | |
|         fileObject = None
 | |
|         copied = False
 | |
|         try:
 | |
|             # if current file exists, move it to a safe place temporarily
 | |
|             if os.path.exists(filename):
 | |
| 
 | |
|                 # Check if read-only.
 | |
|                 if not os.access(filename, os.W_OK):
 | |
|                     wx.MessageBox("Could not save '%s'.  No write permission to overwrite existing file." % FileNameFromPath(filename),
 | |
|                                   msgTitle,
 | |
|                                   wx.OK | wx.ICON_EXCLAMATION,
 | |
|                                   self.GetDocumentWindow())
 | |
|                     return False
 | |
| 
 | |
|                 i = 1
 | |
|                 backupFilename = "%s.bak%s" % (filename, i)
 | |
|                 while os.path.exists(backupFilename):
 | |
|                     i += 1
 | |
|                     backupFilename = "%s.bak%s" % (filename, i)
 | |
|                 shutil.copy(filename, backupFilename)
 | |
|                 copied = True
 | |
| 
 | |
|             fileObject = file(filename, 'w')
 | |
|             self.SaveObject(fileObject)
 | |
|             fileObject.close()
 | |
|             fileObject = None
 | |
|             
 | |
|             if backupFilename:
 | |
|                 os.remove(backupFilename)
 | |
|         except:
 | |
|             # for debugging purposes
 | |
|             import traceback
 | |
|             traceback.print_exc()
 | |
| 
 | |
|             if fileObject:
 | |
|                 fileObject.close()  # file is still open, close it, need to do this before removal 
 | |
| 
 | |
|             # save failed, remove copied file
 | |
|             if backupFilename and copied:
 | |
|                 os.remove(backupFilename)
 | |
| 
 | |
|             wx.MessageBox("Could not save '%s'.  %s" % (FileNameFromPath(filename), sys.exc_value),
 | |
|                           msgTitle,
 | |
|                           wx.OK | wx.ICON_EXCLAMATION,
 | |
|                           self.GetDocumentWindow())
 | |
|             return False
 | |
| 
 | |
|         self.SetDocumentModificationDate()
 | |
|         self.SetFilename(filename, True)
 | |
|         self.Modify(False)
 | |
|         self.SetDocumentSaved(True)
 | |
|         #if wx.Platform == '__WXMAC__':  # Not yet implemented in wxPython
 | |
|         #    wx.FileName(file).MacSetDefaultTypeAndCreator()
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def OnOpenDocument(self, filename):
 | |
|         """
 | |
|         Constructs an input file for the given filename (which must not
 | |
|         be empty), and calls LoadObject. If LoadObject returns true, the
 | |
|         document is set to unmodified; otherwise, an error message box is
 | |
|         displayed. The document's views are notified that the filename has
 | |
|         changed, to give windows an opportunity to update their titles. All of
 | |
|         the document's views are then updated.
 | |
|         """
 | |
|         if not self.OnSaveModified():
 | |
|             return False
 | |
| 
 | |
|         msgTitle = wx.GetApp().GetAppName()
 | |
|         if not msgTitle:
 | |
|             msgTitle = _("File Error")
 | |
| 
 | |
|         fileObject = file(filename, 'r')
 | |
|         try:
 | |
|             self.LoadObject(fileObject)
 | |
|             fileObject.close()
 | |
|             fileObject = None
 | |
|         except:
 | |
|             # for debugging purposes
 | |
|             import traceback
 | |
|             traceback.print_exc()
 | |
| 
 | |
|             if fileObject:
 | |
|                 fileObject.close()  # file is still open, close it 
 | |
| 
 | |
|             wx.MessageBox("Could not open '%s'.  %s" % (FileNameFromPath(filename), sys.exc_value),
 | |
|                           msgTitle,
 | |
|                           wx.OK | wx.ICON_EXCLAMATION,
 | |
|                           self.GetDocumentWindow())
 | |
|             return False
 | |
| 
 | |
|         self.SetDocumentModificationDate()
 | |
|         self.SetFilename(filename, True)
 | |
|         self.Modify(False)
 | |
|         self.SetDocumentSaved(True)
 | |
|         self.UpdateAllViews()
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def LoadObject(self, file):
 | |
|         """
 | |
|         Override this function and call it from your own LoadObject before
 | |
|         loading your own data. LoadObject is called by the framework
 | |
|         automatically when the document contents need to be loaded.
 | |
| 
 | |
|         Note that the wxPython version simply sends you a Python file object,
 | |
|         so you can use pickle.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def SaveObject(self, file):
 | |
|         """
 | |
|         Override this function and call it from your own SaveObject before
 | |
|         saving your own data. SaveObject is called by the framework
 | |
|         automatically when the document contents need to be saved.
 | |
| 
 | |
|         Note that the wxPython version simply sends you a Python file object,
 | |
|         so you can use pickle.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def Revert(self):
 | |
|         """
 | |
|         Override this function to revert the document to its last saved state.
 | |
|         """
 | |
|         return False
 | |
| 
 | |
| 
 | |
|     def GetPrintableName(self):
 | |
|         """
 | |
|         Copies a suitable document name into the supplied name buffer.
 | |
|         The default function uses the title, or if there is no title, uses the
 | |
|         filename; or if no filename, the string 'Untitled'.
 | |
|         """
 | |
|         if self._documentTitle:
 | |
|             return self._documentTitle
 | |
|         elif self._documentFile:
 | |
|             return FileNameFromPath(self._documentFile)
 | |
|         else:
 | |
|             return _("Untitled")
 | |
| 
 | |
| 
 | |
|     def GetDocumentWindow(self):
 | |
|         """
 | |
|         Intended to return a suitable window for using as a parent for
 | |
|         document-related dialog boxes. By default, uses the frame associated
 | |
|         with the first view.
 | |
|         """
 | |
|         if len(self._documentViews) > 0:
 | |
|             return self._documentViews[0].GetFrame()
 | |
|         else:
 | |
|             return wx.GetApp().GetTopWindow()
 | |
| 
 | |
| 
 | |
|     def OnCreateCommandProcessor(self):
 | |
|         """
 | |
|         Override this function if you want a different (or no) command
 | |
|         processor to be created when the document is created. By default, it
 | |
|         returns an instance of wxCommandProcessor.
 | |
|         """
 | |
|         return CommandProcessor()
 | |
| 
 | |
| 
 | |
|     def OnSaveModified(self):
 | |
|         """
 | |
|         If the document has been modified, prompts the user to ask if the
 | |
|         changes should be changed. If the user replies Yes, the Save function
 | |
|         is called. If No, the document is marked as unmodified and the
 | |
|         function succeeds. If Cancel, the function fails.
 | |
|         """
 | |
|         if not self.IsModified():
 | |
|             return True
 | |
| 
 | |
|         """ check for file modification outside of application """
 | |
|         if not self.IsDocumentModificationDateCorrect():
 | |
|             msgTitle = wx.GetApp().GetAppName()
 | |
|             if not msgTitle:
 | |
|                 msgTitle = _("Warning")
 | |
|             res = wx.MessageBox(_("'%s' has been modified outside of %s.  Overwrite '%s' with current changes?") % (self.GetPrintableName(), msgTitle, self.GetPrintableName()),
 | |
|                                 msgTitle,
 | |
|                                 wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
 | |
|                                 self.GetDocumentWindow())
 | |
|     
 | |
|             if res == wx.NO:
 | |
|                 self.Modify(False)
 | |
|                 return True
 | |
|             elif res == wx.YES:
 | |
|                 return wx.lib.docview.Document.Save(self)
 | |
|             else: # elif res == wx.CANCEL:
 | |
|                 return False
 | |
| 
 | |
|         msgTitle = wx.GetApp().GetAppName()
 | |
|         if not msgTitle:
 | |
|             msgTitle = _("Warning")
 | |
| 
 | |
|         res = wx.MessageBox(_("Save changes to '%s'?") % self.GetPrintableName(),
 | |
|                             msgTitle,
 | |
|                             wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION,
 | |
|                             self.GetDocumentWindow())
 | |
| 
 | |
|         if res == wx.NO:
 | |
|             self.Modify(False)
 | |
|             return True
 | |
|         elif res == wx.YES:
 | |
|             return self.Save()
 | |
|         else: # elif res == wx.CANCEL:
 | |
|             return False
 | |
| 
 | |
| 
 | |
|     def Draw(context):
 | |
|         """
 | |
|         Called by printing framework to draw the view.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def AddView(self, view):
 | |
|         """
 | |
|         If the view is not already in the list of views, adds the view and
 | |
|         calls OnChangedViewList.
 | |
|         """
 | |
|         if not view in self._documentViews:
 | |
|             self._documentViews.append(view)
 | |
|             self.OnChangedViewList()
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def RemoveView(self, view):
 | |
|         """
 | |
|         Removes the view from the document's list of views, and calls
 | |
|         OnChangedViewList.
 | |
|         """
 | |
|         if view in self._documentViews:
 | |
|             self._documentViews.remove(view)
 | |
|             self.OnChangedViewList()
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def OnCreate(self, path, flags):
 | |
|         """
 | |
|         The default implementation calls DeleteContents (an empty
 | |
|         implementation) sets the modified flag to false. Override this to
 | |
|         supply additional behaviour when the document is opened with Open.
 | |
|         """
 | |
|         if flags & DOC_NO_VIEW:
 | |
|             return True
 | |
|         return self.GetDocumentTemplate().CreateView(self, flags)
 | |
| 
 | |
| 
 | |
|     def OnChangedViewList(self):
 | |
|         """
 | |
|         Called when a view is added to or deleted from this document. The
 | |
|         default implementation saves and deletes the document if no views
 | |
|         exist (the last one has just been removed).
 | |
|         """
 | |
|         if len(self._documentViews) == 0:
 | |
|             if self.OnSaveModified():
 | |
|                 pass # C version does a delete but Python will garbage collect
 | |
| 
 | |
| 
 | |
|     def UpdateAllViews(self, sender = None, hint = None):
 | |
|         """
 | |
|         Updates all views. If sender is non-NULL, does not update this view.
 | |
|         hint represents optional information to allow a view to optimize its
 | |
|         update.
 | |
|         """
 | |
|         for view in self._documentViews:
 | |
|             if view != sender:
 | |
|                 view.OnUpdate(sender, hint)
 | |
| 
 | |
| 
 | |
|     def NotifyClosing(self):
 | |
|         """
 | |
|         Notifies the views that the document is going to close.
 | |
|         """
 | |
|         for view in self._documentViews:
 | |
|             view.OnClosingDocument()
 | |
| 
 | |
| 
 | |
|     def SetFilename(self, filename, notifyViews = False):
 | |
|         """
 | |
|         Sets the filename for this document. Usually called by the framework.
 | |
|         If notifyViews is true, wxView.OnChangeFilename is called for all
 | |
|         views.
 | |
|         """
 | |
|         self._documentFile = filename
 | |
|         if notifyViews:
 | |
|             for view in self._documentViews:
 | |
|                 view.OnChangeFilename()
 | |
| 
 | |
| 
 | |
|     def GetWriteable(self):
 | |
|         """
 | |
|         Returns true if the document can be written to its accociated file path.
 | |
|         This method has been added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         if not self._writeable:
 | |
|             return False 
 | |
|         if not self._documentFile:  # Doesn't exist, do a save as
 | |
|             return True
 | |
|         else:
 | |
|             return os.access(self._documentFile, os.W_OK)
 | |
| 
 | |
| 
 | |
|     def SetWriteable(self, writeable):
 | |
|         """
 | |
|         Set to False if the document can not be saved.  This will disable the ID_SAVE_AS
 | |
|         event and is useful for custom documents that should not be saveable.  The ID_SAVE
 | |
|         event can be disabled by never Modifying the document.  This method has been added
 | |
|         to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         self._writeable = writeable
 | |
| 
 | |
| 
 | |
| class View(wx.EvtHandler):
 | |
|     """
 | |
|     The view class can be used to model the viewing and editing component of
 | |
|     an application's file-based data. It is part of the document/view
 | |
|     framework supported by wxWindows, and cooperates with the wxDocument,
 | |
|     wxDocTemplate and wxDocManager classes.
 | |
|     """
 | |
| 
 | |
|     def __init__(self):
 | |
|         """
 | |
|         Constructor. Define your own default constructor to initialize
 | |
|         application-specific data.
 | |
|         """
 | |
|         wx.EvtHandler.__init__(self)
 | |
|         self._viewDocument = None
 | |
|         self._viewFrame = None
 | |
| 
 | |
| 
 | |
|     def Destroy(self):
 | |
|         """
 | |
|         Destructor. Removes itself from the document's list of views.
 | |
|         """
 | |
|         if self._viewDocument:
 | |
|             self._viewDocument.RemoveView(self)
 | |
|         wx.EvtHandler.Destroy(self)
 | |
| 
 | |
| 
 | |
|     def ProcessEvent(self, event):
 | |
|         """
 | |
|         Processes an event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         if not self.GetDocument() or not self.GetDocument().ProcessEvent(event):
 | |
|             return False
 | |
|         else:
 | |
|             return True
 | |
| 
 | |
| 
 | |
|     def ProcessUpdateUIEvent(self, event):
 | |
|         """
 | |
|         Processes a UI event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         return False
 | |
| 
 | |
| 
 | |
|     def OnActivateView(self, activate, activeView, deactiveView):
 | |
|         """
 | |
|         Called when a view is activated by means of wxView::Activate. The
 | |
|         default implementation does nothing.
 | |
|         """
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def OnClosingDocument(self):
 | |
|         """
 | |
|         Override this to clean up the view when the document is being closed.
 | |
|         The default implementation does nothing.
 | |
|         """
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def OnDraw(self, dc):
 | |
|         """
 | |
|         Override this to draw the view for the printing framework.  The
 | |
|         default implementation does nothing.
 | |
|         """
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def OnPrint(self, dc, info):
 | |
|         """
 | |
|         Override this to print the view for the printing framework.  The
 | |
|         default implementation calls View.OnDraw.
 | |
|         """
 | |
|         self.OnDraw(dc)
 | |
| 
 | |
| 
 | |
|     def OnUpdate(self, sender, hint):
 | |
|         """
 | |
|         Called when the view should be updated. sender is a pointer to the
 | |
|         view that sent the update request, or NULL if no single view requested
 | |
|         the update (for instance, when the document is opened). hint is as yet
 | |
|         unused but may in future contain application-specific information for
 | |
|         making updating more efficient.
 | |
|         """
 | |
|         if hint:
 | |
|             if hint[0] == "modify":  # if dirty flag changed, update the view's displayed title
 | |
|                 frame = self.GetFrame()
 | |
|                 if frame and hasattr(frame, "OnTitleIsModified"):
 | |
|                     frame.OnTitleIsModified()
 | |
|                     return True
 | |
|         return False
 | |
|         
 | |
| 
 | |
|     def OnChangeFilename(self):
 | |
|         """
 | |
|         Called when the filename has changed. The default implementation
 | |
|         constructs a suitable title and sets the title of the view frame (if
 | |
|         any).
 | |
|         """
 | |
|         if self.GetFrame():
 | |
|             appName = wx.GetApp().GetAppName()
 | |
|             if not self.GetDocument():
 | |
|                 if appName:
 | |
|                     title = appName
 | |
|                 else:
 | |
|                     return
 | |
|             else:
 | |
|                 if appName and isinstance(self.GetFrame(), DocChildFrame):  # Only need app name in title for SDI
 | |
|                     title = appName + _(" - ")
 | |
|                 else:
 | |
|                     title = ''
 | |
|                 self.GetFrame().SetTitle(title + self.GetDocument().GetPrintableName())
 | |
| 
 | |
| 
 | |
|     def GetDocument(self):
 | |
|         """
 | |
|         Returns the document associated with the view.
 | |
|         """
 | |
|         return self._viewDocument
 | |
| 
 | |
| 
 | |
|     def SetDocument(self, doc):
 | |
|         """
 | |
|         Associates the given document with the view. Normally called by the
 | |
|         framework.
 | |
|         """
 | |
|         self._viewDocument = doc
 | |
|         if doc:
 | |
|             doc.AddView(self)
 | |
| 
 | |
| 
 | |
|     def GetViewName(self):
 | |
|         """
 | |
|         Gets the name associated with the view (passed to the wxDocTemplate
 | |
|         constructor). Not currently used by the framework.
 | |
|         """
 | |
|         return self._viewTypeName
 | |
| 
 | |
| 
 | |
|     def SetViewName(self, name):
 | |
|         """
 | |
|         Sets the view type name. Should only be called by the framework.
 | |
|         """
 | |
|         self._viewTypeName = name
 | |
| 
 | |
| 
 | |
|     def Close(self, deleteWindow=True):
 | |
|         """
 | |
|         Closes the view by calling OnClose. If deleteWindow is true, this
 | |
|         function should delete the window associated with the view.
 | |
|         """
 | |
|         if self.OnClose(deleteWindow = deleteWindow):
 | |
|             return True
 | |
|         else:
 | |
|             return False
 | |
| 
 | |
| 
 | |
|     def Activate(self, activate=True):
 | |
|         """
 | |
|         Call this from your view frame's OnActivate member to tell the
 | |
|         framework which view is currently active. If your windowing system
 | |
|         doesn't call OnActivate, you may need to call this function from
 | |
|         OnMenuCommand or any place where you know the view must be active, and
 | |
|         the framework will need to get the current view.
 | |
| 
 | |
|         The prepackaged view frame wxDocChildFrame calls wxView.Activate from
 | |
|         its OnActivate member and from its OnMenuCommand member.
 | |
|         """
 | |
|         if self.GetDocument() and self.GetDocumentManager():
 | |
|             self.OnActivateView(activate, self, self.GetDocumentManager().GetCurrentView())
 | |
|             self.GetDocumentManager().ActivateView(self, activate)
 | |
| 
 | |
| 
 | |
|     def OnClose(self, deleteWindow=True):
 | |
|         """
 | |
|         Implements closing behaviour. The default implementation calls
 | |
|         wxDocument.Close to close the associated document. Does not delete the
 | |
|         view. The application may wish to do some cleaning up operations in
 | |
|         this function, if a call to wxDocument::Close succeeded. For example,
 | |
|         if your application's all share the same window, you need to
 | |
|         disassociate the window from the view and perhaps clear the window. If
 | |
|         deleteWindow is true, delete the frame associated with the view.
 | |
|         """
 | |
|         if self.GetDocument():
 | |
|             return self.GetDocument().Close()
 | |
|         else:
 | |
|             return True
 | |
| 
 | |
| 
 | |
|     def OnCreate(self, doc, flags):
 | |
|         """
 | |
|         wxDocManager or wxDocument creates a wxView via a wxDocTemplate. Just
 | |
|         after the wxDocTemplate creates the wxView, it calls wxView::OnCreate.
 | |
|         In its OnCreate member function, the wxView can create a
 | |
|         wxDocChildFrame or a derived class. This wxDocChildFrame provides user
 | |
|         interface elements to view and/or edit the contents of the wxDocument.
 | |
| 
 | |
|         By default, simply returns true. If the function returns false, the
 | |
|         view will be deleted.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def OnCreatePrintout(self):
 | |
|         """
 | |
|         Returns a wxPrintout object for the purposes of printing. It should
 | |
|         create a new object every time it is called; the framework will delete
 | |
|         objects it creates.
 | |
| 
 | |
|         By default, this function returns an instance of wxDocPrintout, which
 | |
|         prints and previews one page by calling wxView.OnDraw.
 | |
| 
 | |
|         Override to return an instance of a class other than wxDocPrintout.
 | |
|         """
 | |
|         return DocPrintout(self, self.GetDocument().GetPrintableName())
 | |
| 
 | |
| 
 | |
|     def GetFrame(self):
 | |
|         """
 | |
|         Gets the frame associated with the view (if any). Note that this
 | |
|         "frame" is not a wxFrame at all in the generic MDI implementation
 | |
|         which uses the notebook pages instead of the frames and this is why
 | |
|         this method returns a wxWindow and not a wxFrame.
 | |
|         """
 | |
|         return self._viewFrame
 | |
| 
 | |
| 
 | |
|     def SetFrame(self, frame):
 | |
|         """
 | |
|         Sets the frame associated with this view. The application should call
 | |
|         this if possible, to tell the view about the frame.  See GetFrame for
 | |
|         the explanation about the mismatch between the "Frame" in the method
 | |
|         name and the type of its parameter.
 | |
|         """
 | |
|         self._viewFrame = frame
 | |
| 
 | |
| 
 | |
|     def GetDocumentManager(self):
 | |
|         """
 | |
|         Returns the document manager instance associated with this view.
 | |
|         """
 | |
|         if self._viewDocument:
 | |
|             return self.GetDocument().GetDocumentManager()
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
| 
 | |
| class DocTemplate(wx.Object):
 | |
|     """
 | |
|     The wxDocTemplate class is used to model the relationship between a
 | |
|     document class and a view class.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=DEFAULT_TEMPLATE_FLAGS, icon=None):
 | |
|         """
 | |
|         Constructor. Create instances dynamically near the start of your
 | |
|         application after creating a wxDocManager instance, and before doing
 | |
|         any document or view operations.
 | |
| 
 | |
|         manager is the document manager object which manages this template.
 | |
| 
 | |
|         description is a short description of what the template is for. This
 | |
|         string will be displayed in the file filter list of Windows file
 | |
|         selectors.
 | |
| 
 | |
|         filter is an appropriate file filter such as \*.txt.
 | |
| 
 | |
|         dir is the default directory to use for file selectors.
 | |
| 
 | |
|         ext is the default file extension (such as txt).
 | |
| 
 | |
|         docTypeName is a name that should be unique for a given type of
 | |
|         document, used for gathering a list of views relevant to a
 | |
|         particular document.
 | |
| 
 | |
|         viewTypeName is a name that should be unique for a given view.
 | |
| 
 | |
|         docClass is a Python class. If this is not supplied, you will need to
 | |
|         derive a new wxDocTemplate class and override the CreateDocument
 | |
|         member to return a new document instance on demand.
 | |
| 
 | |
|         viewClass is a Python class. If this is not supplied, you will need to
 | |
|         derive a new wxDocTemplate class and override the CreateView member to
 | |
|         return a new view instance on demand.
 | |
| 
 | |
|         flags is a bit list of the following:
 | |
|         wx.TEMPLATE_VISIBLE The template may be displayed to the user in
 | |
|         dialogs.
 | |
| 
 | |
|         wx.TEMPLATE_INVISIBLE The template may not be displayed to the user in
 | |
|         dialogs.
 | |
| 
 | |
|         wx.DEFAULT_TEMPLATE_FLAGS Defined as wxTEMPLATE_VISIBLE.
 | |
|         """
 | |
|         self._docManager = manager
 | |
|         self._description = description
 | |
|         self._fileFilter = filter
 | |
|         self._directory = dir
 | |
|         self._defaultExt = ext
 | |
|         self._docTypeName = docTypeName
 | |
|         self._viewTypeName = viewTypeName
 | |
|         self._docType = docType
 | |
|         self._viewType = viewType
 | |
|         self._flags = flags
 | |
|         self._icon = icon
 | |
| 
 | |
|         self._docManager.AssociateTemplate(self)
 | |
| 
 | |
| 
 | |
|     def GetDefaultExtension(self):
 | |
|         """
 | |
|         Returns the default file extension for the document data, as passed to
 | |
|         the document template constructor.
 | |
|         """
 | |
|         return self._defaultExt
 | |
| 
 | |
| 
 | |
|     def SetDefaultExtension(self, defaultExt):
 | |
|         """
 | |
|         Sets the default file extension.
 | |
|         """
 | |
|         self._defaultExt = defaultExt
 | |
| 
 | |
| 
 | |
|     def GetDescription(self):
 | |
|         """
 | |
|         Returns the text description of this template, as passed to the
 | |
|         document template constructor.
 | |
|         """
 | |
|         return self._description
 | |
| 
 | |
| 
 | |
|     def SetDescription(self, description):
 | |
|         """
 | |
|         Sets the template description.
 | |
|         """
 | |
|         self._description = description
 | |
| 
 | |
| 
 | |
|     def GetDirectory(self):
 | |
|         """
 | |
|         Returns the default directory, as passed to the document template
 | |
|         constructor.
 | |
|         """
 | |
|         return self._directory
 | |
| 
 | |
| 
 | |
|     def SetDirectory(self, dir):
 | |
|         """
 | |
|         Sets the default directory.
 | |
|         """
 | |
|         self._directory = dir
 | |
| 
 | |
| 
 | |
|     def GetDocumentManager(self):
 | |
|         """
 | |
|         Returns the document manager instance for which this template was
 | |
|         created.
 | |
|         """
 | |
|         return self._docManager
 | |
| 
 | |
| 
 | |
|     def SetDocumentManager(self, manager):
 | |
|         """
 | |
|         Sets the document manager instance for which this template was
 | |
|         created. Should not be called by the application.
 | |
|         """
 | |
|         self._docManager = manager
 | |
| 
 | |
| 
 | |
|     def GetFileFilter(self):
 | |
|         """
 | |
|         Returns the file filter, as passed to the document template
 | |
|         constructor.
 | |
|         """
 | |
|         return self._fileFilter
 | |
| 
 | |
| 
 | |
|     def SetFileFilter(self, filter):
 | |
|         """
 | |
|         Sets the file filter.
 | |
|         """
 | |
|         self._fileFilter = filter
 | |
| 
 | |
| 
 | |
|     def GetFlags(self):
 | |
|         """
 | |
|         Returns the flags, as passed to the document template constructor.
 | |
|         (see the constructor description for more details).
 | |
|         """
 | |
|         return self._flags
 | |
| 
 | |
| 
 | |
|     def SetFlags(self, flags):
 | |
|         """
 | |
|         Sets the internal document template flags (see the constructor
 | |
|         description for more details).
 | |
|         """
 | |
|         self._flags = flags
 | |
| 
 | |
| 
 | |
|     def GetIcon(self):
 | |
|         """
 | |
|         Returns the icon, as passed to the document template
 | |
|         constructor.  This method has been added to wxPython and is
 | |
|         not in wxWindows.
 | |
|         """
 | |
|         return self._icon
 | |
| 
 | |
| 
 | |
|     def SetIcon(self, flags):
 | |
|         """
 | |
|         Sets the icon.  This method has been added to wxPython and is not
 | |
|         in wxWindows.
 | |
|         """
 | |
|         self._icon = icon
 | |
| 
 | |
| 
 | |
|     def GetDocumentType(self):
 | |
|         """
 | |
|         Returns the Python document class, as passed to the document template
 | |
|         constructor.
 | |
|         """
 | |
|         return self._docType
 | |
| 
 | |
| 
 | |
|     def GetViewType(self):
 | |
|         """
 | |
|         Returns the Python view class, as passed to the document template
 | |
|         constructor.
 | |
|         """
 | |
|         return self._viewType
 | |
| 
 | |
| 
 | |
|     def IsVisible(self):
 | |
|         """
 | |
|         Returns true if the document template can be shown in user dialogs,
 | |
|         false otherwise.
 | |
|         """
 | |
|         return (self._flags & TEMPLATE_VISIBLE) == TEMPLATE_VISIBLE
 | |
| 
 | |
| 
 | |
|     def IsNewable(self):
 | |
|         """
 | |
|         Returns true if the document template can be shown in "New" dialogs,
 | |
|         false otherwise.
 | |
|         
 | |
|         This method has been added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         return (self._flags & TEMPLATE_NO_CREATE) != TEMPLATE_NO_CREATE
 | |
|         
 | |
| 
 | |
|     def GetDocumentName(self):
 | |
|         """
 | |
|         Returns the document type name, as passed to the document template
 | |
|         constructor.
 | |
|         """
 | |
|         return self._docTypeName
 | |
| 
 | |
| 
 | |
|     def GetViewName(self):
 | |
|         """
 | |
|         Returns the view type name, as passed to the document template
 | |
|         constructor.
 | |
|         """
 | |
|         return self._viewTypeName
 | |
| 
 | |
| 
 | |
|     def CreateDocument(self, path, flags):
 | |
|         """
 | |
|         Creates a new instance of the associated document class. If you have
 | |
|         not supplied a class to the template constructor, you will need to
 | |
|         override this function to return an appropriate document instance.
 | |
|         """
 | |
|         doc = self._docType()
 | |
|         doc.SetFilename(path)
 | |
|         doc.SetDocumentTemplate(self)
 | |
|         self.GetDocumentManager().AddDocument(doc)
 | |
|         doc.SetCommandProcessor(doc.OnCreateCommandProcessor())
 | |
|         if doc.OnCreate(path, flags):
 | |
|             return doc
 | |
|         else:
 | |
|             if doc in self.GetDocumentManager().GetDocuments():
 | |
|                 doc.DeleteAllViews()
 | |
|             return None
 | |
| 
 | |
| 
 | |
|     def CreateView(self, doc, flags):
 | |
|         """
 | |
|         Creates a new instance of the associated document view. If you have
 | |
|         not supplied a class to the template constructor, you will need to
 | |
|         override this function to return an appropriate view instance.
 | |
|         """
 | |
|         view = self._viewType()
 | |
|         view.SetDocument(doc)
 | |
|         if view.OnCreate(doc, flags):
 | |
|             return view
 | |
|         else:
 | |
|             view.Destroy()
 | |
|             return None
 | |
| 
 | |
| 
 | |
|     def FileMatchesTemplate(self, path):
 | |
|         """
 | |
|         Returns True if the path's extension matches one of this template's
 | |
|         file filter extensions.
 | |
|         """
 | |
|         ext = FindExtension(path)
 | |
|         if not ext: return False
 | |
|         
 | |
|         extList = self.GetFileFilter().replace('*','').split(';')
 | |
|         return ext in extList
 | |
| 
 | |
| 
 | |
| class DocManager(wx.EvtHandler):
 | |
|     """
 | |
|     The wxDocManager class is part of the document/view framework supported by
 | |
|     wxWindows, and cooperates with the wxView, wxDocument and wxDocTemplate
 | |
|     classes.
 | |
|     """
 | |
| 
 | |
|     def __init__(self, flags=DEFAULT_DOCMAN_FLAGS, initialize=True):
 | |
|         """
 | |
|         Constructor. Create a document manager instance dynamically near the
 | |
|         start of your application before doing any document or view operations.
 | |
| 
 | |
|         flags is used in the Python version to indicate whether the document
 | |
|         manager is in DOC_SDI or DOC_MDI mode.
 | |
| 
 | |
|         If initialize is true, the Initialize function will be called to
 | |
|         create a default history list object. If you derive from wxDocManager,
 | |
|         you may wish to call the base constructor with false, and then call
 | |
|         Initialize in your own constructor, to allow your own Initialize or
 | |
|         OnCreateFileHistory functions to be called.
 | |
|         """
 | |
| 
 | |
|         wx.EvtHandler.__init__(self)
 | |
| 
 | |
|         self._defaultDocumentNameCounter = 1
 | |
|         self._flags = flags
 | |
|         self._currentView = None
 | |
|         self._lastActiveView = None
 | |
|         self._maxDocsOpen = 10000
 | |
|         self._fileHistory = None
 | |
|         self._templates = []
 | |
|         self._docs = []
 | |
|         self._lastDirectory = ""
 | |
| 
 | |
|         if initialize:
 | |
|             self.Initialize()
 | |
| 
 | |
|         wx.EVT_MENU(self, wx.ID_OPEN, self.OnFileOpen)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE, self.OnFileClose)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.OnFileCloseAll)
 | |
|         wx.EVT_MENU(self, wx.ID_REVERT, self.OnFileRevert)
 | |
|         wx.EVT_MENU(self, wx.ID_NEW, self.OnFileNew)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVE, self.OnFileSave)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVEAS, self.OnFileSaveAs)
 | |
|         wx.EVT_MENU(self, wx.ID_UNDO, self.OnUndo)
 | |
|         wx.EVT_MENU(self, wx.ID_REDO, self.OnRedo)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT, self.OnPrint)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.OnPrintSetup)
 | |
|         wx.EVT_MENU(self, wx.ID_PREVIEW, self.OnPreview)
 | |
| 
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.OnUpdateFileOpen)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.OnUpdateFileClose)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.OnUpdateFileCloseAll)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.OnUpdateFileRevert)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.OnUpdateFileNew)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.OnUpdateFileSave)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.OnUpdateFileSaveAs)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.OnUpdateUndo)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.OnUpdateRedo)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.OnUpdatePrint)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.OnUpdatePrintSetup)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.OnUpdatePreview)
 | |
| 
 | |
| 
 | |
|     def Destroy(self):
 | |
|         """
 | |
|         Destructor.
 | |
|         """
 | |
|         self.Clear()
 | |
|         wx.EvtHandler.Destroy(self)
 | |
| 
 | |
| 
 | |
|     def GetFlags(self):
 | |
|         """
 | |
|         Returns the document manager's flags.  This method has been
 | |
|         added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         return self._flags
 | |
| 
 | |
| 
 | |
|     def CloseDocument(self, doc, force=True):
 | |
|         """
 | |
|         Closes the specified document.
 | |
|         """
 | |
|         if doc.Close() or force:
 | |
|             doc.DeleteAllViews()
 | |
|             if doc in self._docs:
 | |
|                 doc.Destroy()
 | |
|             return True
 | |
|         return False
 | |
| 
 | |
| 
 | |
|     def CloseDocuments(self, force=True):
 | |
|         """
 | |
|         Closes all currently opened documents.
 | |
|         """
 | |
|         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
 | |
|             if not self.CloseDocument(document, force):
 | |
|                 return False
 | |
|             if document:
 | |
|                 document.DeleteAllViews() # Implicitly delete the document when the last view is removed
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def Clear(self, force=True):
 | |
|         """
 | |
|         Closes all currently opened document by callling CloseDocuments and
 | |
|         clears the document manager's templates.
 | |
|         """
 | |
|         if not self.CloseDocuments(force):
 | |
|             return False
 | |
|         self._templates = []
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def Initialize(self):
 | |
|         """
 | |
|         Initializes data; currently just calls OnCreateFileHistory. Some data
 | |
|         cannot always be initialized in the constructor because the programmer
 | |
|         must be given the opportunity to override functionality. In fact
 | |
|         Initialize is called from the wxDocManager constructor, but this can
 | |
|         be vetoed by passing false to the second argument, allowing the
 | |
|         derived class's constructor to call Initialize, possibly calling a
 | |
|         different OnCreateFileHistory from the default.
 | |
| 
 | |
|         The bottom line: if you're not deriving from Initialize, forget it and
 | |
|         construct wxDocManager with no arguments.
 | |
|         """
 | |
|         self.OnCreateFileHistory()
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def OnCreateFileHistory(self):
 | |
|         """
 | |
|         A hook to allow a derived class to create a different type of file
 | |
|         history. Called from Initialize.
 | |
|         """
 | |
|         self._fileHistory = wx.FileHistory()
 | |
| 
 | |
| 
 | |
|     def OnFileClose(self, event):
 | |
|         """
 | |
|         Closes and deletes the currently active document.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         if doc:
 | |
|             doc.DeleteAllViews()
 | |
|             if doc in self._docs:
 | |
|                 self._docs.remove(doc)
 | |
| 
 | |
| 
 | |
|     def OnFileCloseAll(self, event):
 | |
|         """
 | |
|         Closes and deletes all the currently opened documents.
 | |
|         """
 | |
|         return self.CloseDocuments(force = False)
 | |
| 
 | |
|     
 | |
|     def OnFileNew(self, event):
 | |
|         """
 | |
|         Creates a new document and reads in the selected file.
 | |
|         """
 | |
|         self.CreateDocument('', DOC_NEW)
 | |
| 
 | |
| 
 | |
|     def OnFileOpen(self, event):
 | |
|         """
 | |
|         Creates a new document and reads in the selected file.
 | |
|         """
 | |
|         if not self.CreateDocument('', DEFAULT_DOCMAN_FLAGS):
 | |
|             self.OnOpenFileFailure()
 | |
| 
 | |
| 
 | |
|     def OnFileRevert(self, event):
 | |
|         """
 | |
|         Reverts the current document by calling wxDocument.Save for the current
 | |
|         document.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         if not doc:
 | |
|             return
 | |
|         doc.Revert()
 | |
| 
 | |
| 
 | |
|     def OnFileSave(self, event):
 | |
|         """
 | |
|         Saves the current document by calling wxDocument.Save for the current
 | |
|         document.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         if not doc:
 | |
|             return
 | |
|         doc.Save()
 | |
| 
 | |
| 
 | |
|     def OnFileSaveAs(self, event):
 | |
|         """
 | |
|         Calls wxDocument.SaveAs for the current document.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         if not doc:
 | |
|             return
 | |
|         doc.SaveAs()
 | |
| 
 | |
| 
 | |
|     def OnPrint(self, event):
 | |
|         """
 | |
|         Prints the current document by calling its View's OnCreatePrintout
 | |
|         method.
 | |
|         """
 | |
|         view = self.GetCurrentView()
 | |
|         if not view:
 | |
|             return
 | |
| 
 | |
|         printout = view.OnCreatePrintout()
 | |
|         if printout:
 | |
|             if not hasattr(self, "printData"):
 | |
|                 self.printData = wx.PrintData()
 | |
|                 self.printData.SetPaperId(wx.PAPER_LETTER)
 | |
|             self.printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
 | |
|                 
 | |
|             pdd = wx.PrintDialogData(self.printData)
 | |
|             printer = wx.Printer(pdd)
 | |
|             printer.Print(view.GetFrame(), printout)
 | |
| 
 | |
| 
 | |
|     def OnPrintSetup(self, event):
 | |
|         """
 | |
|         Presents the print setup dialog.
 | |
|         """
 | |
|         view = self.GetCurrentView()
 | |
|         if view:
 | |
|             parentWin = view.GetFrame()
 | |
|         else:
 | |
|             parentWin = wx.GetApp().GetTopWindow()
 | |
| 
 | |
|         if not hasattr(self, "printData"):
 | |
|             self.printData = wx.PrintData()
 | |
|             self.printData.SetPaperId(wx.PAPER_LETTER)
 | |
|             
 | |
|         data = wx.PrintDialogData(self.printData)
 | |
|         printDialog = wx.PrintDialog(parentWin, data)
 | |
|         printDialog.GetPrintDialogData().SetSetupDialog(True)
 | |
|         printDialog.ShowModal()
 | |
|         
 | |
|         # this makes a copy of the wx.PrintData instead of just saving
 | |
|         # a reference to the one inside the PrintDialogData that will
 | |
|         # be destroyed when the dialog is destroyed
 | |
|         self.printData = wx.PrintData(printDialog.GetPrintDialogData().GetPrintData())
 | |
|         
 | |
|         printDialog.Destroy()
 | |
| 
 | |
| 
 | |
|     def OnPreview(self, event):
 | |
|         """
 | |
|         Previews the current document by calling its View's OnCreatePrintout
 | |
|         method.
 | |
|         """
 | |
|         view = self.GetCurrentView()
 | |
|         if not view:
 | |
|             return
 | |
| 
 | |
|         printout = view.OnCreatePrintout()
 | |
|         if printout:
 | |
|             if not hasattr(self, "printData"):
 | |
|                 self.printData = wx.PrintData()
 | |
|                 self.printData.SetPaperId(wx.PAPER_LETTER)
 | |
|             self.printData.SetPrintMode(wx.PRINT_MODE_PREVIEW)
 | |
|                 
 | |
|             data = wx.PrintDialogData(self.printData)
 | |
|             # Pass two printout objects: for preview, and possible printing.
 | |
|             preview = wx.PrintPreview(printout, view.OnCreatePrintout(), data)
 | |
|             if not preview.Ok():
 | |
|                 wx.MessageBox(_("Unable to display print preview."))
 | |
|                 return
 | |
|             # 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.
 | |
|             mimicFrame =  wx.GetApp().GetTopWindow()
 | |
|             frame = wx.PreviewFrame(preview, mimicFrame, _("Print Preview"), mimicFrame.GetPosition(), mimicFrame.GetSize())
 | |
|             frame.SetIcon(mimicFrame.GetIcon())
 | |
|             frame.SetTitle(_("%s - %s - Preview") % (mimicFrame.GetTitle(), view.GetDocument().GetPrintableName()))
 | |
|             frame.Initialize()
 | |
|             frame.Show(True)
 | |
| 
 | |
| 
 | |
|     def OnUndo(self, event):
 | |
|         """
 | |
|         Issues an Undo command to the current document's command processor.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         if not doc:
 | |
|             return
 | |
|         if doc.GetCommandProcessor():
 | |
|             doc.GetCommandProcessor().Undo()
 | |
| 
 | |
| 
 | |
|     def OnRedo(self, event):
 | |
|         """
 | |
|         Issues a Redo command to the current document's command processor.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         if not doc:
 | |
|             return
 | |
|         if doc.GetCommandProcessor():
 | |
|             doc.GetCommandProcessor().Redo()
 | |
| 
 | |
| 
 | |
|     def OnUpdateFileOpen(self, event):
 | |
|         """
 | |
|         Updates the user interface for the File Open command.
 | |
|         """
 | |
|         event.Enable(True)
 | |
| 
 | |
| 
 | |
|     def OnUpdateFileClose(self, event):
 | |
|         """
 | |
|         Updates the user interface for the File Close command.
 | |
|         """
 | |
|         event.Enable(self.GetCurrentDocument() != None)
 | |
| 
 | |
| 
 | |
|     def OnUpdateFileCloseAll(self, event):
 | |
|         """
 | |
|         Updates the user interface for the File Close All command.
 | |
|         """
 | |
|         event.Enable(self.GetCurrentDocument() != None)
 | |
| 
 | |
| 
 | |
|     def OnUpdateFileRevert(self, event):
 | |
|         """
 | |
|         Updates the user interface for the File Revert command.
 | |
|         """
 | |
|         event.Enable(self.GetCurrentDocument() != None)
 | |
| 
 | |
| 
 | |
|     def OnUpdateFileNew(self, event):
 | |
|         """
 | |
|         Updates the user interface for the File New command.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def OnUpdateFileSave(self, event):
 | |
|         """
 | |
|         Updates the user interface for the File Save command.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         event.Enable(doc != None and doc.IsModified())
 | |
| 
 | |
| 
 | |
|     def OnUpdateFileSaveAs(self, event):
 | |
|         """
 | |
|         Updates the user interface for the File Save As command.
 | |
|         """
 | |
|         event.Enable(self.GetCurrentDocument() != None and self.GetCurrentDocument().GetWriteable())
 | |
| 
 | |
| 
 | |
|     def OnUpdateUndo(self, event):
 | |
|         """
 | |
|         Updates the user interface for the Undo command.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         event.Enable(doc != None and doc.GetCommandProcessor() != None and doc.GetCommandProcessor().CanUndo())
 | |
|         if doc and doc.GetCommandProcessor():
 | |
|             doc.GetCommandProcessor().SetMenuStrings()
 | |
|         else:
 | |
|             event.SetText(_("&Undo\tCtrl+Z"))
 | |
| 
 | |
| 
 | |
|     def OnUpdateRedo(self, event):
 | |
|         """
 | |
|         Updates the user interface for the Redo command.
 | |
|         """
 | |
|         doc = self.GetCurrentDocument()
 | |
|         event.Enable(doc != None and doc.GetCommandProcessor() != None and doc.GetCommandProcessor().CanRedo())
 | |
|         if doc and doc.GetCommandProcessor():
 | |
|             doc.GetCommandProcessor().SetMenuStrings()
 | |
|         else:
 | |
|             event.SetText(_("&Redo\tCtrl+Y"))
 | |
| 
 | |
| 
 | |
|     def OnUpdatePrint(self, event):
 | |
|         """
 | |
|         Updates the user interface for the Print command.
 | |
|         """
 | |
|         event.Enable(self.GetCurrentDocument() != None)
 | |
| 
 | |
| 
 | |
|     def OnUpdatePrintSetup(self, event):
 | |
|         """
 | |
|         Updates the user interface for the Print Setup command.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def OnUpdatePreview(self, event):
 | |
|         """
 | |
|         Updates the user interface for the Print Preview command.
 | |
|         """
 | |
|         event.Enable(self.GetCurrentDocument() != None)
 | |
| 
 | |
| 
 | |
|     def GetCurrentView(self):
 | |
|         """
 | |
|         Returns the currently active view.
 | |
|         """
 | |
|         if self._currentView:
 | |
|             return self._currentView
 | |
|         if len(self._docs) == 1:
 | |
|             return self._docs[0].GetFirstView()
 | |
|         return None
 | |
| 
 | |
| 
 | |
|     def GetLastActiveView(self):
 | |
|         """
 | |
|         Returns the last active view.  This is used in the SDI framework where dialogs can be mistaken for a view
 | |
|         and causes the framework to deactivete the current view.  This happens when something like a custom dialog box used
 | |
|         to operate on the current view is shown.
 | |
|         """
 | |
|         if len(self._docs) >= 1:
 | |
|             return self._lastActiveView
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
| 
 | |
|     def ProcessEvent(self, event):
 | |
|         """
 | |
|         Processes an event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         view = self.GetCurrentView()
 | |
|         if view:
 | |
|             if view.ProcessEvent(event):
 | |
|                 return True
 | |
|         id = event.GetId()
 | |
|         if id == wx.ID_OPEN:
 | |
|             self.OnFileOpen(event)
 | |
|             return True
 | |
|         elif id == wx.ID_CLOSE:
 | |
|             self.OnFileClose(event)
 | |
|             return True
 | |
|         elif id == wx.ID_CLOSE_ALL:
 | |
|             self.OnFileCloseAll(event)
 | |
|             return True
 | |
|         elif id == wx.ID_REVERT:
 | |
|             self.OnFileRevert(event)
 | |
|             return True
 | |
|         elif id == wx.ID_NEW:
 | |
|             self.OnFileNew(event)
 | |
|             return True
 | |
|         elif id == wx.ID_SAVE:
 | |
|             self.OnFileSave(event)
 | |
|             return True
 | |
|         elif id == wx.ID_SAVEAS:
 | |
|             self.OnFileSaveAs(event)
 | |
|             return True
 | |
|         elif id == wx.ID_UNDO:
 | |
|             self.OnUndo(event)
 | |
|             return True
 | |
|         elif id == wx.ID_REDO:
 | |
|             self.OnRedo(event)
 | |
|             return True
 | |
|         elif id == wx.ID_PRINT:
 | |
|             self.OnPrint(event)
 | |
|             return True
 | |
|         elif id == wx.ID_PRINT_SETUP:
 | |
|             self.OnPrintSetup(event)
 | |
|             return True
 | |
|         elif id == wx.ID_PREVIEW:
 | |
|             self.OnPreview(event)
 | |
|             return True
 | |
|         else:
 | |
|             return False
 | |
| 
 | |
| 
 | |
|     def ProcessUpdateUIEvent(self, event):
 | |
|         """
 | |
|         Processes a UI event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         id = event.GetId()
 | |
|         view = self.GetCurrentView()
 | |
|         if view:
 | |
|             if view.ProcessUpdateUIEvent(event):
 | |
|                 return True
 | |
|         if id == wx.ID_OPEN:
 | |
|             self.OnUpdateFileOpen(event)
 | |
|             return True
 | |
|         elif id == wx.ID_CLOSE:
 | |
|             self.OnUpdateFileClose(event)
 | |
|             return True
 | |
|         elif id == wx.ID_CLOSE_ALL:
 | |
|             self.OnUpdateFileCloseAll(event)
 | |
|             return True
 | |
|         elif id == wx.ID_REVERT:
 | |
|             self.OnUpdateFileRevert(event)
 | |
|             return True
 | |
|         elif id == wx.ID_NEW:
 | |
|             self.OnUpdateFileNew(event)
 | |
|             return True
 | |
|         elif id == wx.ID_SAVE:
 | |
|             self.OnUpdateFileSave(event)
 | |
|             return True
 | |
|         elif id == wx.ID_SAVEAS:
 | |
|             self.OnUpdateFileSaveAs(event)
 | |
|             return True
 | |
|         elif id == wx.ID_UNDO:
 | |
|             self.OnUpdateUndo(event)
 | |
|             return True
 | |
|         elif id == wx.ID_REDO:
 | |
|             self.OnUpdateRedo(event)
 | |
|             return True
 | |
|         elif id == wx.ID_PRINT:
 | |
|             self.OnUpdatePrint(event)
 | |
|             return True
 | |
|         elif id == wx.ID_PRINT_SETUP:
 | |
|             self.OnUpdatePrintSetup(event)
 | |
|             return True
 | |
|         elif id == wx.ID_PREVIEW:
 | |
|             self.OnUpdatePreview(event)
 | |
|             return True
 | |
|         else:
 | |
|             return False
 | |
| 
 | |
| 
 | |
|     def CreateDocument(self, path, flags=0):
 | |
|         """
 | |
|         Creates a new document in a manner determined by the flags parameter,
 | |
|         which can be:
 | |
| 
 | |
|         wx.lib.docview.DOC_NEW Creates a fresh document.
 | |
|         wx.lib.docview.DOC_SILENT Silently loads the given document file.
 | |
| 
 | |
|         If wx.lib.docview.DOC_NEW is present, a new document will be created and returned,
 | |
|         possibly after asking the user for a template to use if there is more
 | |
|         than one document template. If wx.lib.docview.DOC_SILENT is present, a new document
 | |
|         will be created and the given file loaded into it. If neither of these
 | |
|         flags is present, the user will be presented with a file selector for
 | |
|         the file to load, and the template to use will be determined by the
 | |
|         extension (Windows) or by popping up a template choice list (other
 | |
|         platforms).
 | |
| 
 | |
|         If the maximum number of documents has been reached, this function
 | |
|         will delete the oldest currently loaded document before creating a new
 | |
|         one.
 | |
| 
 | |
|         wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE
 | |
|         and wx.lib.docview.DOC_NO_VIEW flag.
 | |
|         
 | |
|         if wx.lib.docview.DOC_OPEN_ONCE is present, trying to open the same file multiple 
 | |
|         times will just return the same document.
 | |
|         if wx.lib.docview.DOC_NO_VIEW is present, opening a file will generate the document,
 | |
|         but not generate a corresponding view.
 | |
|         """
 | |
|         templates = []
 | |
|         for temp in self._templates:
 | |
|             if temp.IsVisible():
 | |
|                 templates.append(temp)
 | |
|         if len(templates) == 0:
 | |
|             return None
 | |
| 
 | |
|         if len(self.GetDocuments()) >= self._maxDocsOpen:
 | |
|            doc = self.GetDocuments()[0]
 | |
|            if not self.CloseDocument(doc, False):
 | |
|                return None
 | |
| 
 | |
|         if flags & DOC_NEW:
 | |
|             for temp in templates[:]:
 | |
|                 if not temp.IsNewable():
 | |
|                     templates.remove(temp)
 | |
|             if len(templates) == 1:
 | |
|                 temp = templates[0]
 | |
|             else:
 | |
|                 temp = self.SelectDocumentType(templates)
 | |
|             if temp:
 | |
|                 newDoc = temp.CreateDocument(path, flags)
 | |
|                 if newDoc:
 | |
|                     newDoc.SetDocumentName(temp.GetDocumentName())
 | |
|                     newDoc.SetDocumentTemplate(temp)
 | |
|                     newDoc.OnNewDocument()
 | |
|                 return newDoc
 | |
|             else:
 | |
|                 return None
 | |
| 
 | |
|         if path and flags & DOC_SILENT:
 | |
|             temp = self.FindTemplateForPath(path)
 | |
|         else:
 | |
|             temp, path = self.SelectDocumentPath(templates, path, flags)
 | |
| 
 | |
|         # Existing document
 | |
|         if path and self.GetFlags() & DOC_OPEN_ONCE:
 | |
|             for document in self._docs:
 | |
|                 if document.GetFilename() and os.path.normcase(document.GetFilename()) == os.path.normcase(path):
 | |
|                     """ check for file modification outside of application """
 | |
|                     if not document.IsDocumentModificationDateCorrect():
 | |
|                         msgTitle = wx.GetApp().GetAppName()
 | |
|                         if not msgTitle:
 | |
|                             msgTitle = _("Warning")
 | |
|                         shortName = document.GetPrintableName()
 | |
|                         res = wx.MessageBox(_("'%s' has been modified outside of %s.  Reload '%s' from file system?") % (shortName, msgTitle, shortName),
 | |
|                                             msgTitle,
 | |
|                                             wx.YES_NO | wx.ICON_QUESTION,
 | |
|                                             self.FindSuitableParent())
 | |
|                         if res == wx.YES:
 | |
|                            if not self.CloseDocument(document, False):
 | |
|                                wx.MessageBox(_("Couldn't reload '%s'.  Unable to close current '%s'.") % (shortName, shortName))
 | |
|                                return None
 | |
|                            return self.CreateDocument(path, flags)
 | |
|                         elif res == wx.NO:  # don't ask again
 | |
|                             document.SetDocumentModificationDate()
 | |
| 
 | |
|                     firstView = document.GetFirstView()
 | |
|                     if not firstView and not (flags & DOC_NO_VIEW):
 | |
|                         document.GetDocumentTemplate().CreateView(document, flags)
 | |
|                         document.UpdateAllViews()
 | |
|                         firstView = document.GetFirstView()
 | |
|                         
 | |
|                     if firstView and firstView.GetFrame() and not (flags & DOC_NO_VIEW):
 | |
|                         firstView.GetFrame().SetFocus()  # Not in wxWindows code but useful nonetheless
 | |
|                         if hasattr(firstView.GetFrame(), "IsIconized") and firstView.GetFrame().IsIconized():  # Not in wxWindows code but useful nonetheless
 | |
|                             firstView.GetFrame().Iconize(False)
 | |
|                     return None
 | |
| 
 | |
|         if temp:
 | |
|             newDoc = temp.CreateDocument(path, flags)
 | |
|             if newDoc:
 | |
|                 newDoc.SetDocumentName(temp.GetDocumentName())
 | |
|                 newDoc.SetDocumentTemplate(temp)
 | |
|                 if not newDoc.OnOpenDocument(path):
 | |
|                     newDoc.DeleteAllViews()  # Implicitly deleted by DeleteAllViews
 | |
|                     frame = newDoc.GetFirstView().GetFrame()
 | |
|                     if frame:
 | |
|                         frame.Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it.
 | |
|                     return None
 | |
|                 self.AddFileToHistory(path)
 | |
|             return newDoc
 | |
| 
 | |
|         return None
 | |
| 
 | |
| 
 | |
|     def CreateView(self, doc, flags=0):
 | |
|         """
 | |
|         Creates a new view for the given document. If more than one view is
 | |
|         allowed for the document (by virtue of multiple templates mentioning
 | |
|         the same document type), a choice of view is presented to the user.
 | |
|         """
 | |
|         templates = []
 | |
|         for temp in self._templates:
 | |
|             if temp.IsVisible():
 | |
|                 if temp.GetDocumentName() == doc.GetDocumentName():
 | |
|                     templates.append(temp)
 | |
|         if len(templates) == 0:
 | |
|             return None
 | |
| 
 | |
|         if len(templates) == 1:
 | |
|             temp = templates[0]
 | |
|             view = temp.CreateView(doc, flags)
 | |
|             if view:
 | |
|                 view.SetViewName(temp.GetViewName())
 | |
|             return view
 | |
| 
 | |
|         temp = SelectViewType(templates)
 | |
|         if temp:
 | |
|             view = temp.CreateView(doc, flags)
 | |
|             if view:
 | |
|                 view.SetViewName(temp.GetViewName())
 | |
|             return view
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
| 
 | |
|     def DeleteTemplate(self, template, flags):
 | |
|         """
 | |
|         Placeholder, not yet implemented in wxWindows.
 | |
|         """
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def FlushDoc(self, doc):
 | |
|         """
 | |
|         Placeholder, not yet implemented in wxWindows.
 | |
|         """
 | |
|         return False
 | |
| 
 | |
| 
 | |
|     def MatchTemplate(self, path):
 | |
|         """
 | |
|         Placeholder, not yet implemented in wxWindows.
 | |
|         """
 | |
|         return None
 | |
| 
 | |
| 
 | |
|     def GetCurrentDocument(self):
 | |
|         """
 | |
|         Returns the document associated with the currently active view (if any).
 | |
|         """
 | |
|         view = self.GetCurrentView()
 | |
|         if view:
 | |
|             return view.GetDocument()
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
| 
 | |
|     def MakeDefaultName(self):
 | |
|         """
 | |
|         Returns a suitable default name. This is implemented by appending an
 | |
|         integer counter to the string "Untitled" and incrementing the counter.
 | |
|         """
 | |
|         name = _("Untitled %d") % self._defaultDocumentNameCounter
 | |
|         self._defaultDocumentNameCounter = self._defaultDocumentNameCounter + 1
 | |
|         return name
 | |
| 
 | |
| 
 | |
|     def MakeFrameTitle(self):
 | |
|         """
 | |
|         Returns a suitable title for a document frame. This is implemented by
 | |
|         appending the document name to the application name.
 | |
|         """
 | |
|         appName = wx.GetApp().GetAppName()
 | |
|         if not doc:
 | |
|             title = appName
 | |
|         else:
 | |
|             docName = doc.GetPrintableName()
 | |
|             title = docName + _(" - ") + appName
 | |
|         return title
 | |
| 
 | |
| 
 | |
|     def AddFileToHistory(self, fileName):
 | |
|         """
 | |
|         Adds a file to the file history list, if we have a pointer to an
 | |
|         appropriate file menu.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             self._fileHistory.AddFileToHistory(fileName)
 | |
| 
 | |
| 
 | |
|     def RemoveFileFromHistory(self, i):
 | |
|         """
 | |
|         Removes a file from the file history list, if we have a pointer to an
 | |
|         appropriate file menu.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             self._fileHistory.RemoveFileFromHistory(i)
 | |
| 
 | |
| 
 | |
|     def GetFileHistory(self):
 | |
|         """
 | |
|         Returns the file history.
 | |
|         """
 | |
|         return self._fileHistory
 | |
| 
 | |
| 
 | |
|     def GetHistoryFile(self, i):
 | |
|         """
 | |
|         Returns the file at index i from the file history.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             return self._fileHistory.GetHistoryFile(i)
 | |
|         else:
 | |
|             return None
 | |
| 
 | |
| 
 | |
|     def FileHistoryUseMenu(self, menu):
 | |
|         """
 | |
|         Use this menu for appending recently-visited document filenames, for
 | |
|         convenient access. Calling this function with a valid menu enables the
 | |
|         history list functionality.
 | |
| 
 | |
|         Note that you can add multiple menus using this function, to be
 | |
|         managed by the file history object.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             self._fileHistory.UseMenu(menu)
 | |
| 
 | |
| 
 | |
|     def FileHistoryRemoveMenu(self, menu):
 | |
|         """
 | |
|         Removes the given menu from the list of menus managed by the file
 | |
|         history object.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             self._fileHistory.RemoveMenu(menu)
 | |
| 
 | |
| 
 | |
|     def FileHistoryLoad(self, config):
 | |
|         """
 | |
|         Loads the file history from a config object.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             self._fileHistory.Load(config)
 | |
| 
 | |
| 
 | |
|     def FileHistorySave(self, config):
 | |
|         """
 | |
|         Saves the file history into a config object. This must be called
 | |
|         explicitly by the application.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             self._fileHistory.Save(config)
 | |
| 
 | |
| 
 | |
|     def FileHistoryAddFilesToMenu(self, menu=None):
 | |
|         """
 | |
|         Appends the files in the history list, to all menus managed by the
 | |
|         file history object.
 | |
| 
 | |
|         If menu is specified, appends the files in the history list to the
 | |
|         given menu only.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             if menu:
 | |
|                 self._fileHistory.AddFilesToThisMenu(menu)
 | |
|             else:
 | |
|                 self._fileHistory.AddFilesToMenu()
 | |
| 
 | |
| 
 | |
|     def GetHistoryFilesCount(self):
 | |
|         """
 | |
|         Returns the number of files currently stored in the file history.
 | |
|         """
 | |
|         if self._fileHistory:
 | |
|             return self._fileHistory.GetNoHistoryFiles()
 | |
|         else:
 | |
|             return 0
 | |
| 
 | |
| 
 | |
|     def FindTemplateForPath(self, path):
 | |
|         """
 | |
|         Given a path, try to find template that matches the extension. This is
 | |
|         only an approximate method of finding a template for creating a
 | |
|         document.
 | |
|         
 | |
|         Note this wxPython verson looks for and returns a default template if no specific template is found.
 | |
|         """
 | |
|         default = None
 | |
|         for temp in self._templates:
 | |
|             if temp.FileMatchesTemplate(path):
 | |
|                 return temp
 | |
|                 
 | |
|             if "*.*" in temp.GetFileFilter():
 | |
|                 default = temp
 | |
|         return default
 | |
| 
 | |
| 
 | |
|     def FindSuitableParent(self):
 | |
|         """
 | |
|         Returns a parent frame or dialog, either the frame with the current
 | |
|         focus or if there is no current focus the application's top frame.
 | |
|         """
 | |
|         parent = wx.GetApp().GetTopWindow()
 | |
|         focusWindow = wx.Window_FindFocus()
 | |
|         if focusWindow:
 | |
|             while focusWindow and not isinstance(focusWindow, wx.Dialog) and not isinstance(focusWindow, wx.Frame):
 | |
|                 focusWindow = focusWindow.GetParent()
 | |
|             if focusWindow:
 | |
|                 parent = focusWindow
 | |
|         return parent
 | |
| 
 | |
| 
 | |
|     def SelectDocumentPath(self, templates, flags, save):
 | |
|         """
 | |
|         Under Windows, pops up a file selector with a list of filters
 | |
|         corresponding to document templates. The wxDocTemplate corresponding
 | |
|         to the selected file's extension is returned.
 | |
| 
 | |
|         On other platforms, if there is more than one document template a
 | |
|         choice list is popped up, followed by a file selector.
 | |
| 
 | |
|         This function is used in wxDocManager.CreateDocument.
 | |
|         """
 | |
|         if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__":
 | |
|             descr = ''
 | |
|             for temp in templates:
 | |
|                 if temp.IsVisible():
 | |
|                     if len(descr) > 0:
 | |
|                         descr = descr + _('|')
 | |
|                     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
 | |
|             descr = _("All|*.*|%s") % descr  # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk
 | |
|         else:
 | |
|             descr = _("*.*")
 | |
| 
 | |
|         dlg = wx.FileDialog(self.FindSuitableParent(),
 | |
|                                _("Select a File"),
 | |
|                                wildcard=descr,
 | |
|                                style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR)
 | |
|         # dlg.CenterOnParent()  # wxBug: caused crash with wx.FileDialog
 | |
|         if dlg.ShowModal() == wx.ID_OK:
 | |
|             path = dlg.GetPath()
 | |
|         else:
 | |
|             path = None
 | |
|         dlg.Destroy()
 | |
|             
 | |
|         if path:  
 | |
|             theTemplate = self.FindTemplateForPath(path)
 | |
|             return (theTemplate, path)
 | |
|         
 | |
|         return (None, None)           
 | |
| 
 | |
| 
 | |
|     def OnOpenFileFailure(self):
 | |
|         """
 | |
|         Called when there is an error opening a file.
 | |
|         """
 | |
|         pass
 | |
| 
 | |
| 
 | |
|     def SelectDocumentType(self, temps, sort=False):
 | |
|         """
 | |
|         Returns a document template by asking the user (if there is more than
 | |
|         one template). This function is used in wxDocManager.CreateDocument.
 | |
| 
 | |
|         Parameters
 | |
| 
 | |
|         templates - list of templates from which to choose a desired template.
 | |
| 
 | |
|         sort - If more than one template is passed in in templates, then this
 | |
|         parameter indicates whether the list of templates that the user will
 | |
|         have to choose from is sorted or not when shown the choice box dialog.
 | |
|         Default is false.
 | |
|         """
 | |
|         templates = []
 | |
|         for temp in temps:
 | |
|             if temp.IsVisible():
 | |
|                 want = True
 | |
|                 for temp2 in templates:
 | |
|                     if temp.GetDocumentName() == temp2.GetDocumentName() and temp.GetViewName() == temp2.GetViewName():
 | |
|                         want = False
 | |
|                         break
 | |
|                 if want:
 | |
|                     templates.append(temp)
 | |
| 
 | |
|         if len(templates) == 0:
 | |
|             return None
 | |
|         elif len(templates) == 1:
 | |
|             return template[0]
 | |
| 
 | |
|         if sort:
 | |
|             def tempcmp(a, b):
 | |
|                 return cmp(a.GetDescription(), b.GetDescription())
 | |
|             templates.sort(tempcmp)
 | |
| 
 | |
|         strings = []
 | |
|         for temp in templates:
 | |
|             strings.append(temp.GetDescription())
 | |
| 
 | |
|         res = wx.GetSingleChoiceIndex(_("Select a document type:"),
 | |
|                                       _("Documents"),
 | |
|                                       strings,
 | |
|                                       self.FindSuitableParent())
 | |
|         if res == -1:
 | |
|             return None
 | |
|         return templates[res]
 | |
| 
 | |
| 
 | |
|     def SelectViewType(self, temps, sort=False):
 | |
|         """
 | |
|         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.
 | |
|         """
 | |
|         templates = []
 | |
|         strings = []
 | |
|         for temp in temps:
 | |
|             if temp.IsVisible() and temp.GetViewTypeName():
 | |
|                 if temp.GetViewName() not in strings:
 | |
|                     templates.append(temp)
 | |
|                     strings.append(temp.GetViewTypeName())
 | |
| 
 | |
|         if len(templates) == 0:
 | |
|             return None
 | |
|         elif len(templates) == 1:
 | |
|             return templates[0]
 | |
| 
 | |
|         if sort:
 | |
|             def tempcmp(a, b):
 | |
|                 return cmp(a.GetViewTypeName(), b.GetViewTypeName())
 | |
|             templates.sort(tempcmp)
 | |
| 
 | |
|         res = wx.GetSingleChoiceIndex(_("Select a document view:"),
 | |
|                                       _("Views"),
 | |
|                                       strings,
 | |
|                                       self.FindSuitableParent())
 | |
|         if res == -1:
 | |
|             return None
 | |
|         return templates[res]
 | |
| 
 | |
| 
 | |
|     def GetTemplates(self):
 | |
|         """
 | |
|         Returns the document manager's template list.  This method has been added to
 | |
|         wxPython and is not in wxWindows.
 | |
|         """
 | |
|         return self._templates
 | |
| 
 | |
| 
 | |
|     def AssociateTemplate(self, docTemplate):
 | |
|         """
 | |
|         Adds the template to the document manager's template list.
 | |
|         """
 | |
|         if docTemplate not in self._templates:
 | |
|             self._templates.append(docTemplate)
 | |
| 
 | |
| 
 | |
|     def DisassociateTemplate(self, docTemplate):
 | |
|         """
 | |
|         Removes the template from the list of templates.
 | |
|         """
 | |
|         self._templates.remove(docTemplate)
 | |
| 
 | |
| 
 | |
|     def AddDocument(self, document):
 | |
|         """
 | |
|         Adds the document to the list of documents.
 | |
|         """
 | |
|         if document not in self._docs:
 | |
|             self._docs.append(document)
 | |
| 
 | |
| 
 | |
|     def RemoveDocument(self, doc):
 | |
|         """
 | |
|         Removes the document from the list of documents.
 | |
|         """
 | |
|         if doc in self._docs:
 | |
|             self._docs.remove(doc)
 | |
| 
 | |
| 
 | |
|     def ActivateView(self, view, activate=True, deleting=False):
 | |
|         """
 | |
|         Sets the current view.
 | |
|         """
 | |
|         if activate:
 | |
|             self._currentView = view
 | |
|             self._lastActiveView = view
 | |
|         else:
 | |
|             self._currentView = None
 | |
| 
 | |
| 
 | |
|     def GetMaxDocsOpen(self):
 | |
|         """
 | |
|         Returns the number of documents that can be open simultaneously.
 | |
|         """
 | |
|         return self._maxDocsOpen
 | |
| 
 | |
| 
 | |
|     def SetMaxDocsOpen(self, maxDocsOpen):
 | |
|         """
 | |
|         Sets the maximum number of documents that can be open at a time. By
 | |
|         default, this is 10,000. If you set it to 1, existing documents will
 | |
|         be saved and deleted when the user tries to open or create a new one
 | |
|         (similar to the behaviour of Windows Write, for example). Allowing
 | |
|         multiple documents gives behaviour more akin to MS Word and other
 | |
|         Multiple Document Interface applications.
 | |
|         """
 | |
|         self._maxDocsOpen = maxDocsOpen
 | |
| 
 | |
| 
 | |
|     def GetDocuments(self):
 | |
|         """
 | |
|         Returns the list of documents.
 | |
|         """
 | |
|         return self._docs
 | |
| 
 | |
| 
 | |
| class DocParentFrame(wx.Frame):
 | |
|     """
 | |
|     The wxDocParentFrame class provides a default top-level frame for
 | |
|     applications using the document/view framework. This class can only be
 | |
|     used for SDI (not MDI) parent frames.
 | |
| 
 | |
|     It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplates
 | |
|     classes.
 | |
|     """
 | |
| 
 | |
|     def __init__(self, manager, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
 | |
|         """
 | |
|         Constructor.  Note that the event table must be rebuilt for the
 | |
|         frame since the EvtHandler is not virtual.
 | |
|         """
 | |
|         wx.Frame.__init__(self, frame, id, title, pos, size, style)
 | |
|         self._docManager = manager
 | |
| 
 | |
|         wx.EVT_CLOSE(self, self.OnCloseWindow)
 | |
| 
 | |
|         wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
 | |
|         wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
 | |
| 
 | |
|         wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
 | |
| 
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
 | |
| 
 | |
| 
 | |
|     def ProcessEvent(self, event):
 | |
|         """
 | |
|         Processes an event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         return self._docManager and self._docManager.ProcessEvent(event)
 | |
| 
 | |
| 
 | |
|     def ProcessUpdateUIEvent(self, event):
 | |
|         """
 | |
|         Processes a UI event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         return self._docManager and self._docManager.ProcessUpdateUIEvent(event)
 | |
| 
 | |
| 
 | |
|     def OnExit(self, event):
 | |
|         """
 | |
|         Called when File/Exit is chosen and closes the window.
 | |
|         """
 | |
|         self.Close()
 | |
| 
 | |
| 
 | |
|     def OnMRUFile(self, event):
 | |
|         """
 | |
|         Opens the appropriate file when it is selected from the file history
 | |
|         menu.
 | |
|         """
 | |
|         n = event.GetId() - wx.ID_FILE1
 | |
|         filename = self._docManager.GetHistoryFile(n)
 | |
|         if filename:
 | |
|             self._docManager.CreateDocument(filename, DOC_SILENT)
 | |
|         else:
 | |
|             self._docManager.RemoveFileFromHistory(n)
 | |
|             msgTitle = wx.GetApp().GetAppName()
 | |
|             if not msgTitle:
 | |
|                 msgTitle = _("File Error")
 | |
|             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),
 | |
|                           msgTitle,
 | |
|                           wx.OK | wx.ICON_EXCLAMATION,
 | |
|                           self)
 | |
| 
 | |
| 
 | |
|     def OnCloseWindow(self, event):
 | |
|         """
 | |
|         Deletes all views and documents. If no user input cancelled the
 | |
|         operation, the frame will be destroyed and the application will exit.
 | |
|         """
 | |
|         if self._docManager.Clear(not event.CanVeto()):
 | |
|             self.Destroy()
 | |
|         else:
 | |
|             event.Veto()
 | |
| 
 | |
| 
 | |
| class DocChildFrame(wx.Frame):
 | |
|     """
 | |
|     The wxDocChildFrame class provides a default frame for displaying
 | |
|     documents on separate windows. This class can only be used for SDI (not
 | |
|     MDI) child frames.
 | |
| 
 | |
|     The class is part of the document/view framework supported by wxWindows,
 | |
|     and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
 | |
|     classes.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
 | |
|         """
 | |
|         Constructor.  Note that the event table must be rebuilt for the
 | |
|         frame since the EvtHandler is not virtual.
 | |
|         """
 | |
|         wx.Frame.__init__(self, frame, id, title, pos, size, style, name)
 | |
|         wx.EVT_ACTIVATE(self, self.OnActivate)
 | |
|         wx.EVT_CLOSE(self, self.OnCloseWindow)
 | |
|         self._childDocument = doc
 | |
|         self._childView = view
 | |
|         if view:
 | |
|             view.SetFrame(self)
 | |
| 
 | |
|         wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
 | |
| 
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
 | |
| 
 | |
| 
 | |
|     def ProcessEvent(self, event):
 | |
|         """
 | |
|         Processes an event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         if self._childView:
 | |
|             self._childView.Activate(True)
 | |
|         if not self._childView or not self._childView.ProcessEvent(event):
 | |
|             # IsInstance not working, but who cares just send all the commands up since this isn't a real ProcessEvent like wxWindows
 | |
|             # if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
 | |
|             if not self.GetParent() or not self.GetParent().ProcessEvent(event):
 | |
|                 return False
 | |
|             else:
 | |
|                 return True
 | |
|         else:
 | |
|             return True
 | |
| 
 | |
| 
 | |
|     def ProcessUpdateUIEvent(self, event):
 | |
|         """
 | |
|         Processes a UI event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         if self.GetParent():
 | |
|             self.GetParent().ProcessUpdateUIEvent(event)
 | |
|         else:
 | |
|             return False
 | |
| 
 | |
| 
 | |
|     def OnActivate(self, event):
 | |
|         """
 | |
|         Activates the current view.
 | |
|         """
 | |
|         # wx.Frame.OnActivate(event)  This is in the wxWindows docview demo but there is no such method in wxPython, so do a Raise() instead
 | |
|         if self._childView:
 | |
|             self._childView.Activate(event.GetActive())
 | |
| 
 | |
| 
 | |
|     def OnCloseWindow(self, event):
 | |
|         """
 | |
|         Closes and deletes the current view and document.
 | |
|         """
 | |
|         if self._childView:
 | |
|             ans = False
 | |
|             if not event.CanVeto():
 | |
|                 ans = True
 | |
|             else:
 | |
|                 ans = self._childView.Close(deleteWindow = False)
 | |
| 
 | |
|             if ans:
 | |
|                 self._childView.Activate(False)
 | |
|                 self._childView.Destroy()
 | |
|                 self._childView = None
 | |
|                 if self._childDocument:
 | |
|                     self._childDocument.Destroy()  # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
 | |
|                     self._childDocument = None
 | |
|                 self.Destroy()
 | |
|             else:
 | |
|                 event.Veto()
 | |
|         else:
 | |
|             event.Veto()
 | |
| 
 | |
| 
 | |
|     def GetDocument(self):
 | |
|         """
 | |
|         Returns the document associated with this frame.
 | |
|         """
 | |
|         return self._childDocument
 | |
| 
 | |
| 
 | |
|     def SetDocument(self, document):
 | |
|         """
 | |
|         Sets the document for this frame.
 | |
|         """
 | |
|         self._childDocument = document
 | |
| 
 | |
| 
 | |
|     def GetView(self):
 | |
|         """
 | |
|         Returns the view associated with this frame.
 | |
|         """
 | |
|         return self._childView
 | |
| 
 | |
| 
 | |
|     def SetView(self, view):
 | |
|         """
 | |
|         Sets the view for this frame.
 | |
|         """
 | |
|         self._childView = view
 | |
| 
 | |
| 
 | |
| class DocMDIParentFrame(wx.MDIParentFrame):
 | |
|     """
 | |
|     The wxDocMDIParentFrame class provides a default top-level frame for
 | |
|     applications using the document/view framework. This class can only be
 | |
|     used for MDI parent frames.
 | |
| 
 | |
|     It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
 | |
|     classes.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, manager, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
 | |
|         """
 | |
|         Constructor.  Note that the event table must be rebuilt for the
 | |
|         frame since the EvtHandler is not virtual.
 | |
|         """
 | |
|         wx.MDIParentFrame.__init__(self, frame, id, title, pos, size, style, name)
 | |
|         self._docManager = manager
 | |
| 
 | |
|         wx.EVT_CLOSE(self, self.OnCloseWindow)
 | |
| 
 | |
|         wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
 | |
|         wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
 | |
| 
 | |
|         wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
 | |
|         wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
 | |
| 
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
 | |
|         wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
 | |
| 
 | |
| 
 | |
|     def ProcessEvent(self, event):
 | |
|         """
 | |
|         Processes an event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         return self._docManager and self._docManager.ProcessEvent(event)
 | |
| 
 | |
| 
 | |
|     def ProcessUpdateUIEvent(self, event):
 | |
|         """
 | |
|         Processes a UI event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         return self._docManager and self._docManager.ProcessUpdateUIEvent(event)
 | |
| 
 | |
| 
 | |
|     def OnExit(self, event):
 | |
|         """
 | |
|         Called when File/Exit is chosen and closes the window.
 | |
|         """
 | |
|         self.Close()
 | |
| 
 | |
| 
 | |
|     def OnMRUFile(self, event):
 | |
|         """
 | |
|         Opens the appropriate file when it is selected from the file history
 | |
|         menu.
 | |
|         """
 | |
|         n = event.GetId() - wx.ID_FILE1
 | |
|         filename = self._docManager.GetHistoryFile(n)
 | |
|         if filename:
 | |
|             self._docManager.CreateDocument(filename, DOC_SILENT)
 | |
|         else:
 | |
|             self._docManager.RemoveFileFromHistory(n)
 | |
|             msgTitle = wx.GetApp().GetAppName()
 | |
|             if not msgTitle:
 | |
|                 msgTitle = _("File Error")
 | |
|             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),
 | |
|                           msgTitle,
 | |
|                           wx.OK | wx.ICON_EXCLAMATION,
 | |
|                           self)
 | |
| 
 | |
| 
 | |
|     def OnCloseWindow(self, event):
 | |
|         """
 | |
|         Deletes all views and documents. If no user input cancelled the
 | |
|         operation, the frame will be destroyed and the application will exit.
 | |
|         """
 | |
|         if self._docManager.Clear(not event.CanVeto()):
 | |
|             self.Destroy()
 | |
|         else:
 | |
|             event.Veto()
 | |
| 
 | |
| 
 | |
| class DocMDIChildFrame(wx.MDIChildFrame):
 | |
|     """
 | |
|     The wxDocMDIChildFrame class provides a default frame for displaying
 | |
|     documents on separate windows. This class can only be used for MDI child
 | |
|     frames.
 | |
| 
 | |
|     The class is part of the document/view framework supported by wxWindows,
 | |
|     and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
 | |
|     classes.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
 | |
|         """
 | |
|         Constructor.  Note that the event table must be rebuilt for the
 | |
|         frame since the EvtHandler is not virtual.
 | |
|         """
 | |
|         wx.MDIChildFrame.__init__(self, frame, id, title, pos, size, style, name)
 | |
|         self._childDocument = doc
 | |
|         self._childView = view
 | |
|         if view:
 | |
|             view.SetFrame(self)
 | |
|         # self.Create(doc, view, frame, id, title, pos, size, style, name)
 | |
|         self._activeEvent = None
 | |
|         self._activated = 0
 | |
|         wx.EVT_ACTIVATE(self, self.OnActivate)
 | |
|         wx.EVT_CLOSE(self, self.OnCloseWindow)
 | |
| 
 | |
|         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
 | |
|             mdiChildren = filter(lambda x: isinstance(x, wx.MDIChildFrame), frame.GetChildren())
 | |
|             if len(mdiChildren) == 1:
 | |
|                 self.Activate()
 | |
| 
 | |
| 
 | |
| ##    # Couldn't get this to work, but seems to work fine with single stage construction
 | |
| ##    def Create(self, doc, view, frame, id, title, pos, size, style, name):
 | |
| ##        self._childDocument = doc
 | |
| ##        self._childView = view
 | |
| ##        if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
 | |
| ##            if view:
 | |
| ##                view.SetFrame(self)
 | |
| ##                return True
 | |
| ##        return False
 | |
| 
 | |
| 
 | |
| 
 | |
|     def Activate(self):  # Need this in case there are embedded sash windows and such, OnActivate is not getting called
 | |
|         """
 | |
|         Activates the current view.
 | |
|         """
 | |
|         if self._childView:
 | |
|             self._childView.Activate(True)
 | |
| 
 | |
| 
 | |
|     def ProcessEvent(event):
 | |
|         """
 | |
|         Processes an event, searching event tables and calling zero or more
 | |
|         suitable event handler function(s).  Note that the ProcessEvent
 | |
|         method is called from the wxPython docview framework directly since
 | |
|         wxPython does not have a virtual ProcessEvent function.
 | |
|         """
 | |
|         if self._activeEvent == event:
 | |
|             return False
 | |
| 
 | |
|         self._activeEvent = event  # Break recursion loops
 | |
| 
 | |
|         if self._childView:
 | |
|             self._childView.Activate(True)
 | |
| 
 | |
|         if not self._childView or not self._childView.ProcessEvent(event):
 | |
|             if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
 | |
|                 ret = False
 | |
|             else:
 | |
|                 ret = True
 | |
|         else:
 | |
|             ret = True
 | |
| 
 | |
|         self._activeEvent = None
 | |
|         return ret
 | |
| 
 | |
| 
 | |
|     def OnActivate(self, event):
 | |
|         """
 | |
|         Sets the currently active view to be the frame's view. You may need to
 | |
|         override (but still call) this function in order to set the keyboard
 | |
|         focus for your subwindow.
 | |
|         """
 | |
|         if self._activated != 0:
 | |
|             return True
 | |
|         self._activated += 1
 | |
|         wx.MDIChildFrame.Activate(self)
 | |
|         if event.GetActive() and self._childView:
 | |
|             self._childView.Activate(event.GetActive())
 | |
|         self._activated = 0
 | |
| 
 | |
| 
 | |
|     def OnCloseWindow(self, event):
 | |
|         """
 | |
|         Closes and deletes the current view and document.
 | |
|         """
 | |
|         if self._childView:
 | |
|             ans = False
 | |
|             if not event.CanVeto():
 | |
|                 ans = True
 | |
|             else:
 | |
|                 ans = self._childView.Close(deleteWindow = False)
 | |
| 
 | |
|             if ans:
 | |
|                 self._childView.Activate(False)
 | |
|                 self._childView.Destroy()
 | |
|                 self._childView = None
 | |
|                 if self._childDocument:  # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
 | |
|                     self._childDocument.DeleteContents()
 | |
|                     if self._childDocument.GetDocumentManager():
 | |
|                         self._childDocument.GetDocumentManager().RemoveDocument(self._childDocument)
 | |
|                 self._childDocument = None
 | |
|                 self.Destroy()
 | |
|             else:
 | |
|                 event.Veto()
 | |
|         else:
 | |
|             event.Veto()
 | |
| 
 | |
| 
 | |
|     def GetDocument(self):
 | |
|         """
 | |
|         Returns the document associated with this frame.
 | |
|         """
 | |
|         return self._childDocument
 | |
| 
 | |
| 
 | |
|     def SetDocument(self, document):
 | |
|         """
 | |
|         Sets the document for this frame.
 | |
|         """
 | |
|         self._childDocument = document
 | |
| 
 | |
| 
 | |
|     def GetView(self):
 | |
|         """
 | |
|         Returns the view associated with this frame.
 | |
|         """
 | |
|         return self._childView
 | |
| 
 | |
| 
 | |
|     def SetView(self, view):
 | |
|         """
 | |
|         Sets the view for this frame.
 | |
|         """
 | |
|         self._childView = view
 | |
| 
 | |
| 
 | |
|     def OnTitleIsModified(self):
 | |
|         """
 | |
|         Add/remove to the frame's title an indication that the document is dirty.
 | |
|         If the document is dirty, an '*' is appended to the title
 | |
|         This method has been added to wxPython and is not in wxWindows.
 | |
|         """
 | |
|         title = self.GetTitle()
 | |
|         if title:
 | |
|             if self.GetDocument().IsModified():
 | |
|                 if title.endswith("*"):
 | |
|                     return
 | |
|                 else:
 | |
|                     title = title + "*"
 | |
|                     self.SetTitle(title)
 | |
|             else:
 | |
|                 if title.endswith("*"):
 | |
|                     title = title[:-1]
 | |
|                     self.SetTitle(title)                
 | |
|                 else:
 | |
|                     return
 | |
| 
 | |
| 
 | |
| class DocPrintout(wx.Printout):
 | |
|     """
 | |
|     DocPrintout is a default Printout that prints the first page of a document
 | |
|     view.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, view, title="Printout"):
 | |
|         """
 | |
|         Constructor.
 | |
|         """
 | |
|         wx.Printout.__init__(self, title)
 | |
|         self._printoutView = view
 | |
| 
 | |
| 
 | |
|     def GetView(self):
 | |
|         """
 | |
|         Returns the DocPrintout's view.
 | |
|         """
 | |
|         return self._printoutView
 | |
| 
 | |
| 
 | |
|     def OnPrintPage(self, page):
 | |
|         """
 | |
|         Prints the first page of the view.
 | |
|         """
 | |
|         dc = self.GetDC()
 | |
|         ppiScreenX, ppiScreenY = self.GetPPIScreen()
 | |
|         ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
 | |
|         scale = ppiPrinterX/ppiScreenX
 | |
|         w, h = dc.GetSize()
 | |
|         pageWidth, pageHeight = self.GetPageSizePixels()
 | |
|         overallScale = scale * w / pageWidth
 | |
|         dc.SetUserScale(overallScale, overallScale)
 | |
|         if self._printoutView:
 | |
|             self._printoutView.OnDraw(dc)
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def HasPage(self, pageNum):
 | |
|         """
 | |
|         Indicates that the DocPrintout only has a single page.
 | |
|         """
 | |
|         return pageNum == 1
 | |
| 
 | |
| 
 | |
|     def GetPageInfo(self):
 | |
|         """
 | |
|         Indicates that the DocPrintout only has a single page.
 | |
|         """
 | |
|         minPage = 1
 | |
|         maxPage = 1
 | |
|         selPageFrom = 1
 | |
|         selPageTo = 1
 | |
|         return (minPage, maxPage, selPageFrom, selPageTo)
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------
 | |
| # Command Classes
 | |
| #----------------------------------------------------------------------
 | |
| 
 | |
| class Command(wx.Object):
 | |
|     """
 | |
|     wxCommand is a base class for modelling an application command, which is
 | |
|     an action usually performed by selecting a menu item, pressing a toolbar
 | |
|     button or any other means provided by the application to change the data
 | |
|     or view.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, canUndo = False, name = None):
 | |
|         """
 | |
|         Constructor. wxCommand is an abstract class, so you will need to
 | |
|         derive a new class and call this constructor from your own constructor.
 | |
| 
 | |
|         canUndo tells the command processor whether this command is undo-able.
 | |
|         You can achieve the same functionality by overriding the CanUndo member
 | |
|         function (if for example the criteria for undoability is context-
 | |
|         dependent).
 | |
| 
 | |
|         name must be supplied for the command processor to display the command
 | |
|         name in the application's edit menu.
 | |
|         """
 | |
|         self._canUndo = canUndo
 | |
|         self._name = name
 | |
| 
 | |
| 
 | |
|     def CanUndo(self):
 | |
|         """
 | |
|         Returns true if the command can be undone, false otherwise.
 | |
|         """
 | |
|         return self._canUndo
 | |
| 
 | |
| 
 | |
|     def GetName(self):
 | |
|         """
 | |
|         Returns the command name.
 | |
|         """
 | |
|         return self._name
 | |
| 
 | |
| 
 | |
|     def Do(self):
 | |
|         """
 | |
|         Override this member function to execute the appropriate action when
 | |
|         called. Return true to indicate that the action has taken place, false
 | |
|         otherwise. Returning false will indicate to the command processor that
 | |
|         the action is not undoable and should not be added to the command
 | |
|         history.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
|     def Undo(self):
 | |
|         """
 | |
|         Override this member function to un-execute a previous Do. Return true
 | |
|         to indicate that the action has taken place, false otherwise. Returning
 | |
|         false will indicate to the command processor that the action is not
 | |
|         redoable and no change should be made to the command history.
 | |
| 
 | |
|         How you implement this command is totally application dependent, but
 | |
|         typical strategies include:
 | |
| 
 | |
|         Perform an inverse operation on the last modified piece of data in the
 | |
|         document. When redone, a copy of data stored in command is pasted back
 | |
|         or some operation reapplied. This relies on the fact that you know the
 | |
|         ordering of Undos; the user can never Undo at an arbitrary position in
 | |
|         he command history.
 | |
| 
 | |
|         Restore the entire document state (perhaps using document
 | |
|         transactioning). Potentially very inefficient, but possibly easier to
 | |
|         code if the user interface and data are complex, and an 'inverse
 | |
|         execute' operation is hard to write.
 | |
|         """
 | |
|         return True
 | |
| 
 | |
| 
 | |
| class CommandProcessor(wx.Object):
 | |
|     """
 | |
|     wxCommandProcessor is a class that maintains a history of wxCommands, with
 | |
|     undo/redo functionality built-in. Derive a new class from this if you want
 | |
|     different behaviour.
 | |
|     """
 | |
| 
 | |
| 
 | |
|     def __init__(self, maxCommands=-1):
 | |
|         """
 | |
|         Constructor.  maxCommands may be set to a positive integer to limit
 | |
|         the number of commands stored to it, otherwise (and by default) the
 | |
|         list of commands can grow arbitrarily.
 | |
|         """
 | |
|         self._maxCommands = maxCommands
 | |
|         self._editMenu = None
 | |
|         self._undoAccelerator = _("Ctrl+Z")
 | |
|         self._redoAccelerator = _("Ctrl+Y")
 | |
|         self.ClearCommands()
 | |
| 
 | |
| 
 | |
|     def _GetCurrentCommand(self):
 | |
|         if len(self._commands) == 0:
 | |
|             return None
 | |
|         else:
 | |
|             return self._commands[-1]
 | |
| 
 | |
| 
 | |
|     def _GetCurrentRedoCommand(self):
 | |
|         if len(self._redoCommands) == 0:
 | |
|             return None
 | |
|         else:
 | |
|             return self._redoCommands[-1]
 | |
| 
 | |
| 
 | |
|     def GetMaxCommands(self):
 | |
|         """
 | |
|         Returns the maximum number of commands that the command processor
 | |
|         stores.
 | |
| 
 | |
|         """
 | |
|         return self._maxCommands
 | |
| 
 | |
| 
 | |
|     def GetCommands(self):
 | |
|         """
 | |
|         Returns the list of commands.
 | |
|         """
 | |
|         return self._commands
 | |
| 
 | |
| 
 | |
|     def ClearCommands(self):
 | |
|         """
 | |
|         Deletes all the commands in the list and sets the current command
 | |
|         pointer to None.
 | |
|         """
 | |
|         self._commands = []
 | |
|         self._redoCommands = []
 | |
| 
 | |
| 
 | |
|     def GetEditMenu(self):
 | |
|         """
 | |
|         Returns the edit menu associated with the command processor.
 | |
|         """
 | |
|         return self._editMenu
 | |
| 
 | |
| 
 | |
|     def SetEditMenu(self, menu):
 | |
|         """
 | |
|         Tells the command processor to update the Undo and Redo items on this
 | |
|         menu as appropriate. Set this to NULL if the menu is about to be
 | |
|         destroyed and command operations may still be performed, or the
 | |
|         command processor may try to access an invalid pointer.
 | |
|         """
 | |
|         self._editMenu = menu
 | |
| 
 | |
| 
 | |
|     def GetUndoAccelerator(self):
 | |
|         """
 | |
|         Returns the string that will be appended to the Undo menu item.
 | |
|         """
 | |
|         return self._undoAccelerator
 | |
| 
 | |
| 
 | |
|     def SetUndoAccelerator(self, accel):
 | |
|         """
 | |
|         Sets the string that will be appended to the Redo menu item.
 | |
|         """
 | |
|         self._undoAccelerator = accel
 | |
| 
 | |
| 
 | |
|     def GetRedoAccelerator(self):
 | |
|         """
 | |
|         Returns the string that will be appended to the Redo menu item.
 | |
|         """
 | |
|         return self._redoAccelerator
 | |
| 
 | |
| 
 | |
|     def SetRedoAccelerator(self, accel):
 | |
|         """
 | |
|         Sets the string that will be appended to the Redo menu item.
 | |
|         """
 | |
|         self._redoAccelerator = accel
 | |
| 
 | |
| 
 | |
|     def SetEditMenu(self, menu):
 | |
|         """
 | |
|         Tells the command processor to update the Undo and Redo items on this
 | |
|         menu as appropriate. Set this to NULL if the menu is about to be
 | |
|         destroyed and command operations may still be performed, or the
 | |
|         command processor may try to access an invalid pointer.
 | |
|         """
 | |
|         self._editMenu = menu
 | |
| 
 | |
| 
 | |
|     def SetMenuStrings(self):
 | |
|         """
 | |
|         Sets the menu labels according to the currently set menu and the
 | |
|         current command state.
 | |
|         """
 | |
|         if self.GetEditMenu() != None:
 | |
|             undoCommand = self._GetCurrentCommand()
 | |
|             redoCommand = self._GetCurrentRedoCommand()
 | |
|             undoItem = self.GetEditMenu().FindItemById(wx.ID_UNDO)
 | |
|             redoItem = self.GetEditMenu().FindItemById(wx.ID_REDO)
 | |
|             if self.GetUndoAccelerator():
 | |
|                 undoAccel = '\t' + self.GetUndoAccelerator()
 | |
|             else:
 | |
|                 undoAccel = ''
 | |
|             if self.GetRedoAccelerator():
 | |
|                 redoAccel = '\t' + self.GetRedoAccelerator()
 | |
|             else:
 | |
|                 redoAccel = ''
 | |
|             if undoCommand and undoItem and undoCommand.CanUndo():
 | |
|                 undoItem.SetText(_("&Undo ") + undoCommand.GetName() + undoAccel)
 | |
|             #elif undoCommand and not undoCommand.CanUndo():
 | |
|             #    undoItem.SetText(_("Can't Undo") + undoAccel)
 | |
|             else:
 | |
|                 undoItem.SetText(_("&Undo" + undoAccel))
 | |
|             if redoCommand and redoItem:
 | |
|                 redoItem.SetText(_("&Redo ") + redoCommand.GetName() + redoAccel)
 | |
|             else:
 | |
|                 redoItem.SetText(_("&Redo") + redoAccel)
 | |
| 
 | |
| 
 | |
|     def CanUndo(self):
 | |
|         """
 | |
|         Returns true if the currently-active command can be undone, false
 | |
|         otherwise.
 | |
|         """
 | |
|         if self._GetCurrentCommand() == None:
 | |
|             return False
 | |
|         return self._GetCurrentCommand().CanUndo()
 | |
| 
 | |
| 
 | |
|     def CanRedo(self):
 | |
|         """
 | |
|         Returns true if the currently-active command can be redone, false
 | |
|         otherwise.
 | |
|         """
 | |
|         return self._GetCurrentRedoCommand() != None
 | |
| 
 | |
| 
 | |
|     def Submit(self, command, storeIt=True):
 | |
|         """
 | |
|         Submits a new command to the command processor. The command processor
 | |
|         calls wxCommand::Do to execute the command; if it succeeds, the
 | |
|         command is stored in the history list, and the associated edit menu
 | |
|         (if any) updated appropriately. If it fails, the command is deleted
 | |
|         immediately. Once Submit has been called, the passed command should
 | |
|         not be deleted directly by the application.
 | |
| 
 | |
|         storeIt indicates whether the successful command should be stored in
 | |
|         the history list.
 | |
|         """
 | |
|         done = command.Do()
 | |
|         if done:
 | |
|             del self._redoCommands[:]
 | |
|             if storeIt:
 | |
|                 self._commands.append(command)
 | |
|         if self._maxCommands > -1:
 | |
|             if len(self._commands) > self._maxCommands:
 | |
|                 del self._commands[0]
 | |
|         return done
 | |
| 
 | |
| 
 | |
|     def Redo(self):
 | |
|         """
 | |
|         Redoes the command just undone.
 | |
|         """
 | |
|         cmd = self._GetCurrentRedoCommand()
 | |
|         if not cmd:
 | |
|             return False
 | |
|         done = cmd.Do()
 | |
|         if done:
 | |
|             self._commands.append(self._redoCommands.pop())
 | |
|         return done
 | |
| 
 | |
| 
 | |
|     def Undo(self):
 | |
|         """
 | |
|         Undoes the command just executed.
 | |
|         """
 | |
|         cmd = self._GetCurrentCommand()
 | |
|         if not cmd:
 | |
|             return False
 | |
|         done = cmd.Undo()
 | |
|         if done:
 | |
|             self._redoCommands.append(self._commands.pop())
 | |
|         return done
 | |
| 
 | |
| 
 |