blob: ccbc9f3657ea7cf7025c5afeede8b4f506a34715 [file] [log] [blame]
<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>
<h2>Different Types of Connection Anchors</h2>
<p>Currently the following different types of connection anchors are supported:</p>
<h3>Chop Box Anchor</h3>
<p>It can be created calling
<a href="../../../javadoc/org/eclipse/graphiti/services/IPeCreateService.html#createChopboxAnchor(org.eclipse.graphiti.mm.pictograms.AnchorContainer)">
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.</p>
<p>&nbsp;</p>
<p>
<img alt="" border="0" height="104" src="visio/anchor-chopbox.gif" width="164"></p>
<p><strong>Figure: Chop box anchor (always pointing to the center)</strong></p>
<p>&nbsp;</p>
<h3>Box Relative Anchor</h3>
<p>It can be created calling
<a href="../../../javadoc/org/eclipse/graphiti/services/IPeCreateService.html#createBoxRelativeAnchor(org.eclipse.graphiti.mm.pictograms.AnchorContainer)">
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>&nbsp;</p>
<p><img alt="" height="95" src="visio/anchor-boxrelative.gif" width="165"></p>
<p><strong>Figure: Box relative anchor (on middle-right border)</strong></p>
<p>&nbsp;</p>
<h3>Fix Point Anchor</h3>
<p>It can be created calling
<a href="../../../javadoc/org/eclipse/graphiti/services/IPeCreateService.html#createFixPointAnchor(org.eclipse.graphiti.mm.pictograms.AnchorContainer)">
createFixPointAnchor</a>. A fix point anchor is located at fix 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>&nbsp;</p>
<p>
<img alt="" border="0" height="154" src="visio/anchor-points.gif" width="444"></p>
<p><strong>Figure: Points of a chop box anchor </strong></p>
<p>&nbsp;</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>
<h2>Creating Connections with Drag &amp; Drop from Anchors</h2>
<p>If the user shall be able to create connections directly via drag &amp; drop from
an anchor without the connection-tool, this can be implemented by so called drag
&amp; 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 &amp; 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>.</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 &amp; 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 end of the add method of
the TutorialAddEClassFeature, 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>
<p>&nbsp;</p>
<div class="literallayout">
<div class="incode">
<p class="code"><span class="keyword">public </span>PictogramElement add(IAddContext
context) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// ... EXISTING CODING ...</span><br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// add a chopbox anchor to the shape</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
peCreateService.createChopboxAnchor(containerShape);<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// create an additional box relative anchor at middle-right</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="keyword">final </span>BoxRelativeAnchor boxAnchor = <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
peCreateService.createBoxRelativeAnchor(containerShape);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boxAnchor.setRelativeWidth(1.0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
boxAnchor.setRelativeHeight(0.5);<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// anchor references visible rectangle instead of
invisible rectangle</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boxAnchor.setReferencedGraphicsAlgorithm(roundedRectangle);<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// assign a graphics algorithm for the box relative
anchor</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rectangle rectangle = gaService.createRectangle(boxAnchor);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rectangle.setFilled(<span class="keyword">true</span>);<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// anchor is located on the right border of the visible
rectangle<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // and touches the border of
the invisible rectangle</span><br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="keyword">int </span>w = 6;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
gaService.setLocationAndSize(rectangle, -2 * w, -w, 2 * w, 2 * w);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rectangle.setForeground(manageColor(<span class="string"><em>CLASS_FOREGROUND</em></span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rectangle.setBackground(manageColor(<span class="string"><em>CLASS_BACKGROUND</em></span>));<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// call the layout feature</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
layoutPictogramElement(containerShape);<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="keyword">return </span>containerShape;<br>}
</p>
</div>
</div>
<p>&nbsp;</p>
<p>Additionally the feature provider has to deliver the drag &amp; 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>
<p>&nbsp;</p>
<div class="literallayout">
<div class="incode">
<p class="code">@Override<br><span class="keyword">public </span>IFeature[]
getDragAndDropFeatures(IPictogramElementContext context) {<br>&nbsp;&nbsp;&nbsp;
<span class="comment">// simply return all create connection features</span><br>&nbsp;&nbsp;&nbsp;
<span class="keyword">return </span>getCreateConnectionFeatures();<br>}
</p>
</div>
</div>
<p>&nbsp;</p>
<p><strong>Note:</strong> A more sophisticated solution with an anchor on a EClass
with an <em>extended rendering area</em> is shown in chapter
<a href="selection-behavior.htm">selection behavior</a>.</p>
<h2><span lang="EN-GB">Test: Create a Connection with Drag &amp; Drop from Anchor</span></h2>
<p>Start the editor again and create two new EClasses (existing EClasses don’t work,
because they have no anchor at the middle-right border). 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>
</body>
</html>