blob: 9c07a11d75ccda45a662bf06796f7f69678a0191 [file] [log] [blame]
<!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>
<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="" 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="" 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 <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>&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>
<!-- End code ------------------------------------------------------------------------------- -->
<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>
<!-- Begin code ------------------------------------------------------------------------------- -->
<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>
<!-- End code ------------------------------------------------------------------------------- -->
<p class="Note">Note: 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>Test: Create a Connection with Drag &amp; Drop from Anchor</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>
<p>&nbsp;</p>
</body>
</html>