Access Keys:
Skip to content (Access Key - 0)

Developer Guide

A step by step dive into the Kap Lab Diagrammer component

Introduction

This documentation present how to integrate diagramming functionality in your AS3 application:

  • Adding a SVG library in a flex application
  • Adding layout to a diagram
  • Binding data to a diagram
  • Sprites composition in a diagram

We use Flex for this tutorial, but because the Diagrammer is a pure AS3 component, it can also be integrated into Flash AS3 applications.

Keep in mind that the samples used in this documentation are neither meant to be useful nor in phase with software development quality standards. For the sake of simplicity and to keep focus on the original goal which is showing how to integrate the Diagrammer, we tried to reduce the amount of code artifact. So we put all the code we can into a single mxml file, and created as little class as possible, using generic data container such as ArrayCollections. In real world software, you should use a MVC framework, create specific class to hold your data, and so on.

You can download a complete solution with all the code from this documentation if you don't want to type.

Adding a SVG library in a flex application

In this chapter we will show how to write a very simple application and with a few lines of code add a diagramming functionality.

First we need to create the sprite library that will be used in the application.

Creating a SVG shape library

Overview

Diagrammer uses SVG to define sprites. Using SVG helps easily integrate complex shapes into Diagrammer. It also gives the opportunity to export a diagram in SVG for printing.

Diagrammer supports a subset of SVG 1.1. Most of the features needed for sprite definitions are supported :

  • Document structure (<svg>, <defs>, <g>).
  • Basic shapes (<rect>, <circle>, <ellipse>, <line>, <polyline>, <polygon>).
  • Full support of drawing paths with: line, elliptic arcs, cubic Bezier curves, quadratic Bezier curves commands.
  • SVG text features are partially implemented and match the text rendering capabilities of the flash player (<text>, <tspan>)
  • Full support of transformations: translate, scale, rotate, skewX, skewY, matrix.
  • Styling using simple and complex CSS selectors is supported.
  • Gradients and gradients linking definitions are supported.

Sprite definition

To define sprites, Diagrammer uses extensions to standard SVG. They are defined in the namespace "http://schemas.kapit.fr/svg/2007/". You must add to the <svg> tag in your library the following attribute : xmlns:k="http://schemas.kapit.fr/svg/2007/" .
Each sprite must be defined as a group (<g> tag), with the followings attributes :

  • k:spriteid defines the identifier of the sprite. It is used in Diagrammer as a unique identifier for a specific shape.
  • k:groupid defines the group of the sprite. Diagrammer provides a method to retrieve all sprite of a given group. This functionality can use by components (drop down menu, panels) that enable user to select any sprite from a given group.

Actions and anchor point definition

Using css styling, we will define how can the user interact with each sprite.
To enable input links to a part of a sprite, we must add the style action-accept:link to this part (it can be a group or any basic drawing instruction).
To enable output links for a part of a sprite, we must add the style action-click:link to this part.
To enable annotation for a part of a sprite, we must add the action-accept:annotation to this part. We usually put this in the group that defines the sprite.
As a basic rule, it is better to add a dedicated transparent path to define the link anchors, but depending on the sprite we can use part of sprite.

Putting it together

In this sample we will use a two sprite library. We define two basic shapes, a rectangle and a rounded rectangle. Using a vector based image editor that support SVG export (such as Inkscape), we can define more complex sprite. Be sure to remove all non standard tags from the SVG library before using it in Diagrammer.
We will use a SVG file generated by Inkspace to create a simple rectangle with a linear gradient and a rounded rectangle :

The generated files look like this :

Two Sprites Library Creation sample

We first clean the files, remove non standard tag and namespaces (sodipodi, inscape, purl, cc, rdf).

Non Standard tags and namespaces Remove Sample

We then put the css part into the definition part :

CSS Integration Sample

We defined basic and bg style. Basic style will be applied to a sprite to enable annotations. Bg style will be applied to anchor part.
The system style annotation and link-annotation are overloaded to fit our taste.
Then for each sprite we modify the group to set spriteid and groupid.

