Difference between revisions of "Object tree"

From Inkscape Wiki
Jump to navigation Jump to search
Line 37: Line 37:
   * Calls parent class's build() method.
   * Calls parent class's build() method.
   * Reads in attributes by calling readAttr() for each attribute.
   * Reads in attributes by calling readAttr() for each attribute.
   * Creates objects for XML node children, inserts them into the object tree, and calls their SPObject::invoke_build method.
   * For each XML node child:
  ** Creates object for child XML node.
  ** Inserts object into the object tree by calling SPObject::attach().
  ** Builds object by calling SPObject::invoke_build().


=== readAttr (SPObject) ===
=== readAttr (SPObject) ===

Revision as of 11:22, 22 September 2016

Overview

The object tree implements an XML-to-display primitive mapping, and provides an object hierarchy that can be modified using the GUI. Changes in the XML tree are automatically propagated to the object tree via observers, but not the other way around—a function called updateRepr() must be explicitly called. Relevant nodes of the object tree contains fully cascaded CSS style information. The object tree also includes clones of objects that are referenced by the <use> element in the XML tree (this is needed as clones may have different styling due to inheritance).

SPObject (src/sp-object.h) is the abstract base class for each node in the object tree. Each derived class implements a certain SVG element type or is an abstract base class for a different node type.

Here is a typical class dependency structure:

 SPObject
   SPItem
     SPLPEItem
       SPShape
         SPRect


SPItem (src/sp-item.h) is the base class for all graphic (visible) SVG nodes. It adds handling for styling, clipping, masking, and transforms.

SPLPEItem (src/sp-lpe-item.h) handles keeping Live Path Effects updated.

SPShape (src/sp-shape.h) is a base class for all shapes. It takes care of markers.

The object tree is constructed from the XML tree by first manually constructing the SPRoot object (derived from SPObject) in SPDocument::createDoc() (src/document.h) and then calling the SPObject::invoke_build() member function. This function does some bookkeeping and then envokes the build() method (i.e. SPRoot::build() in the case of the root element). It also add the signaling that keeps objects in sync with the XML tree.

Functions

The most important functions from an architecture point of view defined by SPObject are:

envoke_build (SPObject)

 * Does bookkeeping.
 * Calls build() member function.
 * Adds signals to keep in sync with XML tree.

build (derived)

 * Calls parent class's build() method.
 * Reads in attributes by calling readAttr() for each attribute.
 * For each XML node child:
 ** Creates object for child XML node.
 ** Inserts object into the object tree by calling SPObject::attach().
 ** Builds object by calling SPObject::invoke_build().

readAttr (SPObject)

 * Looks up key for attribute (string).
 * Calls setKeyValue() which does nothing other than call set()

set (derived)

 * Reads in attribute:
 ** Processing as needed (e.g. converting % length to absolute length).
 ** Calls requestDisplayUpdate() if required.
 * Calls parent class set() to handle unknown attributes.

requestDisplayUpdate(unsigned int flags) (SPObject)

 * Merge update flags into uflags.
 * If SP_OBJECT_MODIFIED_FLAG or SP_OBJECT_CHILD_MODIFIED_FLAG not previously set:
 ** If object has parent, call parent's requestDisplayUpdate with SP_OBJECT_CHILD_MODIFIED_FLAG
 ** Else call document->requestModified() function which signals to GTK to redraw by calling sp_document_idle_handler() which calls SPDocument::_updateDocument().

updateDisplay(SPCtx *ctx, unsigned flags) (SPObject)

 * Called by SPDocument::_updateDocument() which is called by SPDocument::ensureUpToDate(), etc.
 * Called on child objects by SPGroup::update(), etc.
 * Merges uflags into flags.
 * Merges uflags into mflags.
 * Updates style if necessary.
 * Call update( ctx, flags).

