wxDocview Overview

The docview module is at the heart of the wxDocview package which is the foundation for the wxArt2D library. But the wxDocview package can also be used by other applications which require an advanced document view system.

Basics

About documents, views, document / view frameworks and applications.

Example

What is a Document? What is a View?

Think of a HTML document which consists of several HTML tags (the data). A view on this HTML document might be a view which interprets the HTML tags and displays a formatted page, while another view might show the pure HTML tags. In this case you have two views on the same document. Yet another view may collect all tags used in the HTML documents, and display statistics on this. This last case uses a view on multiple documents.

What does a Document/ View Framework do?

A document/ view framework follows the idea that a typical application consists of "documents" and "views on documents". A document in this term holds data and provides for interface independent operations on its data. Views visualize and change the data of the documents. Other objects in a document/ view framework are I/O handlers, which load and save the document's data to a file or stream.

A document/ view framework assists the programmer to follow this program paradigm and offers an API to work efficiently with this approach. The overall central command processor maintains the open documents in a list, and is used to create new views on those documents. It uses document templates for creating new documents, and view templates for creating new views for a document. How new views are hooked into the application's windows and frames, is under control of a view connector. Each document can have an internal command processor, which will then be used to make modification on the document undoable.

wxDocview vs. WxWidgets

wxDocview introduces a new document/ view framework for wxWidgets which uses another approach than the standard wxWidgets document/ view framework. Read wxDocview vs. WxWidgets to understand why this framework was designed and why it may better fit your needs than the framework currently used by wxWidgets.

If you are familiar with the standard document/ view framework of wxWidgets you may have noticed, that it also uses a DocTemplate but no ViewTemplate. Many files formats may use the same type of document type. But not each file format needs to have a specific view, since views do normally only depend on the type of document. Seperating templates into view and document templates has resolved this problem.

How a docview application looks like

The figure shows how a docview based application might look like. A command processor has a list of documents. The command processor takes care of closing and opening or creating new documents. Next to that it creates views for the documents. It is called a command processor because here is the entry point for command like operations on the current document or view. Views do display data stored in a documentonto a document view window, which is a subwindow of a document frame.

The application here has three documents, Document1 has three views. View1 is using Frame1 to display itself. View2 and View3 use Frame2 to display themselves. Document2 has two views, both use Frame3 for the display. At last Document3 has one view, displayed on the Parent Frame of the application.

Details

More about specific classes, the event concept and smart pointers.

Classes

In a docview controlled application, a2dDocumentCommandProcessor is essential, since it keeps track of opened documents, and the current view that has the focus or is active. Many operation or commands called via this class operate on the current document or view. Another important class is a2dViewConnector which connects a view (a2dView) with a window. This class is the only class that has the knowledge what interface (i.e. MDI) your application uses. If you want to switch to another interface you have just to modify your a2dViewConnector derived class or create an additional a2dViewConnector.

You derive your document classes as subclasses of the a2dDocument and your view classes derive from the a2dView.

The a2dDocumentTemplate defines what files/ file extensions belong to which type of a2dDocument. It can also define what a2dIOHandlerStrIn needs to be used for reading this document from a file, and what a2dIOHandlerStrOut needs to be used for writing the document to a file. So several templates can exist for the same type of document, but each for different in and output formats.

The a2dViewTemplate defines which types of views can be generated for a certain a2dDocument. In general all those templates are associated with the a2dDocumentCommandProcessor. It is possible to attach several a2dViewTemplates directly to a a2dViewConnector, in case one wants to limit the types of views for a certain connector type. Since templates are reference counted, one view template can be owned by several view connectors and the a2dDocumentCommandProcessor.

Both types of templates do have a pointer to a specific a2dViewConnector, and this connector is used to connect new documents and views into the application.

For a more detailed description about the individual classes, read wxDocview Classes.

Events

An important idea behind this docview module is, that the parts of the docview framework communicate through events with each other. Each part knows only the things which are absolutely necessary for it. The classes are therefore very loosely coupled. This makes it possible to use some of the classes in a standalone situation.

