Creating Default Anchors for custom User Symbols
This article describes how to create default anchors on custom user symbols with ILOG Diagrammer for .NET.
First, we need to make sure that we know what anchors and user symbols are. Let’s briefly define these two notions:
- A user symbol is a graphic object built with the ILOG Diagrammer for .NET Diagram Designer. This designer, fully integrated into Visual Studio, is a WYSIWYG editor that produces C# or VB.NET code. Using this editor, you can build complex interactive symbols by assembling available shapes and symbols.
- An anchor is a point on a graphic object where a link can be connected. Each graphic object has a collection of anchors on which it’s possible to connect links.
Now that we know what we’re talking about, we can imagine the following scenario: A user has created a custom user symbol using our designer, and he wants to specify the exact location where links could be connected to this symbol. For example, when designing an electrical symbol, one need to specify that wires can be connected to the component terminals. Here is an example of such a symbol:
Let’s create this symbol in Visual Studio:
- Launch Visual Studio 2005 or 2008.
- Select File->New->Project->ILOG Diagrammer Symbol Library and name the project ElectricalSymbolsLibrary.
- In the solution explorer, right click on the project, and choose Add New Item->UserSymbol (ILOG Diagrammer) and name the symbol Transistor.cs.
- Choose Diagrammer->Import File and import transistor.ivn after extracting it from the following archive. Click Yes in the dialog asking if you want to import the file as vector graphics.
You should now have your transistor symbol visible in the designer:
Let’s now use this new symbol in a diagram so that we can try to connect links to it. To add a diagram to the project, right-click in the solution explorer on the project and choose Add->New Item->Diagram (ILOG Diagrammer). Compile the project (Build->Build Solution) to update the toolbox. Open the toolbox, your new transistor symbol should be available:
Drag a transistor symbol from the toolbox to the design surface. Repeat the operation to have several symbols in the diagram. You should now have something like this:
Let’s now try to connect the transistors together by creating links between them. Open the toolbox and locate the Connectors tab. Click on one of the links available in the tab, then move the mouse over one of the transistors. The anchors where the link can be connected are highlighted:
We can see that by default a user symbol has four anchors, each one located at the middle of the bounding box sides. Obviously, that’s not what we want here. One way to get the right anchors is to edit each transistor instance by modifying its anchors collection: After removing the default anchors (set the UseDefaultAnchors property to false), add three BoundsAnchor to the anchors collection (right-click on the transistor, and choose Edit Anchors…). Then, we need to move each anchor at the desired location. To do this, choose the Edit Anchors (
) icon from the Diagrammer toolbar and move the mouse over the transistor. It’s now possible to move the three anchors previously added to their right location by clicking each anchor and dragging it to its desired location. Then, if we go back to the link mode connection by clicking on a link in the toolbox Connectors tab, we can see by passing the mouse over it, that our transitor has now its anchors placed at their right location:
The main drawbacks of this approach are:
- The anchors are not part of the symbol itself, since they have been added after the symbol creation. If you create an instance of this symbol by code, your new anchors will not be available.
- We’re not using the default anchors feature of the graphic objects, and thus, anchors are created and added to the component model even though there are no links connected to them. This can be a performance issue if you have many objects with many anchors.
An alternative to this approach is to define the default anchors directly when designing the transistor. How can we do this ? Let’s go back to the designer view of our transistor by double clicking the Transistor.cs file in the Solution Explorer. The trick is that all the real anchors (not the default ones) defined in the sub objects of our transistor will be exposed as default anchors for our user symbol. Thus, we simply need to add three anchors on the sub objects composing our transistor. Let’s see how to do it.
If you look at the Document Outline view in Visual Studio, you will see that our transistor is composed of several shapes:
The interesting objects are the polyline1, polyline2 and line1 objects. On each one, we will add a new PolyPointsAnchor, which is a type of anchor whose location is bound to a vertex of a polyline object. Right-click on the polyline1 object in the designer view, and choose Edit Anchors. Add a PolyPointsAnchor and click the OK button. Repeat the operation for the polyline2 and line1 objects. Note that in our example, the anchors are located on the first vertex of each polyline, which is the default for PolyPointsAnchor objects.
Let’s compile the project and switch back to our diagram view to test our transistor by double clicking the Diagram1.cs file in the Solution Explorer. To start with a fresh diagram, remove existing instances of the transistors. Then drag and drop a new transistor from the toolbox and try to connect a link to see that the highlighted anchors are the expected ones:
We’ve successfully changed the default anchors of our transistor, without having to write a single line of code.
Tags: connect, default anchors, Diagram, link, user symbol, Visual Studio
















October 29th, 2008 at 10:24 pm
This is helpful. Seems like the number of connections setting doesn’t work; I set it to ‘1′ yet I can drag and connect many lines to a single anchor.
Also, could you do in another blog how to programatically navigate to ‘connecting’ objects by using the anchors? This electrical widget would actually be a great example. Let’s assume the transistor is connected to ground on one end, power on another and a diode on the the third. Visually we can see that these items are connected, but how would I tell via code that the transitor object is connected to a ground object on one end, and a diode on another?
These little examples like this do wonders for me. Thanks again!
October 30th, 2008 at 11:44 am
There’s indeed a bug here, because the number of connections is not taken into account in this particular case. Thanks for pointing it out. I’ll fix this problem in a patch.