update (derived)

 * Performs object related updates like resolving % lengths.
 * Calls child objects with updated transform matrix and with SP_OBJECT_PARENT_MODIFIED_FLAG added to flags if needed.
 * Calls parent class update() if needed.

requestModified(unsigned int flags)

 * Merge modified flags into mflags.
 * If SP_OBJECT_MODIFIED_FLAG or SP_OBJECT_CHILD_MODIFIED_FLAG not previously set:
 ** If object has parent, call parent's requestModified with SP_OBJECT_CHILD_MODIFIED_FLAG
 ** Else call document->requestModified() function which signals to GTK to redraw.

emitModified

modified

updateRepr(unsigned int flags) (SPObject)

 * Called to sync changes in SPObject to XML node.
 * Returns immediately if object is clone.
 * Checks validity of XML node.
 * Calls updateRepr(document, node, flags).

updateRepr(Inkscape::XML::Document, Inkscape::XML::Node, unsigned int flags)

 * Returns if object is clone.
 * Calls write()

write(Inkscape::XML::Document, Inkscape::XML::Node, unsigned int flags) (derived)

 * Updates XML node (or creates new node if necessary) with object data.
 * This will result in SPObject::repr_attr_changed() being called for any changed attributes (which then reads back in the attribute).

release (derived)

 * Opposite of SPObject::build. Removes listeners etc.
 * Called when object removed from tree.
 * Calls SPObject::detach() on children.

attach (SPObject)

 * Inserts child object into tree.

detach (SPObject)

 * Removes child object from tree.

Processes

This section lists program flows for typical processes.

Change Fill of <rect>

Note, not all function calls shown.

 ColorItem::buttonClicked(): Entrance
   sp_repr_css_set_property()
     Lots of calls to various functions to merge the new color into the rectangle's 'style' attribute.
   SPObject::repr_attr_changed: rect13
   SPRect::set: 2 fill:#ff0000: entrance: rect13 uflags: 0 mflags: 0 flags: 0
     SPShape::set, SPLPEItem::set, SPItem::set
     SPObject::set: 2 fill:#ff0000: entrance: rect13 uflags: 0 mflags: 0 flags: 0
       SPObject::requestDisplayUpdate: entrance: rect13 uflags: 0 mflags: 0 flags: 0
         SPObject::requestDisplayUpdate: entrance: svg2 uflags: 0 mflags: 0 flags: 0
           SPDocument::requestModified(): Entrance
             May call sp_document_idle_handler() and/or sp_document_rerouter_handler().
             This doesn't appear to trigger a display refresh. The refresh happens below.
           SPDocument::requestModified(): Exit
         SPObject::requestDisplayUpdate: exit: svg2 uflags: 2 mflags: 0 flags: 0
       SPObject::requestDisplayUpdate: exit: rect13 uflags: 9 mflags: 0 flags: 0
     SPObject::set: exit: rect13 uflags: 9 mflags: 0 flags: 0
   SPRect::set: exit: rect13 uflags: 9 mflags: 0 flags: 0
   Inkscape::DocumentUndo::maybeDone: Entrance
     SPDocument::ensureUpToDate(): Entrance
       SPDocument::_updateDocument(): Entrance
         SPObject::updateDisplay: entrance: svg2 uflags: 2 mflags: 0 flags: 0
           SPObject::updateDisplay: entrance: rect13 uflags: 9 mflags: 0 flags: 0
             SPRect::update: entrance: rect13 uflags: 0 mflags: 9 flags: 9
               SPShape::update, SPLPEItem::update, SPItem::update
             SPRect::update: exit: rect13 uflags: 0 mflags: 9 flags: 9
           SPObject::updateDisplay: exit: rect13 uflags: 0 mflags: 9 flags: 0
         SPObject::updateDisplay: exit: svg2 uflags: 0 mflags: 2 flags: 0
         SPDocument::_emitModified: Entrance
           SPObject::emitModified: entrance: svg2 uflags: 0 mflags: 2 flags: 0
             SPObject::emitModified: entrance: rect13 uflags: 0 mflags: 9 flags: 0
               SPShape::modified: entrance: rect13 uflags: 0 mflags: 0 flags: 0  Handles markers
               SPShape::modified: exit: rect13 uflags: 0 mflags: 0 flags: 0
             SPObject::emitModified: exit: rect13 uflags: 0 mflags: 0 flags: 0
           SPObject::emitModified: exit: svg2 uflags: 0 mflags: 0 flags: 0
         SPDocument::_emitModified: Exit
       SPDocument::_updateDocument(): Exit: root uflags: 0 mflags: 0
       SPDocument::_updateDocument(): Entrance  Called two times by SPDocument::ensureUpToDate()
       SPDocument::_updateDocument(): Exit: root uflags: 0 mflags: 0
     SPDocument::ensureUpToDate(): Exit
     Emit commit_signal which connects to SPDesktop::updateNow() which calls SPCanvas::updateNow().
     Render drawing on screen.
   Inkscape::DocumentUndo::maybeDone: Exit
 ColorItem::buttonClicked: Exit

