Copyright and License information Home

__ A B C D E F G H I L M P R S T U V W

### wxStyledTextCtrl - Multiple Views

- GetDocPointer
- SetDocPointer
- CreateDocument
- AddRefDocument
- ReleaseDocument
- Example
- Another Viewpoint

Summary:

An interesting STC feature is the ability to have multiple views of the same Document. This can be used to provide split views of a document within one wxFrame (using a splitter window and two STC instances) or within multiple wxFrames. Changes to the Document in one window are reflected in other windows displaying the same Document.

Backgrounder:

The two most fundamental parts of the STC architecture are the Document and Editor classes. An Editor displays the contents of an instance of a Document class. Internally, a Document instance maintains a reference count and a list of Editor windows in which the Document appears.

Each STC instance displays a single Document instance. Creation of a STC instance causes a blank Document instance to be created with a reference count (see AddRefDocument) of 1. A C++ pointer to the Document instance is held in an STC internal variable called pdoc. When a different document instance is selected into the STC by using SetDocPointer, the reference count of the Document instance that's active prior to the call to SetDocPointer is decremented; when it becomes zero then the Document instance is deleted. This previous document also deletes the editor window from its list of Editor windows.

You can increment the reference count by using AddRefDocument and decrement it by using ReleaseDocument; which will also delete the Document instance when the reference count becomes zero.

You can create more Document instances by using CreateDocument, but only one at a time is displayed. You select the instance to display using SetDocPointer.

GetDocPointer()

Returns a pointer to the active document held by the STC. It's the document that's currently being displayed by the window. This 'pointer' is actually a string object of the form:

    XXXXXXXX_void_p

(on a 32-bit system, anyway) where XXXXXXXX is the actual 32-bit pointer (left-padded to 8 characters with underscores if needed). You should check the return value since it's possible to get None as a return value.

Also see AddRefDocument

top

SetDocPointer(pointer_string)

If you are holding a valid 'pointer' to a Document then you can poke it into the STC instance with the SetDocPointer method. Returns None.

The pointer_string parameter must be set to a valid 'pointer' that was obtained by calling GetDocPointer. As a special case you can pass None and the STC will create a new, empty Document and display it. The 'previous' document removes the current Editor window from its windows list. It also decrements its reference count by 1; if the reference count becomes zero then the document is deleted.

top

CreateDocument()

This method creates a new Document, but only returns it; the Document is not selected into the STC instance. The return value is a pointer string as shown in GetDocPointer. You should check the return value since it's possible to get None as a return value.

The reference count of the Document is 1.

Also see AddRefDocument for more information about reference counts.

top

AddRefDocument(pointer_string)

AddRefDocument adds 1 to the reference count for the Document whose pointer-string you pass in as a parameter. This reference count should not be confused with the Python reference count; this reference count is maintained in the Document data structure internal to the STC instance.

Why would you want to do this? You need to use extra care if your intention is to swap Documents in and out of a STC instance. When you use SetDocPointer the Document that is in view before you use SetDocPointer will have its reference count decremented.

If that reduces the reference count to zero then the Document is deleted. If you later pass in the pointer-string for a Document that's been deleted then you will get a run-time error. Generally, as soon as you obtain a pointer-string from the STC you should use this method to increment the reference count. In any case it needs to be done if you select a different document into the STC. Use ReleaseDocument when you are actually done with the Document; e.g., when the enclosing frame is closed or upon a similar event. This is a tricky aspect of STC programming, and if ignored will cause memory leaks and/or run-time errors.

If you want to use SetDocPointer() for multiple-Document support then you should use GetDocPointer() first and increment the reference count (with AddRefDocument()) before calling SetDocPointer() with the new pointer or the Document being displayed prior to the SetDocPointer() call will be deleted.

top

ReleaseDocument(pointer_string)

ReleaseDocument decrements the reference count of the Document instance described by pointer_string. If the count becomes zero then the Document instance is deleted.

top

Example:

Note that this is an untested example.

    from wxPython.stc import *

    class DocumentEditor(wxStyledTextCtrl):
        def __init__(self,parentWin, default_text='', documentName):
    		wxStyledTextCtrl.__init__(self,parentWin,wxNewId())
    		self.documentName = documentName        #name of currently-viewed document
    		documentViews = {}                      #name->Document-pointer-string mapping

    	def addDocument(self,textContent,name):
    		"""add a new document.
    			textContent is the initial text to go in it,
    			name is a name to use when referring to this
    			document
    		"""
    		currentDocument = self.GetDocPointer()  #get the document that's currently being shown
    		self.AddRefDocument(currentDocument)    #bump its reference count
    		documentViews[self.documentName] = currentDocument   #keep this pointer-string 'handle'
    		newDoc = self.CreateDocument()          #create a new document
    		self.SetDocPointer(newDoc)              #make it shown
    		self.SetText(textContent)               #set its initial text
    		self.documentName = name                #name of currently-viewed document

    	def swapDocuments(self,name):
    		"replaces the current document with a previously created one"
    		if not hasattr(self.documentViews,name): #be sure that the name is valid!
    			return
    		currentDocument = self.GetDocPointer()  #get the document that's currently being shown
    		self.AddRefDocument(currentDocument)    #bump its reference count
    		documentViews[self.documentName] = currentDocument   #keep this pointer-string 'handle'

    		newDoc = documentView[name]             #get the previous document pointer-string
    		self.SetDocPointer(newDoc)              #show the desired document
    		#Note: important to do ReleaseDocument AFTER SetDocPointer or the doc might get deleted prior to SetDocPointer!!!
    		self.ReleaseDocument(newDoc)            #dec the reference count

    		del documentViews[name]                 #don't keep around an old document p-s 'handle'
    		self.documentName = name                #name of currently-viewed document

top

Another viewpoint:

The following is some information from the Scintilla-Interest list (by Greg Smith), note that the terminology is that of Scintilla, not wxSTC, but you may find the information useful.

    Multiple views
    A Scintilla window and the document that it displays are separate entities.
    When you create a new window, you also create a new, empty document. Each
    document has a reference count that is initially set to 1. The document also
    has a list of the Scintilla windows that are linked to it so when any window
    changes the document, all other windows in which it appears are notified to
    cause them to update. The system is arranged in this way so that you can
    work with many documents in a single Scintilla window and so you can display
    a single document in multiple windows (for use with splitter windows).

    SCI_GETDOCPOINTER
    This returns a pointer to the document currently in use by the window. It
    has no other effect.

    SCI_SETDOCPOINTER(<unused>,document *pDoc)
    This message does the following:
    1. It removes the current window from the list held by the current document.
    2. It reduces the reference count of the current document by 1.
    3. If the reference count reaches 0, the document is deleted.
    4. pDoc is set as the new document for the window.
    5. If pDoc was 0, a new, empty document is created and attached to the
    window.

    SCI_CREATEDOCUMENT
    This message creates a new, empty document and returns a pointer to it. This
    document is not selected into the editor and starts with a reference count
    of 1. This means that you have ownership of it and must either reduce its
    reference count by 1 after using SCI_SETDOCPOINTER so that the Scintilla
    window owns it or you must make sure that you reduce the reference count by
    1 with SCI_RELEASEDOCUMENT before you close the application to avoid memory
    leaks.

    SCI_ADDREFDOCUMENT(<unused>, document *pDoc)
    This increases the reference count of a document by 1. If you want to
    replace the current document in the Scintilla window and take ownership of
    the current document, for example if you are editing many documents in one
    window, do the following:
    1. Use SCI_GETDOCPOINTER to get a pointer to the document, pDoc.
    2. Use SCI_ADDREFDOCUMENT(0, pDoc) to increment the reference count.
    3. Use SCI_SETDOCPOINTER(0, pNewDoc) to set a different document or
    SCI_SETDOCPOINTER(0, 0) to set a new, empty document.

    SCI_RELEASEDOCUMENT(<unused>, document *pDoc)
    This message reduces the reference count of the document identified by pDoc.
    pDoc must be the result of SCI_GETDOCPOINTER or SCI_CREATEDOCUMENT and must
    point at a document that still exists. If you call this on a document with a
    reference count of 1 that is still attached to a Scintilla window, bad
    things will happen. To keep the world spinning in its orbit you must balance
    each call to SCI_CREATEDOCUMENT or SCI_ADDREFDOCUMENT with a call to
    SCI_RELEASEDOCUMENT.

top