Refactoring of Writer's usage of the Drawing layer
CURRENTLY UNDER CONSTRUCTION BY OD
The refactoring of the Writer's usage of the Drawing Layer is to create and maintain different Draw models for the Writer's model of Drawing objects and for the Writer's view(s) of Drawing objects. Thus The purpose of this refactoring is to
- improve the maintainability of the Writer's code regarding its usage of the Drawing layer,
- prepare the replacement of the Writer's implementation for graphic objects and embedded object by the corresponding implementation of the Drawing layer,
- get rid of special code in the Drawing layer, which only serves the Writer's needs for Drawing objects,
- solve certain issues regarding Drawing objects in repeated areas of a text document (Note: such repeated areas are page header, page footer and table headers), and
- "pre-prepare" the introduction of multiple different views on a certain text document.
- Develop general idea about the refactoring and its high-level implementation details – the big picture.
- Evaluate Drawing Layer functionality regarding the refactoring.
- Identify issues in Drawing Layer functionality, which needs to be solved in order to support the proposed refactoring.
- Identify certain implementation constraints which
- simplify the refactoring and/or the new code,
- allow the removable of former inappropriate code/solutions, and
- assure a good performance of the new code.
- The load/save performance shall not be affected by the refactoring. The editing performance is affected by the refactoring, but its effect shall be as low as possible.
- Note: It is needed to find a balanced way between the above three goals – e.g. not everything, which simplifies the new code would be good for the performance.
- Evaluate consequences of the refactoring to other functionalities regarding Drawing objects in Writer.
- ODF import/export
- Writer's implementation of the Drawing objects' UNO-API
- Identify known issues, which shall be solved by the proposed refactoring.
- Define testing/QA issues
- test plan(s) for end user tests
- API tests
- UNIT tests
- Get overview of the implementation details.
- Design and implementation of the new/changed architecture of the Writer's usage of the Drawing Layer
- New Classes/Interfaces
- Classes/Interfaces, which are reused, but are adjusted
- Classes/Interfaces, which are removed
- Relationships between the Classes/Interfaces, which implement the new Writer's usage of the Drawing Layer
The Big picture of the refactoring
The general idea of the refactoring is to use the Drawing layer in such a way that the model and the views of Drawing objects from the perspective of the Writer are separated. This new usage shall be transparent for the Drawing layer - no special code should be included into the Drawing layer to reflect this separation.
The solution to make this idea happen is to create different Draw models for different purposes. One Draw model for the intrinsic model of Drawing objects - called simply Draw model in the following. One Draw model for each Writer view for the view of Drawing objects - called Draw view model in the following.
Current state of the art
Currently the Writer holds one Draw model with one Draw page for the model and the view of Drawing objects. This causes certain special code to reflect Writer's specifics regarding Drawing objects:
- As invisible marked layers in the Draw page.
- Certain Drawing objects are not visible in any view, because they are located inside a hidden area (hidden section, hidden paragraph) or inside a page header/footer of a page style, which is not applied to any visible text document page. But, these Drawing objects belong to the model. Thus, they have to be on a Draw page in the Draw model -> invisible marked layers.
- Virtual Drawing objects
- Drawing objects in repeated areas (page header/footer and table header) have to be shown more than once inside a certain view. Because each Drawing object shall be only once in the Draw model, virtual Drawing objects are introduced - class <SdrVirtObj>. These are referencing the intrinsic Drawing object. Drawing objects of type control are not working with this mechanism. There are also some effects (e.g. text animation), which does not work with this mechanism.
- Note: The current usage of class <SdrVirtObj> by inheriting certain classes causes a lot of implementation effort. It is error-prone and complicated. It lacks certain features (controls not supported, no support for certain effects). It is also hard to maintain.
- Special call back mechanism from Drawing layer to Writer on Drawing object changes
- Due to former needs a special call back mechanism from the Drawing layer to the Writer is implemented. In this call back mechanism further information - namely the bounding rectangle of the Drawing object before the change has been applied - is passed to the Writer. This special call back mechanism can be removed nowadays. But unfortunately during the implementation of changes and enhancements to Drawing objects in Writer made in the past (mostly done by myself - firstname.lastname@example.org) this call back mechanism was not put into question.
- Special treatment of Drawing object's position and related properties in UNO-API
- Due different layout directions in text documents, which are not supported by the Drawing layer, the Drawing object's position and related properties (Transformation, StartPosition, EndPosition and PolyPolygonBezier) have to be treated special in the Writer's UNO-API implementation of Drawing. The position directly after the ODF import equals the model position of the Drawing object. If the layout direction is not horizontal, left-to-right the position of the Drawing object have to be adjusted for the layout. Because the Drawing layer only supports horizontal, left-to-right, the other layout direction have to simulated by the adjusted position. But at the UNO-API the model position have to be present and the actual position influences other properties - namely the ones mentioned above. That is the reason for the special treatment of the position and the related properties in Writer's implementation of the Drawing object's UNO-API. This special treatment costs performance on certain UNO-API calls, is error-prone and hard to maintain.
The current state of the art (especially the virtual Drawing objects) also causes some problems with Drawing objects in the preparation work for multiple different views and for probably new views of a text document - cws swrefactor071015.
Solution/Refactoring in detail
The details of the refactoring are:
- The Writer model holds a Draw model. This Draw model represents the model of the Drawing objects, which are contained in a text document. Thus, this Draw model is used for load/save and the UNO-API. The Drawing objects in this Draw model will be called Drawing model objects in the following.
- The Writer model is more or less represented by the <SwDoc> instance.
- Each Writer layout holds its own Draw model for the visualization of the Drawing objects. Such a Draw model will be called Draw view model in the following. The Drawing objects of a Draw view model are clones of the corresponding Drawing model objects. These clones will be called Drawing view objects in the following. For each visualization a new clone is created. For the Drawing layer these clones are independent from each other - there will be no functionality restrictions as they currently exist with virtual Drawing objects.
- A Writer layout is more or less represented by the tree of <SwFrm> instances with a <SwRootFrm> instance as its root.
- Note: Currently, only one Writer layout exists and it is shared between the existing Writer views (reason for the current restrictions between the existing views of a text document). Thus, after the refactoring there will be only one Draw view model. But, this solution will allow to continue the preparation work for multiple different views of a text document without having problems with Drawing objects (the goal of this preparation work is to give each Writer view its own Writer layout).
- The Writer will take care of the relationship between the Drawing model objects and its corresponding Drawing view objects.
- The Writer layout algorithm will create the Drawing view objects from the Drawing model objects.
- A certain instance of the Writer layout for each Drawing model object will hold the relations to the corresponding Drawing view objects.
- A certain instance of the Writer model will listen to the Draw model for changes on Drawing model objects and will assure a propagation of the changes to existing Drawing view objects.
- A certain instance of the Writer layout will listen to the Draw view models for changes on Drawing view objects and will assure a propagation of the changes to the Drawing model object and the other existing Drawing view objects.
- No special handling for undo/redo actions seems to be necessary. A certain undo action is recorded for the Drawing object, at which the action has taken place. On undo/redo the reverse action is applied to this Drawing object and via the above listening mechanism the other Drawing objects are notified.
Drawing layer functionality and issues
For the refactoring the following functions are needed:
- Clone Drawing objects
- Needed when a Drawing view object is created from the Drawing model object.
- Assignment of Drawing objects to each other
- Needed to propagate the changes on one Drawing object to the other related ones.
- Listening to Drawing object's changes
- Being notified, when changes are applied to a certain Drawing object in order to coordinate the propagation to the other related ones.
All functions are available at the Drawing layer. No serious issues regarding these functions are currently known.
- Treat every Drawing object type the same
- simplify code
- Try to avoid the introduction of code into the Drawing layer to support new Writer's usage of the Drawing layer
- special code in Drawing layer for Writer is one of the reasons for this refactoring
- Get rid of class <SdrVirtObj> - instead use "real" Drawing objects
- simplify code
- special Drawing object type of Drawing layer for Writer, not needed any more
- Get rid of class <SdrObjUserCall> - instead use implemented listener-concept
- simplify code
- special notification mechanism of Drawing layer for Writer, not needed any more
- Treatment of change of the Drawing object's position
- A change of the positioning attributes at the Drawing model object is not directly propagated to the existing Drawing view objects. Instead the Writer's layout process is triggered to adapt the Drawing view object's position accordingly.
- A change of the position at a Drawing view object is also not directly propagated to the Drawing model object and the other existing Drawing view objects. Instead the position change is converted to a change of the positioning attributes at the Drawing model object and afterwards the Writer's layout process is triggered to adapt the Drawing view object's position accordingly.
- Assure that on change of other attributes the Drawing model object's position and the Drawing view objects' positions are preserved.
- Get rid of the special treatment of the Drawing model object's position and related properties (Transformation, StartPosition, EndPosition and PolyPolygonBezier) at Writer's UNO-API implementation.
- No longer needed, because model and view data for Drawing objects are separated by this refactoring. Thus, the Draw model object can hold the model position, while the Draw view objects hold the layout position.
- Evaluate, if special treatment of control objects regarding cloning is needed
- Special treatment of Draw embedded objects regarding cloning
- clone of embedded object for visualization should be a graphic object with the replacement graphic of the embedded object as its content.
- this approach is in use for the full drag support of embedded objects, because it reveals that cloning embedded objects is too expensive.
- causes special treatment of graphic objects as visualization objects for embedded objects
- propagation of changes
- context menu
- tool bars
- clipboard handling
- Important note - 8. not considered now, but...
Currently, Draw embedded objects are not possible in Writer, because Writer uses its own implementation. But, 8. has to be considered, when the Writer's implementation is replaced by Draw's implementation.
- 1. and 8. somehow contradicts each other. Thus, assure in the implementation that the special treatment of embedded objects is implemented via a wrapper in the Writer code or via a corresponding virtual method in the Draw code.
- Note: second solution (new virtual method) contradicts with 6. But, would support a similar Drawing layer usage from the other applications.
- 8. would probably cause a new class in the <SdrObject> class hierarchy in order to identify the graphic objects, which are visualizations of embedded objects.
- Note: this would contradict with 6. But, would support a similar Drawing layer usage from the other applications.
Affected Drawing object functionalities
Issues fixed by the refactoring
|email@example.com||support form controls in page header/footer||P3||OOo Later|
|firstname.lastname@example.org||Anchor control to header's paragraph, OpenOffice will crash||P2||OOo 3.x|
|email@example.com||Drawing object copied via CTRL+drag is not visible||P3||OOo 3.x|
|firstname.lastname@example.org||Pictures flicker on top of document when opening||P3||OOo 3.x|
|email@example.com||Invisible object after pasting during "edit group"||P3||OOo 3.x|
|firstname.lastname@example.org||animated text in drawing objects in page header/footer only in one page header/footer||P3||OOo Later|
|email@example.com||"edit group" for page header/footer anchored drawing object group only in one group possible||P3||OOo Later|