Change Width of <rect> (using Toolbar GtkEntry)

 sp_rtb_value_changed(): Entrance
   SimpleNode::setAttribute: width: 200
   SPRect::setVisibleWidth()
   SPObject::updateRepr 1: entrance: rect13 uflags: 0 mflags: 0 flags: 0
     SPObject::updateRepr 2: entrance: rect13 uflags: 0 mflags: 0 flags: 0
       SPRect::write: entrance: rect13 uflags: 0 mflags: 0 flags: 2
         SimpleNode::setAttribute: width: 200 26456
         SPObject::repr_attr_changed: rect13
         SPRect::set: 7 200: entrance: rect13 uflags: 0 mflags: 0 flags: 0
           SPObject::requestDisplayUpdate: entrance: rect13 uflags: 0 mflags: 0 flags: 0
             SPObject::requestDisplayUpdate: entrance: svg2 uflags: 0 mflags: 0 flags: 0
               SPDocument::requestModified(): Entrance
               SPDocument::requestModified(): Exit
             SPObject::requestDisplayUpdate: exit: svg2 uflags: 2 mflags: 0 flags: 0
           SPObject::requestDisplayUpdate: exit: rect13 uflags: 1 mflags: 0 flags: 0
         SPRect::set: exit: rect13 uflags: 1 mflags: 0 flags: 0
         Many calls to SimpleNode::setAttribute()
         SPObject::write: entrance: rect13 uflags: 1 mflags: 0 flags: 0
           Many calls to SimpleNode::setAttribute()
         SPObject::write: exit: rect13 uflags: 1 mflags: 0 flags: 0
       SPRect::write: exit: rect13 uflags: 1 mflags: 0 flags: 2
     SPObject::updateRepr 2: exit: rect13 uflags: 1 mflags: 0 flags: 0
   SPObject::updateRepr 1: exit: rect13 uflags: 0 mflags: 0 flags: 0
   Inkscape::DocumentUndo::maybeDone: Entrance
     SPDocument::ensureUpToDate(): Entrance
       SPDocument::_updateDocument(): Entrance
         SPObject::updateDisplay: entrance: svg2 uflags: 2 mflags: 0 flags: 0
           SPObject::updateDisplay: entrance: rect13 uflags: 1 mflags: 0 flags: 0
             SPRect::update: entrance: rect13 uflags: 0 mflags: 1 flags: 1
               SPShape::update: entrance: rect13 uflags: 0 mflags: 1 flags: 0
               SPShape::update: exit: rect13 uflags: 0 mflags: 1 flags: 0
             SPRect::update: exit: rect13 uflags: 0 mflags: 1 flags: 1
           SPObject::updateDisplay: exit: rect13 uflags: 0 mflags: 1 flags: 0
         SPObject::updateDisplay: exit: svg2 uflags: 0 mflags: 2 flags: 0
         SPDocument::_emitModified: Entrance
           SPObject::emitModified: entrance: svg2 uflags: 0 mflags: 2 flags: 0
             SPObject::emitModified: entrance: rect13 uflags: 0 mflags: 1 flags: 0
               SPShape::modified: entrance: rect13 uflags: 0 mflags: 0 flags: 0
               SPShape::modified: exit: rect13 uflags: 0 mflags: 0 flags: 0
             SPObject::emitModified: exit: rect13 uflags: 0 mflags: 0 flags: 0
           SPObject::emitModified: exit: svg2 uflags: 0 mflags: 0 flags: 0
         SPDocument::_emitModified: Exit
       SPDocument::_updateDocument(): Exit: root uflags: 0 mflags: 0
       SPDocument::_updateDocument(): Entrance
       SPDocument::_updateDocument(): Exit: root uflags: 0 mflags: 0
     SPDocument::ensureUpToDate(): Exit
     Emit commit_signal which connects to SPDesktop::updateNow()
       which calls SPCanvas::updateNow().
     Render drawing on screen.
   Inkscape::DocumentUndo::maybeDone: Exit
 sp_rtb_value_changed(): Exit