Examples

  1. A new document, a a2dDocument instance is created by a a2dDocumentTemplate instance, which informs the a2dViewConnector via an event that a new document was created. The a2dViewConnector derived class creates a a2dView by using a a2dViewTemplate and receives an event from the a2dViewTemplate if the view was created. The latter event is used by the a2dViewConnector to connect the new view with an application window (either this window already exists or the connector creates a new window, this depends on your needs).

  2. A view sents a viewclose event to its display window and document, when it wants to close. When a a2dView sents events to a a2dDocumentViewWindow, the last will either handle the event or sent it up to the parent window, which is often a a2dDocumentFrame. This way views inform a a2dDocumentFrame of closing, and the frame can react by destroying itself, or by disconnecting the view from itself, in order to reconnect to another view later on.

For more read wxDocview Events.

Smart Pointers

Smart pointers are used instead of pointers where possible, this means, that an object can be owned by several other objects (they have a "reference" to it) and will automatically be deleted if no other object has a reference to it. A typical use is for view on a document, when all views are released, and all other classes holding a smart pointer to a document are released, a document will be deleted. This approach does not need administrating a list of views inside a document, and makes the document unaware of how many views exist on it. Still it is aware of something that is used to display the contents of the document, and therefore its sends event around to makes those views and dialogs aware of changes to the document, which views can intercepts in order to update itself.

Reference Counting

In most classes pointer reference counting is used, with the a2dSmrtPtr that uses an Own and Release principle. The last owning objectX which owns an objectY will really delete the objectY when it releases that object. All the other Objects owning objectY will just lower the reference count.

This way a a2dView owns a document, but the same document is also owned by the a2dDocumentCommandProcessor. When the view is closed and released from its a2dDocumentViewWindow, it will also release its a2dDocument. But the document itself will only really be deleted, when all views on it are released, and the a2dDocumentCommandProcessor has released the document too. In the same manner template classes can be owned by the a2dDocumentCommandProcessor, but also by a a2dViewConnector at the same time.

Another useful trick is to own a a2dView one time extra at the beginning of an event processing, and release it again at the end of the event processing. When the event leads to releasing the view from its window (for instance the view's window is closed), this will only lead to real deletion of the view itself when the event processing is completely finished. This because the last release that will lead to the reference count reaching zero, is at the end of the event processing routine.

Using this Framework

To get an idea how to use this framework in real code take a look at the wxDocview Usage and at the samples provided with the wxDocview package's sources.

Different Types of Application, Multi Frame/ Single Frame

In an application with one parent wxFrame and for each view a child wxFrame, every new view will get its one a2dDocumentFrame. The a2dDocumentTemplate creates new documents, and a2dViewTemplate the new views. After creations of a a2dDocument and a a2dView, events are sent to their a2dViewConnector.

In a multi frame application the specialized connector's reaction to a newly created document will be to tell the view template to also generate the first view for the document. After creation of the view, the connector is informed by an event, and will react by creating a new a2dDocumentFrame and/or a child window wxDocView(Scrolled)Window. The last window is set as the display window for the new a2dView, this window will be used by the view to display itself. It is also possible to directly use the a2dDocumentFrame as the display window for the view.

In an MDI like application the type of frame is a a2dDocumentMDIParentFrame containing a2dDocumentMDIChildFrame instances. But for the rest connecting views is equal to the SDI situation.

In a single frame application with only a fixed number of views, which are always shown, a derived viewconnector will not use view templates. Instead it uses the views that were created only once. After creating or opening a new document, an existing view is connected to the document. If the view is already connected to a document, this document will first be detached/ released. One may decide to still create new views, but only connect some views to the windows in the application. The view which are not displayed, will have their display window set to NULL.

In a tabbed/ notebook like situation, one may decide to use existing views from an existing tab. Or create new views and for each new view create an extra tab.

How are views closed?

There are two routes involved in a multiple frame application. If you want to exit the application all top windows/ frames need to be destroyed. But when you only want to close one frame, the view displayed in there will be detached from its document and deleted. Several situations are possible. In Closing Frames and Applications it will go into detail.

DocviewOverview (last edited 2011-03-06 09:55:46 by MichaelStratmann)