Shapes are the primary diagram building blocks. Shapes are used to represent objects from the real world, concepts or abstractions. In NOV diagram shapes are designed to be similar to Microsoft Visio shapes. That is why any knowledge on the Microsoft Visio shape sheet architecture will be of help to understand them. Reversely knowing about NOV Shapes can help you learn Visio internals more quickly.
Usually a shape is created by using a shape factory and then it should be added to the Items collection of a drawing page. The following code snippet demonstrates how to create a rectangle shape and add it to the to the active page of a drawing:
Creating Shapes |
Copy Code
|
// Create a rectangle
NBasicShapesFactory factory = new NBasicShapeFactory();
NShape shape = factory.CreateShape(ENBasicShape.Rectangle);
// Position the rectangle and add it to the active page
shape.SetBounds(new NRectangle(50, 50, 100, 100));
drawing.ActivePage.Items.Add(shape);
|
The shape type is determined by the ShapeType property, which indicates whether the shape is 1D or 2D shape. The shape type influences the way in which NOV diagram threats the shape. Specifically when selected, NOV diagram will display a box tracker that allows the modification of the shape width, height, pin point and rotation. 1D shapes are visually edited by their begin and end points.
To be a fully functional 1D or 2D shape, the shape needs to be first initialized. This is done via the helper Init2DShape() and Init1DShape() methods, which initialize the shape transformation and Width and Height (in Visio also known as the shape XForm). The shape transformation is controlled by the following properties of the shape:
The local pin point is a point in the shape coordinate system which defines the point from the shape that is mapped to the shape location in parent coordinates – the pin point.
LocPinX, LocPinY – specify the X and Y location of the local pin point. The local pin point is in either shape “local” or “local relative” coordinates as indicated by the LocPinRelative property. The GetLocPinPoint and SetLocPinPoint methods help you get and set the local pin point in shape “local” coordinates (i.e. perform the relative to local scaling for you if needed).
LocPinRelative – indicates whether the local pin point is in shape “local” or “local relative coordinates”.
Typically the LocPinX and LocPinY are set to 0.5 and the LocPinRelative property is set to true. This is equivalent to binding the local pin point to the center of the shape Width/Height box.
The pin point is a point in shape parent coordinates, that defines the position of the shape. When the shape local pin point is projected with the shape transform, it is projected in the pin point.
That is why the modification of the pin point is associated with the shape translation. The Pin point is specified by the PinX and PinY properties. The GetPinPoint and SetPinPoint methods help you modify the pin point (both methods work in parent coordinates). If the shape belongs to a composite shape, the SetPinPoint method binds the PinX and PinY properties to a point relative to the owner composite shape Width and Height. In this way when the owner shape is resized, the shape will preserve its relative position.
The FlipX and FlipY properties define whether the shape local coordinates need to be X or Y flipped. The Angle property defines the rotation of the shape relative to the pin point.
The shape transformation is always orthogonal, meaning that any two perpendicular vectors from the shape local coordinates remain perpendicular when transformed to parent coordinates.
The shape transformation is also never a scaling transformation. This means that the distance between any two points in local coordinates will remain the same when these points are transformed to parent coordinates.
Now that you know about the properties that define the shape transformation lets discuss the actions taken by the Init2DShape() and Init1DShape() methods.
The Init2DShape() method performs the following actions:
-Sets the ShapeType to Shape2D.
-Sets the LocPinX and LocPinY properties to 0.5
-Sets the LocPinRelative to true.
The Init1DShape() takes a single argument – the type of 1D transform to initialize – there are three options – Vector, Box and BoxAbsolute. Depending on the argument the method performs the following actions:
-Sets the ShapeType to Shape1D.
-Sets the LocPinX and LocPinY properties to 0.5
-Sets the LocPinRelative to true.
Vector transform
- binds the shape Width to be distance between the Begin and End points.
- binds the shape Angle to be angle formed by the Begin and End line and the X axis.
- binds the PinX and PinY properties to the middle of the line formed by the Begin and End points.
The end result is that the shape behaves as a directed vector connecting the begin and end points. When the user moves the end-points the shape will stretch in width and rotate.
Box transform
- binds the shape Width to be the X distance between the Begin and End points.
- binds the shape Height to be the Y distance between the Begin and End points.
- binds the PinX and PinY properties to the middle of the line formed by the Begin and End points.
The end result is that the shape behaves as a box defined by its left-top and right-bottom corners. When the user moves the end-points the shape will stretch in width and height. The shape will not be rotated. The shape Width and Height can become negative values with this transform. This may have the effect of X or Y flipping.
Box Absolute transform
- binds the shape Width to be the absolute X distance between the Begin and End points.
- binds the shape Height to be the absolute Y distance between the Begin and End points.
- binds the PinX and PinY properties to the middle of the line formed by the Begin and End points.
The end result is that the shape behaves as a box defined by its left-top and right-bottom corners. When the user moves the end-points the shape will stretch in width and height. The shape will not be rotated. The shape Width and Height cannot become negative values with this transform so it will never look like flipped.
It is important to always initialize the shape when making a custom shape, because otherwise the shape transform properties will not be properly bound.
The shape Width and Height properties define the size of the shape in local coordinates. Because the shape transformation is not a scaling transform, the Width and Height can also be viewed as size of the shape in the parent coordinate system.
Typically the shape geometry, ports, controls and other shape elements are created in such a way that they depends on the shape Width and Height via expressions or by using “local relative” coordinates. This however does not change the fact that the Width and Height properties do not affect the shape transformation.
For 2D shapes the Width and Height of the shape can be visually modified when the shape is selected via the box handles. For 1D shapes the Width of the shape is always expressed as a function of the Begin and End points and cannot be visually modified. The Height of the 1D shape with Vector transform however is left as a constant value and you can instruct the shape to show a height handle that will allow the visual modification of the height by setting the EditHeightIn1D property true.
As discussed in the previous section, the shape transform of 1D shapes is bound to the begin and end points of the shape (collectively called end-points). The Begin and End points are points in the parent coordinate system and are controlled by the BeginX, BeginY and EndX, EndY properties of the shape.
The GetBeginPoint and SetBeginPoint methods help you modify the begin point (work in parent coordinates). Similarly the GetEndPoint and SetEndPoint methods help you modify the end point (work in parent coordinates). If the shape belongs to a group shape, the SetBeginPoint and SetEndPoint methods binds the end-point properties to a point relative to the owner group Width and Height. In this way when the owner shape is resized, the shape begin and end points will proportionally change.
Both the begin and end points can be glued to other shapes, ports and geometry aspects. The following table summarized the methods you can use the glue the begin and end points respectively:
Begin Point |
End Point |
Description |
void GlueBeginToGeometryIntersection(NShape shape)
|
void GlueEndToGeometryIntersection(NShape shape)
|
Glues the respective end-point to the intersection of the 1D shape with the specified shape geometry. |
void GlueBeginToGeometryContour(NShape shape, double factor)
|
void GlueEndToGeometryContour(NShape shape, double factor)
|
Glues the respective end-point to a point along the geometry contour, that corresponds to the specified factor. 0 is the begin of the geometry contour, 1 is the end of the contour. |
void GlueBeginToGeometryVertex(NGeometryCommand command, int vertexIndex)
|
void GlueEndToGeometryVertex(NGeometryCommand command, int vertexIndex)
|
Glues the respective end-point to a geometry vertex of the specified geometry command. |
void GlueBeginToPort(NPort fromPort)
|
void GlueEndToPort(NPort fromPort)
|
Glues the respective end-point to the specified port. |
void GlueBeginToNearestPort(NShape shape)
|
void GlueEndToNearestPort(NShape shape)
|
Glues the respective end-point to the nearest port of the specified shape. |
void GlueBeginToShapeBoxIntersection(NShape shape)
|
void GlueEndToShapeBoxIntersection(NShape shape)
|
Glues the respective end-point to the intersection of the 1D shape with the specified shape box. |
void GlueBeginToShapeBox(NShape shape, double widthFactor, double heightFactor)
|
void GlueEndToShapeBox(NShape shape, double widthFactor, double heightFactor)
|
Glues the respective end-point to a relative point inside the specified shape box. |
void GlueBeginToShapeLine(NShape shape, double factor)
|
void GlueEndToShapeLine(NShape shape, double factor)
|
Glues the respective end-point to a point along the line connecting the specified shape begin and end point points. 0 is the begin of the shape, 1 is the end of the shape. |
bool GlueBeginToShape(NShape shape)
|
bool GlueEndToShape(NShape shape)
|
Glues the respective end-point to the specified shape. The actual type of connection that is performed depends on the shape DefaultShapeGlue property, which accepts values from the ENDefaultShapeGlue enumeration:
None - By default the shape does not allow shape to shape connections.
Automatic - The Begin or End point of the connectors are glued automatically depending on the shape type, geometry and ports.
In case the shape is a 2D shape:
If the shape has ports, glues to the nearest port.
Otherwise glues to the shape box intersection.
In case the shape is a 1D shape:
If the shape has ports, glues to the nearest port.
If the shape geometry has closed figures, then glues to the shape line center.
Otherwise glues to the shape contour middle.
GlueToGeometryIntersection - The Begin or End point of the connectors are glued to the contour (outline) of the shape geometry.
GlueToBoxIntersection - The Begin or End point of the connectors are glued to the contour (outline) of the shape box.
GlueToNearestPort - The Begin or End point of the connectors are glued to the nearest port of the shape.
GlueToBoxCenter - The Begin or End point of the connectors are glued to the nearest port of the shape.
|
Each shape can have the following child elements:
- Geometry
The shape geometry is represented by the NGeometry class an instance of which can be obtained by the shape Geometry property. It is a collection geometry commands that define the graphics path displayed by the shape. In most cases you will expressions or “local relative” coordinates to define the geometry of a shape. See Geometry for more information.
- TextBlock
The shape text block is represented by the NTextBlock class an instance of which can be obtained by the shape TextBlock property. It represents text displayed by the shape. The shape Text property is a shortcut method for getting and settings the text displayed by the text block . See Text Block for more information.
- Ports
The ports of the shape are represented by instances of the NPort class that are contained inside the NPortCollection accessible from the Ports property. The ports define the connection points of the shape – e.g. the shape specific positions for connecting other shapes begin and end points. Typically only 2D shapes will have ports, but in some diagrams it is required to make ports for 1D shapes too.
- Controls
The shape control points (abbreviated simply as “controls”) are represented by the NControl class. The controls of a shape are points that the user can drag when the shape is selected. Typically the controls of a shape are made to control the geometry of the shape via expressions. See Controls for more information.
- Scratches
When authoring complex shapes with expressions it is often required to cache the result of certain formulas so that they can be further reused in other expressions. This is when scratches come handy. The scratches are represented the NScratch class and are contained inside the NScratchCollection accessible from the Scratches property. Each scratch has X and Y properties of type double and A,B,C and D properties of type variant (similarly to Visio). The scratches are solely used for the purpose of optimizing expressions – that is the shape does make use of them in any way.
- BeginPointGlue, EndPointGlue and MasterGlue
These child elements serve as calculators for values needed when you glue the “end-points” of the shape (BeginPointGlue and EndPointGlue) or when you make an outward shape glue (MasterGlue). For more information take a look at the Shape Glue topic.
- LayoutData
The layout data is represented by the NLayoutData element and contains properties that are used when the shape is arranged via the automatic layouts.
- Widget
You can place any widget inside a shape. The embedded widget is sized to the shape Width and Height, but it is often needed to resize the shape to the contained widget. You can do that with expressions.