The Bonobo Compound Document Interfaces were originally modeled after the associated COM interfaces. It has become clear that they do not provide much utility in their current form. They have been largely unused to this point, so the Gnome 2 platform shift gives us an opportunity to revamp the interfaces and set them on a path that is more consistent with the rest of Bonobo.
This document is an attempt to identify the requirements for a compound document architecture and propose a solution which is more in line with the rest of the bonobo interfaces.
What are compound documents?
A compound document is obviously an aggregation of multiple sub-documents.
The sub-documents are implemented as standalone components. A set of
interfaces is necessary to allow the components to expose both their model
characteristics to container documents and their display characteristics to
container views. With these generalized interfaces, it is possible to
write simple container applications that can unleash the power of specialized
components while remaining ignorant of the components' purpose. The
container need only know how to perform the following operations on subcomponents.
Activation:
A container must be able to query for subcomponents which provide the container's preferred rendering model (canvas vs. widget). A Control implementation should be provided for ease of identifying embeddable subcomponents. The control should perform component activation and provide a reference to the selected subcomponent via an event. Linking of subcomponents via the Clipboard/Drag'nDrop is also necessary. Using a moniker based scheme is the clear choice for this capability. The design and implementation of this new capability is being performed in parallel to this compound document effort.
WYSIWYG Display/Print rendering:
A subcomponent must be capable of rendering itself in a WYSIWYG fashion using GNOME rendering technology. Components should expose factories to obtain a canvas or widget based "view" reference which can be embedded into a document view. Similarly, an interface to provide print rendering is necessary.Uniform zooming of subcomponents is accomplished through the size request/size allocation cycle on the plug/socket interfaces. Components request their size in points based on their full extent at 100% zoom. The container can then factor in manual resizing of the component and scale the allocation by the current zoom factor of the document. The component then scales itself to utilize the allocated space. If the component's unscaled dimensional requirements change due to editing, for example if a new line of text is added to a text control, the component view should emit a new size request (again in points and based on 100% zoom) so that the container can reallocate space and perform any additional layout tasks it deems necessary.
The above zooming mechanism is made more complicated because the current size request mechanism is integer/pixel based, and we need point based granularity using floating point values. We already have a mechanism to perform this transformation, GnomeCanvasWidget. The canvas also incorporates an easy to use zooming mechanism.
Another consideration is whether user resizing of a subcomponent should scale the component view, or crop it. Word, for example, uses a cropping paradigm, where the zoom of the component is not impacted, and only the visible extent of the document changes as the user resizes the component. While it is somewhat counterintuitive to show only a portion of a subcomponent, we must recognize that some users may be used to this sort of behavior and consider providing an alternative mechanism to perform this operation.
Perhaps subcomponents could expose a standard property to identify if they support cropping. A zoom_factor property would also be necessary so that when the container sets a new size allocation, the component could render its visible extent at a given zoom factor for the specified size allocation.
The subcomponent must support at least a subset of its editing capabilities via "in-place" activation of its view controls. The subcomponent should merge UI elements into the container's UI to provide an embedded editing capability. It is not necessary to provide all of the editing functionality that the subcomponent's native application provides, however.
Where possible, a subcomponent should support both canvas and widget based view controls. Until such time as the widget infrastructure becomes more canvas-like, it is anticipated that canvas based subcomponents will be more useful. It is hard to imagine an acceptable document layout implementation using tables and boxes. The canvas is currently better suited to the fine positioning and sizing requirements of a document application.
Persistence:
A subcomponent must be able to save and restore its state via a predictable interface. A compound document container must be able to serialize the state information for all of its subcomponents. The subcomponent must also have a mechanism to notify the container when the component has changed since its state was saved last.
The Original Compound Document interfaces:
The following interfaces represent the compound document architecture as of bonobo-1.0. They are primarily unused as of GNOME 1.4 and have very little utility. Clearly, wholesale restructuring is required.
Proposed Compound Document Interfaces:
The two useful methods from Embeddable will be split out into their own interfaces. Since the View Interface was so thin, the comparable interface will instead return a control and the ControlFrame implementation can be easily used to provide a proper Socket subclass.
interface ControlFactory {
Control createControl (in
ControlFrame frame,
in UIContainer uic);
};
interface CanvasComponentFactory {
Canvas::Component createCanvasComponent
(in boolean aa,
in Canvas::ComponentProxy proxy);
};
Dirty status is obtainable via the persist interfaces, but is currently duplicated in all the Persist subclasses. This method will be moved to Bonobo::Persist to eliminate duplication. Parallel discussions are occuring regarding Cut/Paste Drag/Drop related enhancements to the persist interfaces. These enhancements will provide even more utility to the container for managing subcomponents, and will form the basis for linking in the compound document environment. Persist and its subclasses are the workhorses for the model side of compound documents.
Any component wishing to be considered compound document ready would
need to expose at a minimum, one of the above "view" interface factories,
and either PersistStream or PersistStorage for save/load. Additionally,
The existing Print interface should be exposed to provide a print rendering
capability. The above interfaces should be sufficient for containers
to layout and render subcomponents and manage their persistence.