Photo Album in WPF with the Diagram Control

In this blog post we will build a photo album application. The application shows pictures organized in folders and allows the user to add new pictures, new folders as well add/delete/rearrange the photos that are already added to the folders.

Here is a screenshot of the application:

Photo Album with the WPF Diagram Control

Photo Album with the WPF Diagram Control

The app is built with the diagramming for WPF component.

I. General Settings

We create a new WPF application in Visual Studio. There, in the main window, the Window.Resources section we add a new item – a context menu:

 <ContextMenu x:Key="ContextMenu">
         <MenuItem x:Name="FolderMenuItem" Header="Add new folder" Click="AddFolderMenuItem_Click"/>
         <MenuItem x:Name="ImageMenuItem" Header="Add new image" Click="AddImageMenuItem_Click"/>

The context menu shows up every time we right-click on a node.

We leave the default Grid layout panel and add there a ScrollViewer. The ScrollViewer would hold the diagram. Let’s add a XAML mapping to the Diagram class in the Window element:

xmlns:diag="" xmlns:common="" 

We need a reference to the common namespace as well because the Diagram class uses it. Now, in the ScrollViewer we can add the markup for the Diagram:

<diag:Diagram x:Name="diagram" Bounds="0, 0, 1000, 1000" DefaultShape="Ellipse" AlignToGrid="False" Behavior="Modify" NodeModified="diagram_NodeModified" NodeClicked="diagram_NodeClicked">

The application needs reference to the following MindFusion.Diagramming libraries:

  • MindFusion.Diagramming.Wp
  • MindFusion.Common.Wpf
  • MindFusion.Licensing

II. Styling

In the code-behind file we create a Theme and add two Style-s to it: one for the links and one for the nodes.

 //create a new theme
 Theme theme = new Theme();

 //create a style for the links
 Style linkStyle = new Style();
 linkStyle.Setters.Add(new Setter(DiagramLink.BrushProperty, new SolidColorBrush(Color.FromRgb(245, 245, 240))));
 linkStyle.Setters.Add(new Setter(DiagramLink.StrokeProperty, new SolidColorBrush(Color.FromRgb(191, 191, 191))));
 linkStyle.Setters.Add(new Setter(DiagramLink.HeadStrokeProperty, new SolidColorBrush(Color.FromRgb(191, 191, 191))));
 //register the style with the theme
 theme.RegisterStyle(typeof(DiagramLink), linkStyle);

The link style sets the brush and stroke for the links as well the stroke for the link’s head. The brush is used to fill the head shape of the link. Finally we register the style with the theme. Here is what the node style looks like:

//create a style for the nodes
Style nodeStyle = new Style();
nodeStyle.Setters.Add(new Setter(ShapeNode.StrokeProperty, new SolidColorBrush(Color.FromRgb(191, 191, 191))));
nodeStyle.Setters.Add(new Setter(ShapeNode.FontFamilyProperty, new FontFamily("Lato")));
//register the style with the theme
theme.RegisterStyle(typeof(ShapeNode), nodeStyle);

We specify the stroke that would outline each node and the font that would be used when labels on nodes are painted. The final step is to assign the new Theme to the Theme property of the diagram:

 //assign the theme
  diagram.Theme = theme;

We also change the default head shape of the link and its size:

 //set link styling
 diagram.LinkHeadShapeSize = 12;
 diagram.LinkHeadShape = ArrowHeads.Triangle;

III. Create Diagram Items

When you run the application it shows a diagram that is a tree with folders and images. We will create this diagram in code. First, we create a new array that would hold the names of the folders:

string[] labels = new string[] {"Images", "Events", "Family", "Tourism",
                "Autoexibition 2014 Detroit", "Depeche Mode Concert 2016", "Third March",
                "Lia`s birthday", "New year 2017", "Sam`s graduation",
                "Brazil and Argentina", "Italy 2013", "Summer 2017"};

Then we must create a node for each label:

 //create the initial nodes for the album
 for(int i = 0; i < labels.Length; i++)
     var node = CreateFolder(labels[i]);

Each node is created by calling the CreateFolder method. This method creates and styles a DiagramNode. It sets a Folder image as background for the node and adjusts its text alignment. The node is drawn transparent:

 //creates a new folder with the specified text.
 private ShapeNode CreateFolder(string text)
       var node = new ShapeNode();
       node.Text = text;
       node.Tag = "Folder";
       node.Transparent = true;
       node.TextAlignment = TextAlignment.Center;
       node.TextVerticalAlignment = AlignmentY.Center;
       node.Expandable = true;
       BitmapImage image = this.FindResource("Folder") as BitmapImage;
       node.Image = image;
       return node;

Note that we use the Tag property of a DiagramItem to assign the text “Folder”. We will use this identification string later in the sample, to recognize that the user has clicked on a folder.
The image is declared as a resource in XAML, in the Window.Resources section:

<BitmapImage x:Key="Folder" UriSource="Folder.png" />

Each major folder has subfolders and they contain images. The subfolders with images are located in the Images directory. We declare a global variable that points to the Images folder:

 private const string path = @".\Images";

Then we need to cycle through all directories in “Images” and create subfolders for them.

 int length = 0;
 // reads the initial subfolders for the album 
 string[] subfolders = System.IO.Directory.GetDirectories(path);
 string[] folders = new string[9];

Once we have the subfolders we must cycle through their subfolders as well because each one has several subfolders in it. Those second level subfolders actually contain the images:

 //goes one level deeper into the hierarchy
 for (int i = 0; i < subfolders.Length; i++)
       string[] subsubfolders = System.IO.Directory.GetDirectories(subfolders[i]);
       for(int j = 0; j < subsubfolders.Length; j++)
          folders[length] = subsubfolders[j];

Once we’ve created nodes for each folder it is time to create the nodes that represent the images:

 //loads the images for each folder
 for(int i = 0; i < folders.Length; i++)
      string[] filenames = System.IO.Directory.GetFiles(folders[i]);
      LoadImages(filenames, diagram.Nodes.GetAt(i + 4) as ShapeNode);

We go through all folders that actually contain images and use a new method LoadImages to create DiagramNode-s for each image file. The LoadImages method needs the names of the files that would be places in the children nodes and the parent node:

private void LoadImages(string[] filenames, DiagramNode parent)
     for (int i = 0; i < filenames.Length; i++)
         var node = CreateImage(filenames[i]);
         diagram.Factory.CreateDiagramLink(parent, node);

The method creates an Image node and adds it to the collection of diagram nodes accessible through the diagram.Nodes property. hen it creates a link from the parent to the new node. Note that when we create diagram items through the diagram.Factory helper object they are added automatically to the respective nodes or links collections. Now let’s look at the CreateImage method:

private ShapeNode CreateImage(string path)
      var node = new ShapeNode();
      //customize the node appearance
      node.Shape = Shapes.RoundRect;
      node.Brush = new SolidColorBrush(Color.FromRgb(245, 245, 240));
      node.Tag = "";
      //assign the image
      Uri imageUri = new Uri(path, UriKind.Relative);
      BitmapImage image = new BitmapImage(imageUri);
      node.Image = image;
      return node;

The method creates a node and applies some styling to it. It gets the relative Uri to the image and assigns it to the node.Image property.

The last thing to do is to create links between the three major subfolders and the root folder:

//create links between the root and all subfolders
diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(0) as ShapeNode, diagram.Nodes.GetAt(1) as ShapeNode);
diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(0) as ShapeNode, diagram.Nodes.GetAt(2) as ShapeNode);
diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(0) as ShapeNode, diagram.Nodes.GetAt(3) as ShapeNode);

Then we have to create links between those subfolders and their subfolders in similar way:

diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(1) as ShapeNode, diagram.Nodes.GetAt(4) as ShapeNode);
diagram.Factory.CreateDiagramLink(diagram.Nodes.GetAt(1) as ShapeNode, diagram.Nodes.GetAt(5) as ShapeNode);

IV. Arrange the Diagram

We use the TreeLayout algorithm to arrange our nodes in the right order. This layout is the perfect match for what we want – a hierarchy of nodes that is exactly a tree.

private void Rearrange()
     if (layout == null)
        layout = new TreeLayout(diagram.Nodes.GetAt(0),
        TreeLayoutLinkType.Cascading3, TreeLayoutDirections.TopToBottom,
        40, 20, true, new Size(15, 15));

The TreeLayout like all other automatic layouts available in MindFusion diagramming controls is pretty easy to use. It requires the call of a single Arrange method that takes as a parameter the instance of the diagram being arranged. The constructor lets you customize the layout, in our case we use this TreeLayout constructor. The constructor requires the root node, the TreeLayoutType, the next argument specifies if links are reversed, then comes the TreeLayoutLinkType, the TreeLayoutDirections and several numbers that indicate level distance, node distance and whether root position is kept. The last argument is the margins between the tree and the diagram’s bounding rectangle.

We call the Rearrange method every time we modify the diagram – when nodes are added/deleted or modified.

V. Events

We handle the NodeClicked event, which we use to show the context menu:

private void diagram_NodeClicked(object sender, NodeEventArgs e)
      //gets the node that was clicked
      SelectedNode = e.Node as ShapeNode;
      if (e.MouseButton == MindFusion.Diagramming.Wpf.MouseButton.Right && SelectedNode.Tag.ToString().Length > 0)
         //renders the context menu
         ContextMenu cm = this.FindResource("ContextMenu") as ContextMenu;
         cm.Placement = System.Windows.Controls.Primitives.PlacementMode.Mouse;
         cm.IsOpen = true;

The important part in this code is to get the selected node. We will need it to specify the parent node for any new folders or image nodes that we create. Then, based on the menu selected by the user we either create a new folder node or a new image node calling the CreateFolder or CreateImage method that we listed above.

What happens when the user modifies a node? That happens when the user drags a node from one folder into another folder. In this case the diagram link between the former parent and the node is deleted and a new one is created – between the new parent and the node:

private void diagram_NodeModified(object sender, NodeEventArgs e)
   //gets the nodes at the specified mouse position
   if (diagram.GetNodesAt(e.MousePosition).Count != 1)
      ShapeNode child = e.Node as ShapeNode;
      ShapeNode parent = null;
      bool parentIsFolder = false;
      foreach (ShapeNode node in diagram.GetNodesAt(e.MousePosition))
               //check if the node is a folder
               if (node.Tag.ToString().Length > 0 && node != child)
                   parent = node;
                   parentIsFolder = true;
           //removes the current link between the node and its parent
           if (parentIsFolder)
               if (child.IncomingLinks.GetAt(0) as DiagramLink != null)
                   diagram.Links.Remove(child.IncomingLinks.GetAt(0) as DiagramLink);
           //creates a new link
           diagram.Factory.CreateDiagramLink(parent, child);

Remember that we have assigned “Folder” to the Tag property of all nodes that are folders. We use this to identify them and to move the node from one folder to the other.

And with this our tutorial is over, here is a screenshot from the final application:

Photo Album App with the WPF Diagram: User Interaction

Photo Album App with the WPF Diagram: User Interaction

The link to download the sample is below:

Download Wpf Diagramming Sample: Photoalbum

About Diagramming for WPF: This is the right tool to create flowcharts in WPF that always meet your requirements. The library offers more than 100 predefined node shapes, extensive event set and more than 15 exporters and importers. Each diagram that you build has a completely customizable look through styles, themes and appearance properties for each part of the flowchart. The numerous samples and detailed documentation help you learn quickly how to integrate the component into your own application. You can download the trial version, which has no feature restrictions and does not expire from the WPF Diagram Page on MindFusion website.

Org Chart in JavaScript with the Diagram Library

In this blog post we will use the Js Diagram library to create a beautiful organizational chart, where people from the company are represented with the hierarchy links between them. Each employee has a photo, name, position, boss and section for comments. The links between them demonstrate the hierarchy.

Run the sample from

I. Application Setup

We create a new folder for the project and there we copy the scripts that the sample uses. They are predominantly jQuery scripts, which you can also link from the jQuery CDN website.

Org Chart in JavaScript: Directory Structure

Org Chart in JavaScript: Directory Structure

The samples.css and samples.js scripts are used by all MindFusion JavaScript samples and are not relevant to your application. They layout and style the HTML content.

We need to create two files for this application – an HTML page and a JavaScript file that will be used by it. We create OrgChartEditor.html and link the following scripts and a CSS file in the section:

<a href="http://common/jquery.min.js">http://common/jquery.min.js</a>
<a href="http://common/jquery-ui.min.js">http://common/jquery-ui.min.js</a>

Then we create an empty (for now) js file that will hold the code-behind for the web page. It is called OrgChartEditor.js. We must reference it, from the HTML but we will do that at the end, before the closing tag. That is done because some browsers might not load correctly the scripts if they are initialize before the HTML code for the canvas.

<a href="http://MindFusion.Common.js">http://MindFusion.Common.js</a>
<a href="http://MindFusion.Diagramming.js">http://MindFusion.Diagramming.js</a>
<a href="http://OrgChartEditor.js">http://OrgChartEditor.js</a>

As you see, we have copied MindFusion.Common.js and MindFusion.Diagramming.js in the directory of the web page. There we have also saved OrgChartEditor.js.

The diagram uses an HTML Canvas to render itself. We create one on the web page:

<div style="width: 100%;height: 100%;overflow: auto">
		This page requires a browser that supports HTML 5 Canvas element.

Note that the element has an id. That’s important because we will reference it in the code behind file.

II. The OrgChartNode.

Each employee on the diagram is represented by a special node – the OrgChartNode. This node is a customized TableNode.

// creates a table node with the default settings
var OrgChartNode = function (parent, boss)
       AbstractionLayer.initializeBase(OrgChartNode, this, [parent]);

       this.childNodes = [];

	// set up table cells
	this.redimTable(3, 4);
	this.getCell(1, 3).setColumnSpan(2);
	this.getCell(0, 0).setRowSpan(4);
	this.getCell(1, 1).setText("Title:");
	this.getCell(1, 1).setFont(
            new Font("Verdana", 3.5, true /*bold*/, false /*italic*/));
	this.getCell(1, 2).setFont(
            new Font("Verdana", 3.5, true /*bold*/, false /*italic*/));
	this.getCell(1, 0).setFont(
            new Font("Verdana", 3.5, true /*bold*/, false /*italic*/));
	this.getCell(1, 3).setFont(
            new Font("Verdana", 3, false /*bold*/, false /*italic*/));

Each OrgChartNode has a parent and a boss. The CEO, which is the topmost node in the hierarchy has no boss. The OrgChartNode is a TableNode with 3 columns and four rows. Cell(0,0) is reserved for the image of the employee. It spans 4 rows.

The cells in the second column with index 1 are for labels: title, name, id and comments. We style them with bold font.

The prototype of the OrgChartNode gets or sets the properties which deal with the data we need for each employee. We set the fields for each new node and update the existing canvas elements. We define an updateCanvasElements method that calls the updateCanvasElements of the parent class to mark the changes. We also declare setter/getter methods for each OrgChartNode field:

OrgChartNode.prototype =
	// updates the existing elements
	updateCanvasElements: function (node)
		AbstractionLayer.callBaseMethod(OrgChartNode, this, 'updateCanvasElements');

        // gets the title of the employee
	getTitle: function ()
		return this.title;
        // sets the title of the employee
	setTitle: function (value)
		if (this.title !== value)
			this.title = value;

When we set a new value we invalidate the canvas so that the changes can be rendered correctly on the screen.

// assigns the employee data to the table cells
setFields: function()
    // hide the caption and place the employee names on row 0 
    // rearrange the org hierarchy

The setFields method takes the data from the OrgChartNode fields and assigns it to the correct cells of the table. It also assigns the correct boss of the employee. In our samples bosses are assigned automatically and cannot be edited by the user. This is done by the setHierarchy method:

// rebuilds the hierarchy
setHierarchy: function ()
    // the ceo has no boss
    if (this.boss == undefined)
	   this.hierarchy = 0;
             // first level of executives under the boss
	     if (this.boss.hierarchy == undefined)
		  this.hierarchy = 1;
	         // increase the depth of the hierarchy
		 this.hierarchy = this.boss.hierarchy + 1;
         // rearrange the hierarchy
	 for (var i = 0; i &lt; this.childNodes; i++)

The setColor method assigns the right color for the background of the table. Different levels in the hierarchy are distinguished by different colors. The top level – the CEO – is read.

III. Interaction

The org chart allows the users to do a lot of things: edit certain table cells, delete and create nodes, create and delete links, move and drag the nodes. This is done by handling a lot of events that the diagram library exposes.

First, we set the Behavior property of the diagram to “Custom”. This means we will define how the library responds to user actions. This is done because none of the predefined Behavior modes answer the specific needs of our application:


Then we start handling events. First, we handle the Clicked event:

