<@doc hierarchy="GMLDOM"> Base aspect for drawing multi-part shapes (c) SAP AG 2003-2006. All rights reserved. Aspect Polyshape for GmlDrawing; inherit Shape; ////////////////////////////////////////////////////////////////////////////////////// // BASE PROPERTIES <@doc type="@SHAPE_PARTS[]"> Gets the definition of the shape's frame parts Use this property to define the graphical parts that draw the shape's frame. The frame parts do not contribute to the shape's size during auto-size calculations. Therefore, frame parts can be defined using dynamic formulas that depend on the shape's size (frame parts defined in this way will be adjusted whenever the shape's size changes). static readonly property frameParts = null; <@doc type="@SHAPE_PARTS[]"> Gets the definition of the shape's body parts Use this property to define the graphical parts that draw the shape's contents. The bounding box of the body parts defines the shape's size during auto-size calculations. Therefore, body parts cannot be defined using dynamic formulas that depend on the shape's size (since this would result in cyclic dependencies). static readonly property bodyParts = null; <@struct name="SHAPE_PARTS"> An array of SVG shape parts definitions

The SHAPE_PARTS structure is an array of objects, each representing a single shape part. The shape part's ~type attribute defines the type of SVG element that will be created. All the basic SVG element types can be used, including ~rect, ~circle, ~ellipse, ~line, ~polyline, ~polygon, ~path, ~text, and ~image. The remaining attributes are visual attributes specific to the shape part's type. See the SVG 1.1 Specification (www.w3.org/TR/2003/REC-SVG11-20030114) for more details.

All shape part attributes (except for type) can be expressed using dynamic formulas. A dynamic formula is string containing a valid JavaScript expression that involves one or more GML property references. A GML aspect property reference is written by adding the \@ prefix (e.g., \@fontSize). A GML object property reference is written by adding both the \@ prefix and ! suffix (e.g., \@name!). The ! suffix can be omitted from an object property reference, provided there is no aspect property with the same name.

NOTE: Dynamic formulas that depend on shape size cannot be used for the body parts of auto-sized shapes. Otherwise, cyclic dependencies will be created, resulting in inconsistent shape resize behavior.

////////////////////////////////////////////////////////////////////////////////////// // ASPECT PROPERTIES <@doc type="SVGNode[]" scope="private">Gets the collection of svg nodes of all shape parts virtual property partNodes = null; <@doc type="Object" scope="private">Gets the collection of all dynamic shape formulas virtual property formulas = null; ////////////////////////////////////////////////////////////////////////////////////// // PAINTING METHODS <@doc scope="private"> Paints the shape override virtual method paint() this.supercall(); // paint shape parts var data = this.parseParts(this.Class, base.Class); this.formulas = data.formulas; this.partNodes = new Array(data.shapeParts.length); for (var i=0, len=data.shapeParts.length; i Repaints the shape override virtual method repaint(prop) if (prop in this.formulas) { this.formulas[prop](this.partNodes, this, base); } if (prop == '@strokeColor') { this.frameNode.setAttribute('color', base.@strokeColor); } this.supercall(); end <@doc scope="private"> Repaints the shape after its size has changed override virtual method reshape() var fn=this.formulas['@size']; if (fn) fn(this.partNodes, this, base); end <@doc scope="private"> Creates the shape's wireframe override virtual method createWireframe() this.wireNode = SVG.createElement(this.diagram.wireframesLayer, 'g', {'class':'wireframe'}); var data = this.parseParts(this.Class, base.Class); for (var i=0, len=data.wireParts.length; i Adjusts the shape's wireframe to fit the shape bounding box override virtual method adjustWireframe(cx, cy, w, h) if (!this.wireNode) return; if (arguments.length < 4) w=this.w, h=this.h; if (arguments.length < 2) cx=this.cx, cy=this.cy; var tr = 'translate('+cx+','+cy+')'; if (this.rot) tr += ' rotate('+(this.rot*90)+')'; if (base.@flip) tr += ' matrix('+(base.@flip & #[SVG_FLIPX] ? -1 : 1)+' 0 0 '+(base.@flip & #[SVG_FLIPY] ? -1 : 1)+' 0 0)'; if (this.group != this.diagram) tr = 'translate('+this.ox+','+this.oy+') scale('+this.os+') '+tr; this.wireNode.setAttribute('transform', tr); if (arguments.length == 2) return; var data = this.parseParts(this.Class, base.Class); if (data.wireFormula) data.wireFormula(this.wireNode, w, h); end <@doc scope="private"> Creates the shape's sprite object override virtual method createSprite(parentNode, aspectClass, baseClass, w, h) var sprite = SVG.createElement(parentNode, 'g', {'class':'spriteframe', $stroke:baseClass.prototype.@strokeColor}); var data = aspectClass.prototype.parseParts(aspectClass, baseClass); for (var i=0, len=data.wireParts.length; i Starts a shape rename operation override virtual method startRename() for (var i=0, len=this.partNodes.length; i Parses the polyshape's parts definitions and prepares the required data structures and dynamic formulas virtual method parseParts(aspectClass, baseClass, frameParts) var baseName=baseClass.fullname, alldefs=aspectClass.allPolyshapes; if (alldefs && alldefs[baseName]) return alldefs[baseName]; if (!alldefs) alldefs = aspectClass.allPolyshapes = {}; // prepare data structures var shapeParts = []; var formulas = {}; var wireParts = []; var wireFormula = null; var PA = aspectClass.properties; // table of aspect class properties var PB = baseClass.properties; // table of base class properties // parse frame parts var fparts = frameParts || baseClass.prototype.@frameParts; for (var i=0, len=(fparts && fparts.length || 0); i