Change Width of <rect> (dragging knot)

 KnotHolder::knot_moved_handler: Entrance
   RectKnotHolderEntityWH::knot_set: Entrance
     RectKnotHolderEntityWH::set_internal() Entrance
       SPObject::requestDisplayUpdate: entrance: rect13 uflags: 0 mflags: 0 flags: 0
         SPObject::requestDisplayUpdate: entrance: svg2 uflags: 0 mflags: 0 flags: 0
           SPDocument::requestModified(): Entrance
           SPDocument::requestModified(): Exit
         SPObject::requestDisplayUpdate: exit: svg2 uflags: 2 mflags: 0 flags: 0
       SPObject::requestDisplayUpdate: exit: rect13 uflags: 1 mflags: 0 flags: 0
     RectKnotHolderEntityWH::set_internal() Exit
   RectKnotHolderEntityWH::knot_set() Exit
 KnotHolder::knot_moved_handler: Exit
 sp_document_idle_handler: Entrance
   SPDocument::_updateDocument(): Entrance
     SPObject::updateDisplay: entrance: svg2 uflags: 2 mflags: 0 flags: 0
       SPObject::updateDisplay: entrance: rect13 uflags: 1 mflags: 0 flags: 0
         SPRect::update: entrance: rect13 uflags: 0 mflags: 1 flags: 1
           SPShape::update: entrance: rect13 uflags: 0 mflags: 1 flags: 0
           SPShape::update: exit: rect13 uflags: 0 mflags: 1 flags: 0
         SPRect::update: exit: rect13 uflags: 0 mflags: 1 flags: 1
       SPObject::updateDisplay: exit: rect13 uflags: 0 mflags: 1 flags: 0
     SPObject::updateDisplay: exit: svg2 uflags: 0 mflags: 2 flags: 0
     SPDocument::_emitModified: Entrance
       SPObject::emitModified: entrance: svg2 uflags: 0 mflags: 2 flags: 0
         SPObject::emitModified: entrance: rect13 uflags: 0 mflags: 1 flags: 0
           SPShape::modified: entrance: rect13 uflags: 0 mflags: 0 flags: 0
           SPShape::modified: exit: rect13 uflags: 0 mflags: 0 flags: 0
         SPObject::emitModified: exit: rect13 uflags: 0 mflags: 0 flags: 0
       SPObject::emitModified: exit: svg2 uflags: 0 mflags: 0 flags: 0
     SPDocument::_emitModified: Exit
   SPDocument::_updateDocument(): Exit: root uflags: 0 mflags: 0
 sp_document_idle_handler: Exit
 Render drawing
 Repeat above as handle is dragged
 KnotHolder::knot_ungrabbed_handler: Entrance
   SPObject::updateRepr 1: entrance: rect13 uflags: 1 mflags: 0 flags: 0
     SPObject::updateRepr 2: entrance: rect13 uflags: 1 mflags: 0 flags: 0
       SPRect::write: entrance: rect13 uflags: 1 mflags: 0 flags: 2
         SimpleNode::setAttribute: Entrance: width: 175 25898
         SimpleNode::setAttribute: Entrance: height: 175 25899
         SPObject::repr_attr_changed: rect13 *************************
         SPRect::set: 8 175: entrance: rect13 uflags: 1 mflags: 0 flags: 0
           SPObject::requestDisplayUpdate: entrance: rect13 uflags: 1 mflags: 0 flags: 0
           SPObject::requestDisplayUpdate: exit: rect13 uflags: 1 mflags: 0 flags: 0
         SPRect::set: exit: rect13 uflags: 1 mflags: 0 flags: 0
         SimpleNode::setAttribute: Entrance: height: 175 25900
         SimpleNode::setAttribute: Entrance: x: 25 25901
         More calls to SimpleNode::setAttribute()
         SPObject::write: entrance: rect13 uflags: 1 mflags: 0 flags: 0
          More calls to SimpleNode::setAttribute()
         SPObject::write: exit: rect13 uflags: 1 mflags: 0 flags: 0
       SPRect::write: exit: rect13 uflags: 1 mflags: 0 flags: 2
     SPObject::updateRepr 2: exit: rect13 uflags: 1 mflags: 0 flags: 0
   SPObject::updateRepr 1: exit: rect13 uflags: 1 mflags: 0 flags: 0
   Inkscape::DocumentUndo::maybeDone: Entrance
     SPDocument::ensureUpToDate(): Entrance
       SPDocument::_updateDocument(): Entrance
         SPObject::updateDisplay: entrance: svg2 uflags: 2 mflags: 0 flags: 0
           SPObject::updateDisplay: entrance: rect13 uflags: 1 mflags: 0 flags: 0
             SPRect::update: entrance: rect13 uflags: 0 mflags: 1 flags: 1
               SPShape::update: entrance: rect13 uflags: 0 mflags: 1 flags: 0
               SPShape::update: exit: rect13 uflags: 0 mflags: 1 flags: 0
             SPRect::update: exit: rect13 uflags: 0 mflags: 1 flags: 1
           SPObject::updateDisplay: exit: rect13 uflags: 0 mflags: 1 flags: 0
         SPObject::updateDisplay: exit: svg2 uflags: 0 mflags: 2 flags: 0
         SPDocument::_emitModified: Entrance
           SPObject::emitModified: entrance: svg2 uflags: 0 mflags: 2 flags: 0
             SPObject::emitModified: entrance: rect13 uflags: 0 mflags: 1 flags: 0
               SPShape::modified: entrance: rect13 uflags: 0 mflags: 0 flags: 0
               SPShape::modified: exit: rect13 uflags: 0 mflags: 0 flags: 0
             SPObject::emitModified: exit: rect13 uflags: 0 mflags: 0 flags: 0
           SPObject::emitModified: exit: svg2 uflags: 0 mflags: 0 flags: 0
         SPDocument::_emitModified: Exit
       SPDocument::_updateDocument(): Exit: root uflags: 0 mflags: 0
       SPDocument::_updateDocument(): Entrance
       SPDocument::_updateDocument(): Exit: root uflags: 0 mflags: 0
     SPDocument::ensureUpToDate(): Exit
     Emit commit_signal which connects to SPDesktop::updateNow()
       which calls SPCanvas::updateNow().
     Render drawing on screen.
   Inkscape::DocumentUndo::maybeDone: Exit
 KnotHolder::knot_ungrabbed_handler: Exit