diagram.addEventListener(Event.clicked, function (diagram, eventArgs)
     // check which mouse button was clicked
     var button = eventArgs.getMouseButton();
     var position = eventArgs.getMousePosition();


We handle differently clicks with the right and left mouse buttons. If it is the right mouse button we should create a new OrgChartNode:

// click with the right mouse button creates a node
if (button === 2)
	var node = new OrgChartNode(diagram, undefined);
	node.setBounds(new Rect(position.x, position.y, 20, 20));

	// adds the node to the diagram items

	// rearrange the diagram

Initially, the node has no boss, it will be determined once we link it to the rest of the org chart.

Let’s see what happens when the users clicks on a node:

diagram.addEventListener(Event.nodeClicked, onNodeClicked);

We handle the nodeClicked event with the onNodeClicked method:

// raised when the user clicks on a node
function onNodeClicked(diagram, eventArgs)
	// checks if the user has clicked with the left mouse button (0)
	var button = eventArgs.getMouseButton();
	if (button === 0)
		editNode(diagram, eventArgs);

        //click with the right mouse button creates a node
        else if (button === 2)
        createNode(diagram, eventArgs);

When the node is clicked with the left mouse button – we edit it. When it is clicked with the right one – we create a new node, linked to it, one level deeper into the hierarchy.

// called when the user edits a table
function editNode(diagram, eventArgs)
     var cellEditor = eventArgs.getNode().cellFromPoint(eventArgs.getMousePosition());

     // the table node to edit
     var tableNode = eventArgs.getNode();

We use the cellFromPoint method to identify the cell that was clicked. The cells that cannot be edited – the ones that render the labels – have no cellEditor.

// cells that cannot be edited have no cellEditor assigned
if (cellEditor.cell != undefined)
       if(cellEditor.cell.editable == true)
	   edit = true;

If the cell can be edited we check which is the cell and what type of content it renders:

// if the cell can be edited
if (edit)
	$("diagram_inplaceInput").attr("placeholder", "url");

	cellEditor.cell.onEdited = function (diagram, tableCell)
		if (edit)
			if (cellEditor.cell.image)
				// read and assign the URL of the new image
				if (tableCell.getNewText() != undefined &amp;&amp;
					tableCell.getNewText() != "" &amp;&amp;
					tableCell.getNewText != "undefined")
				cellEditor.cell.text.height = 0;
				cellEditor.cell.text.text = "";

In the code above we check to see if the image location is correctly set and if so – we read the new image from the url and render it in the cell.

Handling the other events is easier, let’s look at the event fired when cell text is edited:

//add an eventListener for the cellTextEdited event
diagram.addEventListener(Event.cellTextEdited, function (diagram, cellArgs)
   cellArgs.getCell().onEdited(diagram, cellArgs);

Here we just call the onEdited method of the cell that is edited, which we explained above. The samples handles this way a lot of events: nodeDeleted, linkCreated, nodeModified and many more. You can check them in the source code provided with the sample.

IV. Diagram Layout

The org chart uses the predefined TreeLayout to arrange the diagram. It is ideal for hierarchical types of charts because it neatly arranges all nodes from a given level in a row/column based on the direction set.

// we apply the tree layout to arrange the diagram
tree = new MindFusion.Graphs.TreeLayout();

// customize the tree layout
tree.direction = MindFusion.Graphs.LayoutDirection.TopToBottom;
tree.linkType = MindFusion.Graphs.TreeLayoutLinkType.Cascading;

The TreeLayout is animated:

// rearrange the diagram

It is called not only at the beginning but also each time a new node is created or deleted, link is created and/or deleted as well when link or node is edited.

V. New Nodes

Finally, let’s see how nodes are created in code:

var ctoNode = new OrgChartNode(diagram, ceoNode);
ctoNode.setBounds(new Rect(25, 55, 60, 25));
ctoNode.setFullName("Bob Smith");
ctoNode.setComment("A great person!");

New nodes, as you already know are created by the user with a right mouse button click on any node. If a link is deleted, the node is detached from the hierarchy and the user should drop it over an existing node to indicate its place in the hierarchy.

With this we finish our sample. We have presented you with the most important information on how this org chart in JavaScript is created. You can download the complete source code of the sample from this link:

Download MindFusion JavaScript Organizational Chart Sample

The sample is also available on GitHub at

The sample is available online at

Find out more about MindFusion JavaScript Diagram Library at

A JavaScript Application for Server Load Monitoring (Continued)

We continue the ServerLoad tutorial with the diagram.

I. Create and Style The Diagram

We create a new JavaScript file named diagram.js in the Scripts folder of the project and reference it in the HTML.

<a href="http://Scripts/MindFusion.Diagramming.js">http://Scripts/MindFusion.Diagramming.js</a> 

Now, in this file we make some namespace mapping to access easy the classes we need:

var Diagram = MindFusion.Diagramming.Diagram;
var DiagramLink = MindFusion.Diagramming.DiagramLink;
var ShapeNode = MindFusion.Diagramming.ShapeNode;
var Style = MindFusion.Diagramming.Style;
var DashStyle = MindFusion.Drawing.DashStyle;
var Alignment = MindFusion.Diagramming.Alignment;

var Rect = MindFusion.Drawing.Rect;
var LayeredLayout = MindFusion.Graphs.LayeredLayout;
var LayoutDirection = MindFusion.Graphs.LayoutDirection;

// a shortcut to the Events class
var Events = MindFusion.Diagramming.Events;

The code for the diagram does not need to be in a single method call, so we’ll use the document.ready event handler:

$(document).ready(function () {

// create a Diagram component that wraps the "diagram" canvas
diagram = MindFusion.AbstractionLayer.createControl(Diagram, null, null, null, $("#diagram")[0]);
//set both base and head link shape size


As with the line chart, we create a diagram object using the canvas id from the html page. Then we make some link customization: we set the base and head shape with setBaseShape and setHeadShape to “Arrow” to indicate that data flows in two directions between servers.

Now let’s use a Style instance to set the stroke, text color and font name. Then we set the link style this way:

//customize the link appearance
var linkStyle = new Style();

When users click on the diagram it is important not to allow them to create new links and nodes. That’s why we use setBehavior to change the default way the diagram responds to user actions:

//diagram items can only be selected

We create the graph in the buildDiagram method. First, we call clearAll to remove all diagram items to make sure only nodes we’ve created are visible:

//generate diagram nodes
function buildDiagram() {


II. Diagram Items

Let’s create the diagram nodes. We use png icons we’ve saved in an “icons” folder in the website. The background of each node is transparent ( setTransparent ), which means only the image will be visible. Then we add the node to the items of the diagram:

var rect = new Rect(0, 0, 15, 15);

var node = new ShapeNode(diagram);
//the web server

We create similar nodes for the data server, the clients and the network servers. The links are created with the DiagramLink class. The constructor takes the origin and target node of the link as parameters. We set an setId to the links, which is important and we add a label :

//add a link between the client and the server
var link = new DiagramLink(
       diagram, node, diagram.nodes[0]);
//same as the title of a given chart series
link.setId("Client" + i);
link.addLabel("Client" + i);

Let’s not forget to emphasize the two links that correspond to the two series that are initially emphasized on the chart:

//bolden the two major links

III. Layout

We’ve created the diagram items but we need to arrange them. We use the LayeredLayout algorithm:

//the layeredLayout arranges the diagram properly - into layers
function applyLayeredLayout() {
    var layout = new LayeredLayout();
    layout.direction = LayoutDirection.TopToBottom;
    layout.siftingRounds = 0;
    layout.nodeDistance = 20;
    layout.layerDistance = 20;

As you see it is very easy to apply a layout with the diagramming control. You just create an instance of the layout, set the properties of your choice and call arrange (). In our case we need the layout direction to be LayoutDirection.TopToBottom We also adjust the nodeDistance and layerDistance and set the number of siftingRounds (attempts to unwind split links) to 0.

IV. Events

The diagram is meant to be interactive. We use the linkSelected and clicked events to handle selection of links and click on an area of the diagram, unoccupied by any items.

// add listeners
diagram.addEventListener(Events.linkSelected, onLinkSelected);
diagram.addEventListener(Events.clicked, onClicked);

When a link is selected, we need to emphasize the line graphic that corresponds to this link. We also emphasize the link itself. In addition, we must adjust the stroke and thickness of the other line graphs and diagram links. We do this in the onLinkSelected method:

//handle the linkSelected event
function onLinkSelected(sender, args) {

    //get the style of the series
    var seriesStyle = lineChart.plot.seriesStyle;

    //thicken just the selected series, the others should be transparent
    for (var j = 0; j &lt; lineChart.series.count() ; j++) {

First we get the series style and then we use setStrokeThickness to reset the thickness of diagram links and series to their default values. After we’ve done that we need to get the selected links and emphasize them:

//bolden all selected links in the diagram as well
for (var m = 0; m &lt; diagram.selection.links.length; m++) {
     var clickedLinkId = diagram.selection.links[m].getId();

When we’ve done that we need to find the series that correspond to these links and emphasize them as well:

//find the series that correspond to the selected links
for (var i = 0; i &lt; lineChart.series.count() ; i++) {
      var _series = lineChart.series.item(i);

      //adjust the stroke thicknesses
      if (_series.title == clickedLinkId) {

          seriesStyle.strokeThicknesses.insert(i, 3);


All this is followed by a call to the draw method that repaints the chart.

//repaint the chart

The next event handler – the onClicked method resets the thicknesses to their default values:

//reset the chart thicknesses
function onClicked(sender, args) {


This is done in the resetThicknesses method, which uses the seriesStyle field of the line chart:

/* bolden the two major series, the others should be very thin.
bolden the two major diaglinks as well. */
function resetThicknesses() {
   var seriesStyle = lineChart.plot.seriesStyle;

   for (var j = 0; j &lt; 5; j++) {

V. Tyre Separators

The diagram is divided into three parts by three separator lines. These lines are unconnected DiagramLink instances that have no head and base shape and have a custom position for the label. We use absolute positioning to locate the arrows. To do this we need to know the current size of the diagram:

//add the separators for the tyres
//first get the size of the diagram
var width = diagram.getBounds().width;
var height = diagram.getBounds().height;

Then the separator link is created with both origin and destination node being null:

//separator for the Clients tyre
//the link starts from the left edge and eds to the right edge of the digram
var link = new DiagramLink(
		diagram, new MindFusion.Drawing.Point(2, (height / 3.5)),
        new MindFusion.Drawing.Point(width, (height / 3.5)));
//remove the shapes at both ends
//do not allow this link to be selected
//move the link label to the right
var linkLabel = link.addLabel("Clients");
linkLabel.setControlPointPosition(1, -5, 0);

Note that we’ve used the setLocked property of the link and have set it to true. This means the link cannot participate in user interaction – it can’t be selected, moved, resized. That’s what we want.

And with this our sample server load application is ready. Once again, here is how it looks:

Server Load Application in JavaScript

Server Load Application in JavaScript

Run The Application

Use this link to download the full sample with all necessary libraries and scripts.

Download Source Code

You can also fork it from GitHub.

Visit the web pages of the diagramming and charting (with gauges) JavaScript libraries to learn more about these tools. Visit the MindFusion forums if you need technical support or want to ask further questions about MindFusion developer tools.

A JavaScript Application for Server Load Monitoring

In two blog posts we will look at the main steps to create a sample server load web application. We will use the chart, gauge and diagram libraries. The data is simulated with random numbers.

Server Load Application in JavaScript

Server Load Application in JavaScript

Run The Application

The chart shows number of users on a given connection between two stations in the network at each moment. The graphic includes data for the last 30 seconds. The diagram shows the servers and clients that build the network. By default the charts shows data only for the two most important connections, out of total 10. Users can select different connections and view their graphics. The gauge control provides data for the average count of users at any given moment.

I. Project Setup

We create an empty website and add a Scripts folder with the necessary files:


and a reference to jQuery or the jQuery library itself:


We create a blank HTML file and we create three HTML Canvas elements – one for each of the controls: chart, diagram, gauge.

We use the Flexbox layout and we create a CSS file referenced by the index.html file where we write the CSS settings for the layout:

<link href="common/style.css" rel="stylesheet" />

We initialize a section region that would have a Flexbox layout:

section {
   display: flex;
   max-width: 700px;

The CSS class used for <div> elements inside <section>:

.column {
  margin: 10px 10px 0px 0px;
  flex: 1 1 0;
  border: 1px solid #cecece;

section:first-of-type .column:first-of-type {
  flex: 1 1 auto;

We specify that the first column on the second row would be twice wider than the other column. This is the diagram, and the other column is occupied by the gauge.

section:nth-of-type(2) .column:first-of-type {
  flex: 2 2 22;

That’s how the HTML uses the CSS attributes:

    <div class="column">
      <canvas id="lineChart"></canvas>

Note the id=”lineChart” attribute – we will use the id to initialize the LineChart object in the *.js file. The diagram and gauge Canvas instances also have id-s.

At the end of the index.html we include a reference to the require.js file to load the chart and gauge libraries this way:

<script src="Scripts/diagram.js" type="text/javascript"></script>
<script data-main="charts" src="Scripts/require.js"></script>

Note: Internet Explorer might not load properly the JavaScript libraries if they are declared at the beginning of the file, (in the head section) before the initialization of the Canvas-es. Therefore it is best to put the script references at the bottom, right before the closing </body> tag.

II. The Gauge

The code for the OvalGauge and the LineChart is in a single method:

var lineChart = null;

define(["require", "exports", 'MindFusion.Common', 'Scripts/MindFusion.Charting', 'MindFusion.Gauges'], function (require, exports, MindFusion_Common_1, m, g) {
    "use strict";

Before the method we declare a global variable for the LineChart. We need to access it in the diagram file so it must have a global visibility.

The OvalGauge control is created using the id of the HTML Canvas:

var userCounter = g.OvalGauge.create($('#userCounter')[0], false);

We will use two Events – raised before the background was painted and before the pointer was painted – to customize how the gauge background and pointer look.

//use custom painting of the background and of the pointer
userCounter.addEventListener(g.Events.prepaintBackground, onGaugerepaintBackground.bind(this));
userCounter.addEventListener(g.Events.prepaintPointer, onPrepaintPointer.bind(this));

The gauge needs a scale – we create an OvalScale and set its min and max value:

var scale = new g.OvalScale(userCounter);

We will also set all three types of settings on the scale – MajorTickSettings, MiddleTickSettings and MinorTickSettings

//initialize the major settings
var majorSettings = scale.majorTickSettings;

A CustomInterval at the MajorTickSettings indicates a special range. We will use one to paint in red the portion on the scale that corresponds to the high amount of users:

 var interval = new g.CustomInterval();

Then we customize the MajorTickSettings, the MiddleTickSettings and MinorTickSettings:

//initialize the middle settings
var middleSettings = scale.middleTickSettings;

//initalize the minor settings
var minorSettings = scale.minorTickSettings;

The scale shows a Range: that is a visual indication of regions on the gauge. It is determined by its setMinValue and setMaxValue values and in our case we will show it on the whole gauge:

//add a range in gradient colors
var range = new g.Range();
range.setFill(g.Utils.createLinearGradient(320, [1, '#ce0000', 0.8, '#ce0000', 0.7, '#FFA500', 0.6, '#FFD700', 0.5, '#008000', 0, '#008000']));

That’s how we handle the PrepaintBackground event to draw custom background for the gauge:

//paint the background in gradient
function onGaugerepaintBackground(sender, args) {
   var context = args.getContext();
   var element = args.getElement();
   var size = sender.getSize();
   var ellipse = new g.Ellipse();
   args.paintVisualElement(ellipse, size);
   var ellipse = new g.Ellipse();
   ellipse.setFill(g.Utils.createLinearGradient(300, [0, '#808080', 0.2, '#808080', 0.8, '#909090', 1, '#909090']));
   ellipse.setMargin(new g.Thickness(0.015));
   args.paintVisualElement(ellipse, size);

The code that handles the prepaint pointer event is similar. The value of the Pointer is set this way:

//add some initial value

When the last chart values changes – each second – we update the pointer value:

var pointer = userCounter.scales[0].pointers[0];

III. The Chart

First we create the LineChart object from the Canvas that we have initialized in the HTML. We take the width and height of the control from its parent container:

var lineChartEl = document.getElementById('lineChart');
lineChartEl.width = lineChartEl.offsetParent.clientWidth;
lineChartEl.height = lineChartEl.offsetParent.clientHeight;
lineChart = new Controls.LineChart(lineChartEl);

The data for the line series is stored in 10 Series2D instances. For each of them we need a list with the X and Y values. The X-values are the same for all series, the Y-values are randomly generated numbers. All of them are instances of the List class:

var values1 = new Collections.List();
var values2 = new Collections.List();
var xValues = new Collections.List();
var xLabels = new Collections.List();

Here we fill the xValues list with numbers:

//initialize x-values and labels, generate sample data for the series
for (var i = 0; i &lt; 30; i++) {

The setXLabels method takes care of the custom labels at the X-axis. At each 3rd call, it removes the first three values and adds three new ones: one with the current time stamp and two more as empty strings.

if (d.getSeconds() % 3 == 0)
     //clear the first three values
     //if the count of the labels is more than 30
     if (removeFirst) {

       //add a label and two empty strings
       xLabels.add(d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds());

We create the Series2D instances and add them to the Series property of the line chart:

//the series for the chart
var series = new Collections.ObservableCollection(new Array(
    new Charting.Series2D(xValues, values1, xLabels),
    new Charting.Series2D(xValues, values2, null),
    new Charting.Series2D(xValues, values10, null)));

The xLables are assigned just to the first series, they will serve as labels source for the X-axis.To show them, we must first hide the coordinates and assign them to the xAxis:

lineChart.xAxis.labels = xLabels;
lineChart.showXCoordinates = false;

then we must “tell” the first series that its labels are used for the XAxis:

//tell the series that the labels are for the X-axis.
series.item(0).supportedLabels = m.MindFusion.Charting.LabelKinds.XAxisLabel;

We use the title property of a Series object to identify the series. That’s why we assign to them unique labels:

//series titles are important - we identify the series with them
for (var i = 0; i < 4; i++)
    series.item(i).title = "Client" + i;

for (var i = 0; i < 3; i++)
    series.item(i + 4).title ="Network" + i;

for (var i = 0; i < 3; i++)
    series.item(i + 7).title ="Data" + i;

Since it is going to be a long chart, we want a second Y-axis to appear to the right. That can be done by adding another YAxisRenderer with the same yAxis to the components rendered by default by the LineChart control. We add the new YAxisRenderer to a vertical StackPanel:

 var y2Stack = new m.MindFusion.Charting.Components.StackPanel();
 y2Stack.orientation = m.MindFusion.Charting.Components.Orientation.Vertical;
 y2Stack.gridRow = 0;
 //add the stack panel to the last grid column
 y2Stack.gridColumn = lineChart.chartPanel.columns.count() - 1;


The layout manager for a LineChart is a Grid panel. We add a new column to it, where the second Y-axis will be rendered. Then we add the StackPanel with the YAxisRenderer to this column. Next we add the yAxis and we specify that the plot is not to the left side of it:

//create the second Y-axis
var secondYAxis = new Charting.YAxisRenderer(lineChart.yAxis);
secondYAxis.plotLeftSide = false;

Then we customize the grid and trigger the timer that will update the data values at each second:

lineChart.gridType = Charting.GridType.Crossed;
lineChart.backColor = new Drawing.Color.fromArgb(230, 230, 230);
lineChart.theme.gridColor1 = Drawing.Color.fromArgb(1, 255, 255, 255);
lineChart.theme.gridColor2 = Drawing.Color.fromArgb(1, 255, 255, 255);
lineChart.theme.gridLineColor = Drawing.Color.fromArgb(0.5, 240, 240, 240);
//start the timer
setInterval(setTime, 1000);

Finally, let’s look at the styling of the series. We keep the brushes in a list. The colors for those brushes are stored in a list with lists – each one with three elements for the red, green and blue values of the color.

//the colors for the brushes
var brushes = new Collections.List();

var rgbColors = new Collections.List();
rgbColors.add(new Array(102, 154, 204));

What we actually do to show the graphics of the connections that are selected in the diagram is thicken the strokes for those line graphics and set the thickness to the rest to 0.15 to make them barely visible.

We do that by using the thicknesses property of the PerSeriesStyle class that we use for styling the chart.

lineChart.plot.seriesStyle = new Charting.PerSeriesStyle(brushes, brushes, thicknesses);

And here is how we create the thicknesses and the brushes:

//create brushes for the chart
var thicknesses = new Collections.List();
  for (var i = 0; i < 10; i++)
      var a = rgbColors.item(i);
      brushes.add(new Drawing.Brush(new Drawing.Color.fromArgb(a[0], a[1], a[2])));
      if (i == 5 || i == 8)

Only the 5th and 8th thickness are set to 3, the others are almost zero – enough to draw the silhouettes of the graphics.

And that’s all for this part I of the tutorial on how to build the client side of a sample server load monitor application in JavaScript. In part II we will look at the diagram control. You can run the sample from here:

Run the online server load monitor application

Here is the link to download the full source code for the application:

Download Source Code

You can also fork it from GitHub.

Find out more about the chart, gauge and diagram JavaScript libraries from their official pages on the MindFusion website.

Ticket Booking System (Continued)

In part I of the Ticket Booking System blog post we discussed the controls used in the software and how we generate and arrange the hall seats. Now let’s get deeper into the details on how we retrieve the data and how we customize the controls.

We use the Entity Framework and the Entity Data Model wizard to connect to our MS SQL database and retrieve the ticket data. Here is the model of the database:

Event Booking Software: MS SQL Database Model

Event Booking Software: MS SQL Database Model

I. The Database

We have a table for the event type (ballet, concert, opera etc.), a table for the events (Swan Lake ballet, Mozart concert, La Traviata oepra etc.), a table for the performances (an event with a date) and a table for the tickets that were sold. The performance table has a column for the base price of the tickets. The hall is divided into 3 sections according to the price of the tickets – the Performance table stores the price for the cheapest category. The other two categories are calculated according to the base price.

II. Events

We keep a class variable for the EventsTicketsEntities, which we initialize in the Form1 constructor:

public partial class Form1 : Form
   EventsTicketsEntities records;
   double basePrice;

   public Form1()
      records = new EventsTicketsEntities();

The events are instances of the Appointment class of the Calendar. Here is the method that we use to create the Appointment-s based on the data from the database:

private void loadEvents()

  List performances = records.Performances.ToList();     

  foreach (Performance p in performances)
      Appointment app = new Appointment();
      app.StartTime = (DateTime)p.Date;
      app.EndTime = app.StartTime.AddHours(2.0);           
      app.HeaderText = "";
      app.DescriptionText = p.Event.Title;
      app.Tag = p.Event.EventType_Id;
      app.Style.Brush = getBrush((int)app.Tag);


We read all records in the Performances table and create an Appointment for each one. The start date of the event is the field from the database. We add to it 2 hours as duration, otherwise the event wouldn’t show up. The brush of the Appointment depends on the type of the event. The appointment does not show any text, but the event title serves as a description. As a rule the calendar control renders an Appointment‘s description as a tooltip when the user hovers the item.

The schedule item description is rendered as a tooltip

The schedule item description is rendered as a tooltip

III. Hall Seats

In order to identify the location of a seat we assign an instance of the Seat structure as an Id to the ShapeNode that represents the seat.

public struct Seat
  public Seat (int row, int column)
     this.Row = row;
     this.Place = column;

  public int Row
     get; set; 

 public int Place
       get; set;


We also include a rowStart parameter in the CreateSection method. The parameter keeps track of the total count of seats being generated. This allows each seat to have a unique row number:


void CreateSection(int rowStart, int[] seatsPerRow,
    float topY, float seatWidth, float seatHeight,
     float xPadding, float yPadding, float arcRadius)
        seat.Id = new Seat(rowStart + r, s);
        seat.Tag = calcSeatCoeff((Seat)seat.Id);	


The Seat tag of the ShapeNode is calculated based on its location in the hall. It is the coefficient, which multiplied by the base price for this performance gives us the final price for this seat.

Each time a new performance is selected on the calendar, our application must refresh the seat info. Here is the method that takes care of the seat colors:

//clears the X sign at an occupied seat
private void updateSeats( double basePrice )
  foreach( var seat in diagram.Nodes)
     (seat as ShapeNode).Text = "";
     if (seat.Tag != null)
        seat.Brush = getSeatBrush(basePrice * (double)seat.Tag);

The method calculates the price of the seat and checks the color that corresponds to this price. Whenever a seat is clicked, the application marks it as selected. This is done by drawing an “X” as text on the ShapeNode using a large Font size:

Seat seatInfo = (Seat)seat.Id;
TICKETS_SOLD _ticket = new TICKETS_SOLD() { };
_ticket.Id = records.TICKETS_SOLD.ToList().Count;
_ticket.Performance_Id = (int)calendar.Tag;
_ticket.Row_Index = seatInfo.Row;
_ticket.Seat_Index = seatInfo.Place;

catch (DbEntityValidationException ex)
    seat.Text = "X";

We create a new TICKETS_SOLD record, which contains a unique Id for the sold ticket, an Id for the performance, and the location of the seat (row and column). There is something more to that. When the user tries to click on a seat that is already sold we want to warn him that it is not possible to buy the seat. This is done by having a special node that stays hidden and shows up for a few seconds only to warn the user:

private void generateOccupiedNode()
    float x = diagram.Bounds.Left + diagram.Bounds.Width / 2 - 50;
    float y = diagram.Bounds.Top + diagram.Bounds.Height / 2 - 30;

    RectangleF nodeBounds = new RectangleF(x, y, 100, 60);
    ShapeNode node = diagram.Factory.CreateShapeNode(nodeBounds);
    node.Brush = new MindFusion.Drawing.SolidBrush(Color.FromArgb(100, 206, 0, 0));            
    node.Font = new Font("Arial", 26);
    node.TextBrush = new MindFusion.Drawing.SolidBrush(Color.Black);
    node.Visible = false;
    node.Shape = Shapes.RoundRect;
    node.Id = "Occupied";


The seat is rendered in the middle of the diagram’s visible area and has a semi – transparent background. We use a timer to track the seconds when the node is displayed:

private void diagram_NodeClicked(object sender, NodeEventArgs e)
   ShapeNode seat = e.Node as ShapeNode;
   if(seat != null)
       if(seat.Text == "X")
           ShapeNode warning = (ShapeNode)diagram.FindNodeById("Occupied");

          if(warning != null)
             warning.Text = "This Seat is Occupied!";
             Timer timer = new Timer();
             timer.Interval = 2500;
             timer.Tick += Timer_Tick;
             warning.Visible = true;

We then find the node and make it invisible again:

private void Timer_Tick(object sender, EventArgs e)
    ShapeNode warning = (ShapeNode)diagram.FindNodeById("Occupied");
    warning.Visible = false;

With this we have covered the basic methods that build the Event Ticket Reservation Software. Here is the final version:

Event Booking System in WinForms

Event Booking System in WinForms

The full source code of the application together with the sample database is available for direct download from here:

Event Ticket Booking System – Download

The sample uses the Diagramming and Scheduling controls from the MindFusion WinForms Pack. If you have questions regarding the sample or the components do not hesitate to post them on the MindFusion discussion board.

A Poll Chart: A Stacked Bar Chart in Java Swing that Represents Results of a Survey – II

Here is a link to Part I: Overview of chart elements, the dashboard, plot and axes.

I. Bars Rendering

The bar graphics is rendered by a BarStackRenderer. It requires a collection of Series and we add four:

private ObservableList createSeries()
      // Important series
	BarSeries series1 = new BarSeries(
	Arrays.asList(40.0, 30.0, 52.0, 62.0),
	Arrays.asList("20%", "15%", "26%", "31%"),
	null /* no top labels */);


Each BarSeries has a list with the data, a list with the inner labels and no top labels. The BarStackRenderer renders in a single bar the values from the same index in each BarSeries e.g. the first bar renders the first double value in all BarSeries, the second bar renders the values on the second position in the series and so on. The BarRenderer itself has a few customizations:

barRenderer = new BarStackRenderer (createSeries());

Let’s not forget to add it to the Plot2D:



II. The Annotations

The labels at the X and Y axis are actually annotations – they are created by AnnotationRenderer instances. An AnnotationRenderer needs a collection of Series. For the Y-axis we use a SimpleSeries instance, which is created and used for the annotations and does not provide data for the bars:

private ObservableList createAxisLabels()
   return FXCollections.observableList(Arrays.asList(
	new SimpleSeries(null, null)
        	public String getLabel(int index, LabelKinds kind)
			return axisLabels[index];
		public double getValue(int index, int dimension) { return index; }
		public int getSize() { return axisLabels.length; }

		public int getDimensions() { return 1; }

		public EnumSet getSupportedLabels() {
	        	return EnumSet.of(LabelKinds.YAxisLabel);
		final String[] axisLabels = {
			"Accomodation", "University\nLocation", "Tuition\nPrice", "Quality of\nEducation" };

Here we indicate that this SimpleSeries provides labels for the YAxis with the getSupportedLabels override, which in our case returns LabelKinds.YAxisLabel. The label is returned by the getLabel method.

The annotations on the X-axis are rendered by a special class called CustomBarSeries. We implement the Series interface to return a set of predefined labels for each data value in this series:

public CustomBarSeries(List values, List innerLabels, List topLabels) {
	super(values, innerLabels, topLabels);
	this._values = values;
	double sum = 0;
	_stackedValues = new ArrayList(values.size());
	for(double val : values)
	   sum += val;
	this._innerLabels = innerLabels;

We also take into consideration that the values rendered by the bar chart where this class is used are stacked – so we sum them and return the summed value when asked:

public double getValue(int index, int dimension) { 
	if( dimension == 0)
	  return _stackedValues.get(index);
        return _values.get(index);			

Then we return the predefined label at the given position and :

public String getLabel(int index, LabelKinds kind)
		return _innerLabels.get(index);

	//else return the labels
	return axisLabels[index];
       final String[] axisLabels = {
		"Very Important", 
		"Somewhat\nImportant", "Slightly\nImportant", 
		"Not\nImportant" };

We create an instance of this CustomBarSeries and we assign it to the new AnnotationRenderer, that is responsible for the labels at the X-axis:

List sl = new ArrayList();
	sl.add(new CustomBarSeries(
	        Arrays.asList(25.0, 50.0, 50.0, 50.0),
	javafx.collections.ObservableList olss = FXCollections.observableList(sl);
	annotationRenderer1 = new AnnotationRenderer(olss);

Let’s not forget to bind the AnnotationRenderer to the X-axis:


Here is the final chart:

A stacked bar chart in Java Swing

Poll chart in Java Swing

That’s the end of this tutorial. Here is the link to download the full sample.

Download The Stacked Bar Chart in Java Sample

About Charting for Java: MindFusion.Charting for Java Swing is a multipurpose graphics library that lets you create and customize a large variety of chart types: bar, column, pie, doughnut, radar, polar etc., candlestick financial charts, gauges and dashboards with dynamic layout of their components. The library boasts a smart API which lets you combine and arrange multiple lots, axes, legends, images and other chart components. The chart appearance can be customized on multiple levels – from properties applied on a single element to global themes reused by all charts and series. Charts use a uniform Series interface for reading data and labels. You can implement the interface and create custom Series that matches your data source. Written in pure Java, this tool provides every type of Java Swing application with powerful charting capabilities. Read more about the component from here.

Ticket Booking System

In this blog post we will create a sample ticketing software that will allow users to select events and book tickets for them. We will use the MindFusion Diagramming and Scheduling components for WinForms. The tutorial is divided int two parts:

I. The Controls

We create a WinForms application in VisualStudio and add a new folder ‘Assemblies’ with the dll-s that we want to use. There we copy:

  • MindFusion.Common.dll
  • MindFusion.Common.WinForms.dll
  • MindFusion.Diagramming.dll
  • MindFusion.Diagramming.WinForms.dll
  • MindFusion.Licensing.dll
  • MindFusion.Scheduling.dll

Then we click on the Toolbox pane -> Choose Items -> Browse and we add the MindFusion.Diagramming.WinForms and MindFusion.Scheduling dll-s. They add a list of components, but we select the DiagramView and the Calendar controls and drop them onto the form. The DiagramView creates automatically the diagram instance that it renders.

II. The Hall Layout

The hall layout is rendered by the flowchart control. We use a special method that we’ve named CreateSection to create and arrange a section in the hall. The declaration of the method is:

void CreateSection(int[] seatsPerRow,
            float topY, float seatWidth, float seatHeight,
            float xPadding, float yPadding, float arcRadius)

We provide the method with an array of integers that indicate the number of seats on each row in the section. Then is the offset to the top and the size of each seat. The xPadding and yPadding arguments indicate the space between two adjacent seats. The last argument indicates how curved the row of seats is.

What the method generally does is calculate the location of each seat and generate a node with these coordinates and given size:

 float y = topY;
     for (int r = seatsPerRow.Length - 1; r &gt;= 0; r--)
           var c = new PointF(0, y + arcRadius);
           int seats = seatsPerRow[r];
           float rowWidth = seats * seatWidth + (seats - 1) * xPadding;
           float x = -rowWidth / 2;
           for (int s = 0; s  0)
                     float angle = 0;
                     float radius = 0;
                         c, new PointF(x, y), ref angle, ref radius);
                     adjustedY = c.Y - arcRadius * Math.Sin(angle * Math.PI / 180);
                     x, (float)adjustedY, seatWidth, seatHeight);
                     x += seatWidth + xPadding;
               y += seatHeight + yPadding;

The nodes are created with Factory.CreateShapeNode method which uses the Factory helper class of the diagram component. The CreateShapeNode method creates and adds the newly created nodes to the Nodes collection of the diagram.

III. The Calendar

The default settings of the Scheduling control give us exactly the month view with events we want to get. However we still need to add some customizations:

First, we won’t allow users to perform in-place edit of events on the calendar:

calendar.AllowInplaceEdit = false;

Then we will change the brushes for the calendar items and will hide the clock icons that appear at the header of events:

calendar.ItemSettings.Size = 10;            
calendar.ItemSettings.ShowClocks = MindFusion.Scheduling.WinForms.ShowClocks.Never;
calendar.ItemSettings.Style.Brush = new MindFusion.Drawing.SolidBrush (Color.FromArgb(102, 154, 204));
calendar.ItemSettings.Style.BorderBottomColor = calendar.ItemSettings.Style.BorderLeftColor =
                calendar.ItemSettings.Style.BorderRightColor = calendar.ItemSettings.Style.BorderTopColor = Color.FromArgb(192, 192, 192);
calendar.ItemSettings.SelectedItemStyle.Brush = new MindFusion.Drawing.SolidBrush (Color.FromArgb(206, 0, 0));
calendar.Selection.SelectedElementsStyle.Brush = new MindFusion.Drawing.SolidBrush(Color.FromArgb(224, 233, 233));

Now let’s create a few items:

Appointment event1 = new Appointment();
event1.StartTime = new DateTime(2017, 5, 2, 16, 0, 0);
event1.EndTime = new DateTime(2017, 5, 2, 18, 30, 0);
event1.HeaderText = "";
event1.DescriptionText = "Swan Lake";
event1.Tag = EventType.Ballet;
event1.Style.Brush = new MindFusion.Drawing.SolidBrush(Color.FromArgb(102, 154, 204));


Our Appointment-s have a start and end time, description, brush according to the EventType and tag that indicates the type of event that is rendered. It would be nice to have tooltips that provide details about the event:

calendar.ShowToolTips = true;

This turns on tooltips on all calendar items. We want tooltips just on our events so we use the TooltipDisplaying event to hide the tooltips on items that are not events:

calendar.TooltipDisplaying += Calendar_TooltipDisplaying;


private void Calendar_TooltipDisplaying(object sender, MindFusion.Scheduling.WinForms.TooltipEventArgs e)
  if(e.Element.GetType() != typeof(Appointment))
       e.Tooltip = "";

Here is a screenshot of the event ticketing system so far:

Event Ticket System with MindFusion WinForms Controls

Event Ticket System with MindFusion WinForms Controls

A download of the project with all necessary dll-s is available from this link:

Ticket Booking System in WinForms

The Scheduling for WinForms and Diagramming for WinForms components are part of MindFusion WinForms control suite – the perfect set of tools to help you build any type of WinForms software fast and easy. Find out more about MindFusion WinForms pack here.

A Class Diagram Tool in Java with the Flowchart Library – II

This is the second part of MindFusion step-by-step tutorial on how to create a Java application that reads the contents of a *.jar file and renders class diagram of its API. In the previous blog post we looked at the UI elements that build the application – the UI, the legend panel, the diagram elements. Now we continue with reading the class data and building the class diagram.

I. Reading the Data

The data that we need – the name of the API member, its fields, its type – enum, class, interface as well inherited classes – is stored in a helper class that we’ve created for the purpose and that is called It is a simple class that does nothing else than storing data:

 public MemberInfo( String name, String fullName )
    { = name;
        this.fullName = fullName;

        //lists for the methods, fields and constructors.
        methods = new ArrayList();
        fields = new ArrayList();
        constructors = new ArrayList();
        inheritsFrom = "";
        packageName = "";
        isInterface = false;
        isEnum = false;

There is a list with the methods, fields and constructors, as well properties for the name of the package, the class this class inherits from as well boolean values that indicate if this is an enum or interface.

For reading the data we use only classes and methods from the official Java packages – no third party tools or libraries:

            //try to open the jar
            JarFile jarFile = new JarFile(pathToJar);

            //explore the elements found in the *.jar.
            Enumeration e = jarFile.entries();

            URL[] urls = {new URL("jar:file:" + pathToJar + "!/")};
            URLClassLoader cl = URLClassLoader.newInstance(urls);
            //if a class is found - read its data
            while (e.hasMoreElements())
                JarEntry je = e.nextElement();
                if (je.isDirectory() || !je.getName().endsWith (".class")) {
                // -6 because of .class file extension.
                String className = je.getName().substring(0, je.getName().length() - 6);
                className = className.replace('/', '.');

In a cycle we read all classes in the jar, parse the data we are interested in and filter data that is no relevant to us – private methods, abstract classes etc. The data we acquire for each class is stored in a new MemberInfo object that we add to a collection.

II. Diagram Elements

The diagram elements that we use to render each class are TableNode-s. We use the caption field to show the name of the class. In addition, we use the capabilities of the Java diagram library to render formatted text and add to the caption the name of the package – drawn on a new line.

            //create the TableNode
            TableNode _table = diagram.getFactory().createTableNode(10, 10, 5, 5, 2, info.memberCount());
            //set the name of the member and the package as table caption.
            String caption = "<b>" + info.getName() + "</b>";
            if(info.getPackageName().length() &gt; 0)
                caption += "\n" + info.getPackageName();
            //center the caption
            _table.setCaptionFormat((new TextFormat(Align.Center, Align.Center)));
            //increase the default caption height

It is important to note here that we add an identifier for each table – this will help us find the right TableNode when we later create connections:


By default TableNode-s are drawn with blue. We check if the current object is enum or interface and change the color scheme accordingly:

            //add enums to the list and paint them green
            if(info.isEnum()) {
                _table.setBrush(new SolidBrush(new Color((int) 210, (int) 250, (int) 208)));
            }//add interfaces to the list and paint them yellow
            else if(info.isInterface()) {
                _table.setBrush(new SolidBrush(new Color((int) 250, (int) 235, (int) 140)));
            else //the class nodes are blue
                _table.setBrush(new SolidBrush(new Color((int)197, (int)223, (int)238)));

Then we add table rows for the constructors, methods and fields. Each row has a cell for the image and for the definition of the member:

            //fill the first cells with data for the constructors.
            for (String constructor : info.getConstructors())
                _table.getCell(0, index).setImage(constructorImage);
                _table.getCell(1, index).setText(constructor);

Finally, we look at all MemberInfo objects and draw DiagramLink between each class and the class it derives from, if any:

  for (MemberInfo info : membersList)
                DiagramNode node = diagram.findNodeById (info.getFullName());
                DiagramNode parent = diagram.findNodeById( info.getParent());

                //add inheritance link
                if(node != null &amp;&amp; parent != null)
                    DiagramLink link = diagram.getFactory ().createDiagramLink(node, parent);


III. Containers

Interfaces and enums are drawn in groups at the end of the TableNode-s for classes. This is done using ContainerNode-s. First, we calculate the dimensions of the ContainerNode by measuring all TableNode-s that must fit into it:

            //calculate the location of the node
            int side = (int)Math.ceil(Math.sqrt(tables.size()));
            int rows = (int)Math.ceil((double)tables.size() / side);
            double singleWidth = tables.get(0).getBounds().getWidth();
            double width = 5 * (side + 1) * coef + singleWidth * side;
            double height = (5 * (rows + 1) + 5) * coef;

            double[] rowHeights = new double[rows];
            for (int i = 0; i &lt; tables.size(); i++)
                rowHeights[i / side] = Math.max(tables.get(i).getBounds().getHeight(), rowHeights[i / side]);

            for (double h : rowHeights)
                height += h;

            //initialize the container
            ContainerNode b = diagram.getFactory().createContainerNode (0, 0, width, height);

Here the variable tables is a list with the TableNode-s that must fit into the container. After the ContainerNode is created, the tables must be added and positioned in it:

            int index = 0;
            for (TableNode e : tables)

                double x = (index % side) * (5 + singleWidth);
                double y = 0;

                for (int r = 0; r &lt; index / side; r++)
                    y += 5 * coef + rowHeights[r];

                //adjust the size of the node
                e.setBounds(new Rectangle2D.Double(x + 5 * coef, y + 10 * coef,                   e.getBounds().getWidth(), e.getBounds ().getHeight()));


Finally we adjust the appearance of the ContainerNode to make it look better and in line with the TableNode-s:

            //customize the container
            b.setCaptionFormat((new TextFormat(Align.Center,  Align.Center)));
            b.setHandlesStyle( HandlesStyle.HatchHandles3 );
            b.setFont(new Font("Verdana", Font.BOLD, 4));
            //no shadow

It’s important to note that the bounds of the container must be updated for the changes to take effect:

            //update the container size.

IV. Diagram Layout

The last part of the application deals with diagram layout. This is very important because in the common scenario we expect to read *.jar files with tens of classes and proper visual arrangement of the flowchart is the key to its usability.

We decide to use the TreeLayout, which is meant exactly to arrange diagrams with nodes on several levels as we expect the class hierarchies to be. It is easy to apply the layout – we create an instance of it and after setting some initial customization we call its arrange method:

         TreeLayout layout = new TreeLayout();

        //the layout type is Centered
        //allow reversed links
        //the type of links will be cascading
        //specify the distance between levels of tree nodes
        //groups must be preserved.


It is easy to understand the type of the settings we’ve used – thanks to the self-explanatory names of the layout class you can see that we specify that the TreeLayout will be centered, the links will be reversed, then we change the link style and the distance between levels. Finally, we specify that the layout of groups must be preserved.

The interesting part is at the end. We must find the ContainerNode-s with the enums and interfaces and move them to the end of the diagram. Here is how:

        // Place enums and delegates at the end
        DiagramNode enums = diagram.findNode(":enums");
        DiagramNode delegates = diagram.findNode(":interfaces");

        double x = 0;
        //calculate the location of each node to find out the last one
        for (DiagramNode node : diagram.getNodes())
        	if (node instanceof TableNode)
        		x = Math.max(x, node.getBounds().getX() +  node.getBounds().getWidth());

        //move enums to the right of the last class node.
        if (enums != null)
            enums.moveTo((float)x + 5f, (float)5);
            x = enums.getBounds().getX() + enums.getBounds().getWidth ();

        if (delegates != null)
            delegates.moveTo((float)x + 5, 5);

We cycle through each TableNode and always move the containers to the end of the rightmost TableNode that we find. Let’s not forget to resize the diagram after we are done:


With this our application is ready and we test it with an arbitrary *.jar file. Here is the result:

Class Diagram Application in Java

Class Diagram Application in Java

You can download the complete source code of the sample from here:

Download the Class Diagram Tool in Java Application

MindFusion support team welcomes your questions about the Java diagram library or any other of our programming tools at the discussion board or per e-mail at

About Diagramming for Java Swing: MindFusion.Diagramming for Java Swing provides your Java application with all necessary functionality to create and customize a diagram. The library is very easy to integrate and program. There are numerous utility methods, rich event set, more than 100 predefined shapes. The tool supports a variety of ways to render or export the diagram, advanced node types like TreeView nodes, hierarchical nodes, tables, container nodes and many more. There are 15 automatic layouts, various input / output options and fully customizable appearance. A detailed list with JDiagram’s features is uploaded here. You can check the online demo to see some of the functionality implemented.

Diagramming for Java Swing is royalty free, there are no distribution fees. Licenses depend on the count of developers using the tool – check here the prices.

Collaborative drawing with MindFusion.Diagramming and SignalR

In this post we’ll show how to use the ASP.NET MVC diagram library and SignalR to implement collaborative drawing of diagrams. This can be useful in visual planning tools where users work together on a task, such as project management or mind-mapping applications.

The complete sample project is available here –

Start by creating an ASP.NET MVC application in Visual Studio. Open Tools -> Library Package Manager -> Package Manager Console and install the MindFusion.Diagramming.Mvc package –

Install-Package MindFusion.Diagramming.Mvc 

While we are there, also install the SignalR package –

install-package Microsoft.AspNet.SignalR

From the project’s context menu, Add submenu, select OWIN startup class and add SignalR to the OWIN pipeline by calling –


Now lets add a diagram view to the home page at Views/Home/Index.cshtml, load the necessary script files and wire up diagram event handlers that will send change notifications to the hub –

@using MindFusion.Diagramming
@using MindFusion.Diagramming.Mvc

    var diagView = new DiagramView("diagramView")

    diagView.Diagram.DefaultShape = Shapes.Ellipse;

@Html.DiagramView(diagView, new { style = "width:700px; height:600px;" })

@section scripts

The hub will synchronize operations done on the diagram by one client by sending a notification to all other connected clients. From the project context menu add a SignalR hub class, naming it DiagramHub. The model class we’ll use to describe node changes looks like this –

public class NodeModel
    public double X { get; set; }

    public double Y { get; set; }

    public double Width { get; set; }

    public double Height { get; set; }

    public string Id { get; set; }

    public string Text { get; set; }

Add these three methods to the hub class to synchronize node creation, move, resize and edit-text operations –

public void NodeCreated(NodeModel clientModel)
public void NodeModified(NodeModel clientModel)
public void NodeTextEdited(NodeModel clientModel)

The diagram event handlers in MindMap.js fill in the model objects and call respective hub methods –

function onNodeCreated(s, e)
    var hubId = $; = hubId + s.getItems().length;

    var r = e.node.bounds;
    var model =
        x: r.x,
        y: r.y,
        width: r.width,
        height: r.height

function onNodeModified(s, e)
    var r = e.node.bounds;
    var model =
        x: r.x,
        y: r.y,
        width: r.width,
        height: r.height

function onNodeTextEdited(s, e)
    var model =
        text: e.getNewText()

Handle notifications sent from server to clients by updating the diagram from received model objects –

$(function ()
    diagramHub = $.connection.diagramHub;
    diagramHub.client.nodeCreated = function (model)
        var node = diagram.factory.createShapeNode(
            model.x, model.y, model.width, model.height); =;
    diagramHub.client.nodeModified = function (model)
        var node = findNode(;
            new MindFusion.Drawing.Rect(
                model.x, model.y, model.width, model.height),
    diagramHub.client.nodeTextEdited = function (model)
        var node = findNode(;

Finally add these helper functions for finding items and storing a global diagram reference –

function onDiagramLoaded(s, e)
    diagram = s;

function findNode(id)
    for (var i = 0; i < diagram.nodes.length; i++)
        var node = diagram.nodes[i];
        if (id ==
            return node;
    return null;

function findLink(id)
    for (var i = 0; i < diagram.links.length; i++)
        var link = diagram.links[i];
        if (id ==
            return link;
    return null;

Start several copies of the application in separate browser instances on your system (or even on different machines if you publish it on IIS or Azure). Now start drawing nodes, moving them or editing their text – changes done on the diagram in one browser will be immediately reflected in all other browsers connected to the hub. However we aren’t yet synchronizing link operations; lets fix that –

public class LinkModel
    public string Id { get; set; }

    public string OriginId { get; set; }

    public string DestinationId { get; set; }

    public string Text { get; set; }

Add following hub methods in server class –

public void LinkCreated(LinkModel clientModel)
public void LinkModified(LinkModel clientModel)
public void LinkTextEdited(LinkModel clientModel)

Call them from respective JavaScript handlers of diagram link events –

function onLinkCreated(s, e)
    var hubId = $; = hubId + s.getItems().length;

    var model =

function onLinkModified(s, e)
    var hubId = $;
    var model =

function onLinkTextEdited(s, e)
    var model =
        text: e.getNewText()

Handle link-related client notifications by creating or modifying links –

diagramHub.client.linkCreated = function (model)
    var link = diagram.factory.createDiagramLink(
        findNode(model.originId), findNode(model.destinationId)); =;
diagramHub.client.linkModified = function (model)
    var link = findLink(;
diagramHub.client.linkTextEdited = function (model)
    var link = findLink(;

Now the application will also synchronize link operations across all connected clients. Here’s a small diagram synchronized between three different browsers –
collaborative mind map

The sample above uses MindFusion’s ASP.NET MVC API. Code for other frameworks will look similar as MindFusion maintains same diagramming model for multiple platforms. You can download the trial version of any MindFusion.Diagramming component from this page.


A Class Diagram Tool in Java with the Flowchart Library – I

This blog post is a step-by-step guide on how to create a tool that parses *.jar files and builds the class hierarchy. The visualization of the diagram is performed by MindFusion Java Swing Diagram library.

Here is an image of the final application:

Class Library Tool in Java

Class Library Tool in Java

In part one we will take a look at the controls that build the user interface for the application.

I. UI Controls

We will use three controls from the diagram library:

    private Diagram diagram;
    private DiagramView diagramView;
    private ZoomControl zoomer;

One JScrollPane:

private JScrollPane _scrollPane;

and a JPanel for the legend and a JMenuBar.

    JPanel controlsPanel = new JPanel();
    JMenuBar menuBar;

Those controls build the user interface. At the top is the menu bar with menus for handling the *.jar files. In the center is a scrollable area that contains the diagram. Right to it is a zoom control. At the bottom is the panel with the legend – images and text that explain the colors and symbols on the class diagram.

II. The Diagram Controls

The three diagram controls are the Diagram, the DiagramView and the ZoomControl. The diagram needs a diagramView to render itself onto. The diagramView users a scrollPane to provide scroll functionality for the flowchart. The zoomControl is a typical Java Swing control, we set a few customization options on it to make it pass the layout of our application.

       //diagram initialization
        diagram = new Diagram();

We set auto resize for the diagram and assign it to the diagramView:

        //initialize a diagramView that will render the diagram.
        diagramView = new DiagramView(diagram);

The scrollPane is initialized with the diagramView and scrolls automatically when the view is bigger than the available size:

         //use a scroll pane to host large diagrams
        _scrollPane = new JScrollPane(diagramView);

The zoomControl is also attached to the diagramView. It’s important that we set its Dimension, the width will be used by the Java layout manager to calculate the available space for it on the application.

        //provide a zoomer for the diagram
        zoomer = new ZoomControl();
        zoomer.setPreferredSize(new Dimension(70, 50));

The arrangement of the controls in the JFrame is done with the BorderLayout. It’s important that we set the layout before we start adding the controls:

     getContentPane().setLayout(new BorderLayout());
     this.add(zoomer, BorderLayout.EAST);
     this.add(createLegendPanel(), BorderLayout.SOUTH);

The zoomer is to the right, the legend panel is at the bottom. The last control that we add is the scrollPane with the diagram, we align it to the center, which means that all the available space would be allocated to her.

     this.add(_scrollPane, BorderLayout.CENTER);

Finally, we create the menu bar.


III. The Legend Panel

The legend panel is a JPanel with BoxLayout of type “LINE_AXIS”.

        JPanel controlsPanel = new JPanel();
        controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.LINE_AXIS));
        controlsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

The legend items are ImageIcon-s – for each symbol in the diagram there’s an icon. We have also created images for the colors of the diagram. Each icon is rendered with explanation label.

Generally, each item on the LegendPanel is initialized like this:

        //create labels for each item on the legend
        JLabel label = new JLabel("Constructor", constructorIcon, JLabel.CENTER);
        controlsPanel.add(Box.createRigidArea(new Dimension(10, 0)));

The layout distributes evenly the available space between the items and we get an easy-to-read legend at the bottom of the application.

IV. The Menu

The menu at the top is implemented as a JMenuBar, which uses mnemonic keys and accelerators to grant access to the menu items with keyboard shortcuts. The only menu item and submenu items currently present are File -> Open jar.

        //Build the first menu.
        menu = new JMenu("File");
                "File operations");

The “Open jar” command uses action listener, which brings up the Open File diagolg. This is a JFileChooser, which filters all files except *.jar files.

     //the method that handles events
    public void actionPerformed(ActionEvent e)
        //identify the command
        if ("open_jar".equals(e.getActionCommand())) {

            //a list with MemberInfo objects that hold class info
            ArrayList membersList = new ArrayList();
            fileChooser = new JFileChooser();

            //set the default directory to this file's directory

            //filter only *.jar files
            FileFilter filter = new FileNameExtensionFilter(null, "jar");

If the method confirms that the user has selected a valid jar, the path to the file is provided to the method that reads and parses the jar, which will be topic for the second part of this tutorial.

The whole sample is available for direct download from this link:

Download the Class Diagram Tool in Java Application

MindFusion support team welcomes your questions about the Java diagram library or any other of our programming tools at the discussion board or per e-mail at

About Diagramming for Java Swing: MindFusion.Diagramming for Java Swing provides your Java application with all necessary functionality to create and customize a diagram. The library is very easy to integrate and program. There are numerous utility methods, rich event set, more than 100 predefined shapes. The tool supports a variety of ways to render or export the diagram, advanced node types like TreeView nodes, hierarchical nodes, tables, container nodes and many more. There are 15 automatic layouts, various input / output options and fully customizable appearance. A detailed list with JDiagram’s features is uploaded here. You can check the online demo to see some of the functionality implemented.

Diagramming for Java Swing is royalty free, there are no distribution fees. Licenses depend on the count of developers using the tool – check here the prices.