Basic Style Integration sample

Now the library is ready. We can open it with any SVG editor to check that it still renders as intended (but we shouldn't export it again to avoid adding unwanted tags).
Here is the SVG file (without the <?xml header) :

SVG Output Sample

Now let's write some code.

Creating the Flex project

Launch Flex Builder and choose New / Flex Project

Enter a name for your Project ("DiagrammerTutorial" for instance). Select Web Application and none for application server type. Press Finish to accept all default options

From the folder where you downloaded it, drag the Diagrammer.swc file into the libs folder in the flex navigator.

Type the following code in the DiagrammerTutorial.mxml file :

Basic Integration Tutorial

We removed the SVG part to show that you don't have to write lots of code. The svg library can be found on the previous section of this documentation.
Save the file, compile the project and run the application :

Drag shapes from the upper right menu to the main view. Clicking on an shape shows a upper right graphical menu that enables you to create new objects linked to the selected one.

Now let's explain the code in detail.

Detailed explanation

On the Application tag we add reference to the view and controls of the diagrammer. We also register a preinitialization function.

On the Application tag we add reference to the view and controls of the diagrammer. We also register a preinitialization function.

Preinitialization Tutorial

We then include the svg library in an xml tag.

Basic Integration sample

Including the svg library in the source is not mandatory. For example you can use an URLLoader to load the library from a svg file somewhere on the network.
In the init fonction we simply load the library from the xml. This must be done before the DiagramView object is created.

SVG Including in XML Tag sample

The application layout is simple. We use an ApplicationControlBar to hold a SVGAssetLibraryGroupButton, and an HBox to hold a DiagramView.

SVGAssetLibraryGroupButton Integration Tutorial

The SVGAssetLibraryGroupButton groupid property is set to "Basic", wich is the value used in our k:groupid attributes for our sprites in the library.

Basic SVGAssetLibraryGroupButton Setting Tutorial

The DiagramView object registers an initDiagram function

InitDiagram Function Registration Tutorial

The initDiagram function sets some diagram's options.

initDiagram Function Options Setting Tutorial

Multipanel is set to false so that the diagram doesn't support multipanel view. This option allows the diagram to be divided in verticals panels and lanes.
SelectionEnabled is set to true, so that objects can be selected on the diagram.
KeyboardEnabled is set to true, so that you can scroll with keyboard, enter text, etc.
DragEnabled enables dragging of object in the diagram.
DropEnabled enables dropping of objects in the diagram.

Adding layout to a diagram

In this part we will add layout functionality to our diagramming application. Diagrammer layouts are powerful algorithms that automatically place sprites and links of a diagram

Adding layout library

From the folder where you downloaded it, drag DiagramProxies.swc to the libs folder in the Flex Navigator.

Adding code

In the script part of DiagrammerTutorial.mxml, add a reference to the proxy.

Proxy Reference Integration Tutorial

In the initDiagram function, add the initialization of the proxy. Proxy initialization must be made after diagram creation.

Proxy Initialization Tutorial

In the ApplicationControlBar, add a button that calls the doRadialLayout function on click.

Basic Integration sample

Add the doRadialLayout function at the end of the script part

RadialLayout Integration Code

Running the test

Build the application and launch it.
Create linked sprites.

Click on the Radial Layout button and let the magic happens...

More layouts

Now your application supports the radial layout. The Diagrammer has many more built-in layouts such as hierarchical, radial, balloon, organic layouts.
Let's add the animated organic layout to your application.
Add a new button to the Application control bar that calls the doAnimatedLayout function when clicked.

Animated Layout Call Code

Add the doAnimatedLayout function at the end of the script part

Animated Layout Integration Code

Compile and launch the application. Create linked objects, click Animated Layout button, and drag one object. You will see all the other objects following your object in a nice animation.

Binding data to a diagram

In this part we will add data binding between the diagram view and application data. This enables developers to propose alternative views of sprites and links of the diagram. Using flex bindings any change in property of sprites and links in the diagram are automatically reported in alternative views.

Data binding from diagram objects to application data uses proxies. To enable binding, a developer must create sprite proxy classes implementing ISpriteProxy interface and link proxy classes implementing ILinkProxy interface. Then he must create a configuration file that links spriteid, links and proxies. Then he must create a DiagramModel with the configuration file and define it as the model of the DiagramView.

When this plumbery is done, everytime a sprite or a link is created, deleted or changed, the corresponding method of the corresponding proxy is called. It is the responsibility of the developer to implements application data manipulation so that application data reflects the states of the diagram.

In this tutorial we will use only one proxy for sprites and one for links. For real world application, you can have specific proxy for some sprites, or have several sprites sharing the same proxy.

Writing data object

From the Flex Navigator src folder, select New / ActionScript Class. Name it MyObject.

Add the following code:

Data Object Definition

We define all attributes as bindable to display them in a DataGrid with no code.

Writing objects proxy

From the Flex Navigator src folder, select New / ActionScript Class. Name it MyObjectProxy, and add ISpriteProxy as an interface. This way all methods will be automaticaly created by Flex builder for you.

Add the following code:

Object Proxy Integration Tutorial

From the Flex Navigator src folder, select New / ActionScript Class. Name it MyLinkProxy, and add ILinkProxy as an interface. This way all methods will be automatically created by Flex builder for you.

Add the following code:

Link Proxy Integration Tutorial

Adding mappings

In the DiagrammerTutorial.mxml file, add a xml document holdings mappings.

Mapping Adding Code

Add imports and application data definition. In this tutorial we will use ArrayCollection as an example, as we don't want to multiply class definitions.

Imports and Application Definition Code

In the initDiagram function, set the proxy ArrayCollection and set the diagram model.

Setting ArrayCollection Proxy and Diagram Model Sample

Data bindings are now activated. You can test it by debugging your application and setting breakpoint in MyObjectProxy and MyLinkProxy methods. You will see that the proxy object is created when the first diagram object is created, and that createDataObject function is called each time an object is created.

The code you wrote add an Object in the myOBjects and myLinks ArrayCollections and keep them synchronized with the diagram sprites and links.

Now we will add some code to use these ArrayCollections.

Displaying application data

We change the application layout by adding two DataGrids. One will display the sprites and the other the links.

DataGrids Integration Code

Build and run the application. Add sprites and links to the diagram, you will see them appear on the corresponding grid. Add annotation to objects and see them reflected in the name column.

Now we have two DataGrids connected to the Diagram. But when you select a sprite or a link, nothing is selected on the grids. And when you select a row on a grid nothing get selected on the Diagram. Let's fix this.

Synchronizing selection

First add some imports

Basic Import Code

Register to the selection changed of the diagram in the initDiagram function

Selection Changed Registration Code

Add the function to handle selection on the diagram and select the corresponding row on the correct grid.

Diagram Selection and DataGrid Row Correspondency Code

Now we have one way selection synchronization : when an object is selected on the diagram the corresponding row get selected on the grid. We need to add the other way.

Register a function on the itemClick event for the two DataGrid :

Item Click Event Integration Code

Add the function in the script part

Item Click Handler Description Code

And that's it. Compile and run the application, create sprites and links, click on a diagram object and grid row and see as all is kept in sync.

Now the last improvement we can add is the ability to change graph object property from user input outside of the diagram view.

Graph object modification

First let's make the name field editable.

Enabling Name Field Edition Code

Add some imports

Basic Import Code

Then type the function handleEditEnd

Edit End Handler Integration Code

In the handleEditEnd function we retrieve the new value and set it as an annotation for the corresponding sprite in the diagrammer. If the sprite doesn't already has an annotation we create it.

You now have a bi-directionnal data bindings between the diagram and application data.

Sprites composition in a diagram

In this part we will add sprite composition capability to our application.
Sprite composition is a mecanism of visually combining several sprites into a single one, just like in a group. But there are differences between grouping and composition :

  • one of the sprites (the master or composite) contains all the composition elements. He can be move and resize, and the composition elements are moved and resized accordingly.
  • Not all sprites can become composite or composition elements. This is defined by the SVG style "action-accept:composition" for a composition element and "action-accept:composite" for a composite (or master element).
  • A composite has reserved areas (svg elements) where composition elements can be put. There is only one composition element per area. So there is a maximum number of elements in a composition, and the maximum depends on the composite sprite definition.
  • Composition is triggered when the user drags a sprite (the composition element) into another sprite (the composite).
  • Composition is considered as a change in data model, so acceptance of composition is enforced through methods of the sprite proxies, and occurrence of composition lead to sprite proxies methods calls.

Creating a SVG shape library

Starting for the result of previous part, we change the SVG library to add composition capabilities.

Modify the XML svglibrary tag content accordingly:

Composition Capabilities Add On The XML SVG Library Tag

Changing the mappings

Replace the diagramMappings tag with this:

Diagram Mapping Modification Code

We only changed the sprite proxy definition to match our new library.

Creating objects programmaticaly

We will create a composite at the application start.

First add some imports

Basic Import Code

Change the initDiagram function:

Composite Creation Code

We first create a rounded-rectangle sprite, which can become a composite, then a rectangle, which can become a composition element.

Then we create a composition with the rounded-rectangle as a master, and the rectangle as an element.

At this point if you run your application you will see the composition sprite. You can move it, resize it and you will see how the composition element are moved and resized.

Composition and data object proxies

We will create a composite at the application start.

Adding properties to data object

Edit the MyObject.as file to add properties :

Data Object Properties Add

We will count the number of elements in a composition (the compositions properties), and store the master (composite) of a composition element.

Handling composition in object proxy

Modify MyObjectProxy.as file to handle composition messages.

Composition Handler on The Object Proxy Code

The property compositionmaster is changed when a sprite enter a composition, and compositionmasterleave when he leaves a composition.

In our application when a sprite enter a compositon we :

  • Make it selectable and movable.
  • Change its sprite.
    We he leaves a composition, an element sprite is set back to original sprite.
    The property compositionelement is changed when a composite receive a new composition element, and compositionelementremove when the element leaves (or is deleted).

In our application we increase and decrease the number of element of the composite when an element is added or removed.

Displaying properties in a DataGrid

Change the objects datagrid to display compositions and master properties

Composition & Master Properties Display Integration Code

Run the application and see as the elements and master fields gets updated when you move elements from composite to another, delete them, add them...

Alter composition acceptance through proxies

Change the MyObjectProxy class to handle accept message:

Message Acceptance Handler Through Proxies Integration Code

Returning false in these function forbid the user to do the action he attempted.

In the compositionmaster case, we accept that a sprite enter a composition only if it wasn't in a composition before or with the same master (in the case the element is moved in another area inside the composite).

In the compositionelement case, we accept that a sprite enter a composition only if it the composition is empty or with the same master (in the case the element is moved in another area inside the composite). This way we limit the number of element of a composition to 1, although we can have several area in a composite.

In the acceptRemoveObject, we don't accept to remve a sprite inside a composition (with a non null masterobject).

As you can see, with acceptance functions you have great flexibility to enforce your business rules.

Join the Lab

  • Access to our free components
  • Give your feedback, your needs
  • Participate to our roadmap

Forgot password ?

Buy Commercial Edition

and Support

(Including Source Code)

Related Projects

Kap Lab Updates on Tour de Flex !

Visit Kap Lab components on Tour de Flex, a great AIR/Flex explorer presenting components selected by Adobe.

Take the Tour (Data Viz & others) »

Need Information?

Why Kap Lab ?

Kap Lab exists because innovation is our passion. Enjoy our products and help us to give you the best.

Cyril Daloz
CEO Kap IT

Adaptavist Theme Builder (3.3.5-conf210) Powered by Atlassian Confluence 2.10.3, the Enterprise Wiki.