<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |
<html> | |
<head> | |
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"> | |
<title>Connection anchors</title> | |
<link href="../book.css" rel="Stylesheet" type="text/css"> | |
<link href="../code.css" rel="Stylesheet" type="text/css"> | |
</head> | |
<body> | |
<h1>Connection Anchors</h1> | |
<p>The ends of connections are placed with the help of anchors. An anchor is a fixed | |
or calculated location, usually associated with a graphical representation. The | |
user must provide the source and target anchor, typically by dragging from and dropping | |
onto the graphical representation of the anchors. The connection points can then | |
be calculated automatically.</p> | |
<h2>Different Types of Connection Anchors</h2> | |
<p>Currently the following different types of connection anchors are supported:</p> | |
<h3>Chop Box Anchors</h3> | |
<p>They can be created calling | |
<a href="../../../javadoc/org/eclipse/graphiti/services/IPeCreateService.html#createChopboxAnchor(org.eclipse.graphiti.mm.pictograms.AnchorContainer)"> | |
IPeCreateService.createChopboxAnchor</a>. A chop box anchor is located virtually in the center of | |
the parent. However, the connection line does not end at the center of the parent | |
but already at the intersection-point with the parent boundaries. This means especially, | |
that the intersection-point is re-calculated not only when the parents size or location | |
changes, but also when the direction of the connection changes. Chop box anchors | |
are the only anchors which do not need a graphics algorithm.</p> | |
<p> </p> | |
<p><img alt="" height="158" src="visio/anchor-chopbox.png" width="217"></p> | |
<p><strong>Figure: Chop box anchor (always pointing to the center)</strong></p> | |
<p> </p> | |
<h3>Box Relative Anchors</h3> | |
<p>They can be created calling | |
<a href="../../../javadoc/org/eclipse/graphiti/services/IPeCreateService.html#createBoxRelativeAnchor(org.eclipse.graphiti.mm.pictograms.AnchorContainer)"> | |
IPeCreateService.createBoxRelativeAnchor</a>. A box relative anchor is located relative to the size | |
and location of the parent. The x/y-coordinates are defined as percentage values | |
between 0.0 and 1.0. This allows for example to locate an anchor always at the middle-right | |
border of the parent (x=1.0, y=0.5). The location of the anchor is re-calculated | |
whenever the parents size or location changes.</p> | |
<p> </p> | |
<p><img alt="" height="152" src="visio/anchor-box-relative.png" width="209"></p> | |
<p><strong>Figure: Box relative anchor (on middle-right border outside of shape)</strong></p> | |
<p> </p> | |
<h3>Fix Point Anchors</h3> | |
<p>They can be created calling | |
<a href="../../../javadoc/org/eclipse/graphiti/services/IPeCreateService.html#createFixPointAnchor(org.eclipse.graphiti.mm.pictograms.AnchorContainer)"> | |
IPeCreateService.createFixPointAnchor</a>. A fix point anchor is located at fixed x/y-coordinates (relative | |
to the parent).</p> | |
<h2><span lang="EN-US">Connection Anchor Points Explained</span></h2> | |
<p>Every connection has two connection anchors which provide the points where the | |
connection starts/ends. Additionally the connection can have multiple bend-points | |
in between. An anchor has two points: the “reference-point” is the logical end-point | |
of the connection and the “location” is the visible end-point of the connection. | |
</p> | |
<p>The following sketch explains those points for a chop box anchor.</p> | |
<p> </p> | |
<p><img alt="" height="154" src="visio/anchor-points.gif" width="444"></p> | |
<p><strong>Figure: Points of a chop box anchor </strong></p> | |
<p> </p> | |
<p>The reference-point (R) of the chop box anchor is the middle of the figure, because | |
this is the point where the connection logically ends. The reference-point changes | |
if the figure changes, but it does not change depending on the connection.</p> | |
<p>We define the point (O) as the other point where the connection logically ends. | |
If the connection has bend-points, then (O) is the bend-point (B) next to the anchor, | |
otherwise (O) is the reference-point (R) of the other connection anchor. This means, | |
that logically the connection is a line from (R) to (O).</p> | |
<p>But a line drawn from (R) to (O) would overlap the figure. To avoid this overlap | |
the location (L) of an anchor is calculated from (R) and (O) as the visible end-point | |
of the connection. In case of the chop box anchor (L) is the intersection between | |
the line (R - O) and the border of the figure.</p> | |
<p>The same algorithm is applied for all other anchor types, although often the | |
calculation is much simpler. For example in a fix point anchor the reference-point | |
(R) is the point the anchor was initialized with and the location (L) is identical | |
to (R).</p> | |
<p class="Note">Note: All anchors have a graphical representation and connections | |
are starting and ending virtually in the center of the graphical representation. | |
But how can it be achieved that connections are starting precisely from the border of | |
this graphical representation? For this purpose define a teh anchor location there and use | |
<a href="../../../javadoc/org/eclipse/graphiti/mm/pictograms/AdvancedAnchor.html#setUseAnchorLocationAsConnectionEndpoint(boolean)"> | |
setUseAnchorLocationAsConnectionEndpoint</a>. At the end of this chapter is | |
an example for this use case.</p> | |
<h2>Creating Connections with Drag & Drop from Anchors</h2> | |
<p> </p> | |
<p> | |
<img alt="" height="154" src="visio/anchor-box-relative-example.png" width="203"></p> | |
<p><strong>Figure: Box relative anchor with graphical representation inside | |
border of shape</strong></p> | |
<p> </p> | |
<p>If the user shall be able to create connections directly via drag & drop from | |
an anchor without the connection-tool, this can be implemented by so called drag | |
& drop features. This does not work for chop box anchors, because they have no visible | |
anchor which can be dragged.</p> | |
<p>To offer drag & drop functionality from anchors we have to overwrite the | |
<a href="../../../javadoc/org/eclipse/graphiti/features/IFeatureProvider.html#getDragAndDropFeatures(org.eclipse.graphiti.features.context.IPictogramElementContext)"> | |
getDragAndDropFeatures</a> method of the feature provider.</p> | |
<p>If this method returns exactly one feature it will be executed directly on drop | |
(if applicable). If you provide more than one feature the user will be presented | |
a popup menu on drop showing all applicable features (applicable means | |
<a href="../../../javadoc/org/eclipse/graphiti/features/IFeature.html#canExecute(org.eclipse.graphiti.features.context.IContext)"> | |
canExecute</a> returns true). The user can select the desired feature which will | |
be executed then.</p> | |
<p>In this example we first add a box relative anchor on the middle-right border | |
of a EClass. Then we support drag & drop from that anchor to another EClass, which | |
will create a new connection.</p> | |
<p>First the box relative anchors have to be created at the end of the add-method of | |
the <span class="inlinecode">TutorialAddEClassFeature</span>, as explained in the | |
following code snippet. Note, that the previously created chop box anchor (see | |
<a href="create-connection-feature.htm">create connection feature</a>) remains, | |
so that the EClass has then two anchors:</p> | |
<!-- Begin code ------------------------------------------------------------------------------- --> | |
<p> </p> | |
<div class="literallayout"> | |
<div class="incode"> | |
<p class="code"><span class="keyword">public </span>PictogramElement add(IAddContext | |
context) {<br> <br> | |
<span class="comment">// ... EXISTING CODING ...</span><br> <br> | |
<span class="comment">// add a chopbox anchor to the shape</span><br> | |
peCreateService.createChopboxAnchor(containerShape);<br> <br> | |
<span class="comment">// create an additional box relative anchor at middle-right</span><br> | |
<span class="keyword">final </span>BoxRelativeAnchor boxAnchor = <br> | |
peCreateService.createBoxRelativeAnchor(containerShape);<br> | |
<br> boxAnchor.setRelativeWidth(1.0);<br> | |
boxAnchor.setRelativeHeight(0.38); <span class="comment">//use golden section </span><br> | |
| |
boxAnchor.setReferencedGraphicsAlgorithm(roundedRectangle);<br><br> | |
<span class="comment">// assign a rectangle graphics algorithm for the | |
box relative anchor<br> // note, that the | |
rectangle is inside the border of the rectangle shape</span><br> | |
<span class="keyword"> final</span> Rectangle rectangle = | |
gaService.createPlainRectangle(boxAnchor);<br> | |
rectangle.setForeground(manageColor(<span class="string"><em>E_CLASS_FOREGROUND</em></span>));<br> | |
rectangle.setBackground(manageColor(<span class="string"><em>E_CLASS_BACKGROUND</em></span>));<br> | |
rectangle.setLineWidth(2);<br> | |
gaService.setLocationAndSize(rectangle, -12, -6, 12, 12);<br> | |
<br> <span class="comment">// call the layout | |
feature</span><br> layoutPictogramElement(containerShape);<br> <br> | |
<span class="keyword">return </span>containerShape;<br>} </p> | |
</div> | |
</div> | |
<p> </p> | |
<!-- End code ------------------------------------------------------------------------------- --> | |
<p>Additionally the feature provider has to deliver the drag & drop features (overwrite | |
the method | |
<a href="../../../javadoc/org/eclipse/graphiti/features/IFeatureProvider.html#getDragAndDropFeatures(org.eclipse.graphiti.features.context.IPictogramElementContext)"> | |
getDragAndDropFeatures</a>).</p> | |
<p>In this very simple implementation all create connection features are returned | |
independent of the given context:</p> | |
<!-- Begin code ------------------------------------------------------------------------------- --> | |
<p> </p> | |
<div class="literallayout"> | |
<div class="incode"> | |
<p class="code">@Override<br><span class="keyword">public </span>IFeature[] | |
getDragAndDropFeatures(IPictogramElementContext context) {<br> | |
<span class="comment">// simply return all create connection features</span><br> | |
<span class="keyword">return </span>getCreateConnectionFeatures();<br>} | |
</p> | |
</div> | |
</div> | |
<p> </p> | |
<!-- End code ------------------------------------------------------------------------------- --> | |
<p class="Note">Note: A more sophisticated solution with an anchor on a EClass with | |
an <em>extended rendering area</em> like the examples at the beginning is shown in chapter | |
<a href="selection-behavior.htm">selection behavior</a>.</p> | |
<h2>Test: Create a Connection with Drag & Drop from Anchor</h2> | |
<p>Start the editor again and create two new EClasses (existing EClasses don’t work, | |
because they have no anchor). Then drag the anchor at | |
the middle-right border of the first EClass and drop it onto the second EClass. | |
This will create a new connection between those two EClasses.</p> | |
<p> </p> | |
<h1>Use an Anchor Location as Connection End-Point</h1> | |
<p> </p> | |
<p> | |
<img alt="" height="153" src="visio/anchor-box-relative-example-2.png" width="203"></p> | |
<p><strong>Figure: Box relative anchor with an anchor location as end-point</strong></p> | |
<p> </p> | |
<p>The above image shows a connection which has an end-point directly on the | |
border of the rectangle on the right. The rectangle is the graphical | |
representation of the box relative anchor. Using a location on the the right border of the anchor | |
as end-point will be possible by invoking | |
<a href="../../../javadoc/org/eclipse/graphiti/mm/pictograms/AdvancedAnchor.html#setUseAnchorLocationAsConnectionEndpoint(boolean)"> | |
setUseAnchorLocationAsConnectionEndpoint </a>on the anchor.</p> | |
<!-- Begin code ------------------------------------------------------------------------------- --> | |
<p> </p> | |
<div class="literallayout"> | |
<div class="incode"> | |
<p class="code"><span class="keyword">public </span>PictogramElement add(IAddContext | |
context) {<br> <br> | |
<span class="comment">// ... EXISTING CODING ...</span><br> <br> | |
<span class="comment">// create an box relative anchor at middle-right</span><br> | |
<span class="keyword">final </span>BoxRelativeAnchor boxAnchor = <br> | |
peCreateService.createBoxRelativeAnchor(containerShape);<br> | |
<br> boxAnchor.setRelativeWidth(1.0);<br> | |
boxAnchor.setRelativeHeight(0.38); <span class="comment">//use golden section</span><br> | |
boxAnchor.setUseAnchorLocationAsConnectionEndpoint(<span class="keyword">true</span>);<br> | |
boxAnchor.setReferencedGraphicsAlgorithm(roundedRectangle);<br> | |
<br> | |
<span class="comment">// assign a rectangle graphics algorithm for the | |
box relative anchor<br> // note, that the | |
rectangle is inside the border of the rectangle shape</span><br> | |
<span class="keyword"> final</span> Rectangle rectangle = | |
gaService.createPlainRectangle(boxAnchor); <br> ellipse.setForeground(manageColor(<span class="string"><em>E_CLASS_FOREGROUND</em></span>));<br> | |
ellipse.setBackground(manageColor(<span class="string"><em>E_CLASS_BACKGROUND</em></span>));<br> | |
ellipse.setLineWidth(2);<br> | |
<span class="comment">// anchor is located on the right border of the visible | |
rectangle<br> // and touches the border of | |
the invisible rectangle</span><br> | |
gaService.setLocationAndSize(rectangle, -12, -6, 12, 12);<br> <br> | |
<span class="comment">// call the layout feature</span><br> | |
layoutPictogramElement(containerShape);<br> <br> | |
<span class="keyword">return </span>containerShape;<br>} </p> | |
</div> | |
</div> | |
<p> </p> | |
<!-- End code ------------------------------------------------------------------------------- --> | |
</body> | |
</html> |