blob: 91567065148040d26c77f81327abb76c5502414c [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>
<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>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</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>&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>
<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 &amp; Drop from Anchors</h2>
<p>&nbsp;</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>&nbsp;</p>
<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> 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 &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 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>&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.38); <span class="comment">//use golden section </span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
boxAnchor.setReferencedGraphicsAlgorithm(roundedRectangle);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// assign a rectangle graphics algorithm for the
box relative anchor<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // note, that the
rectangle is inside the border of the rectangle shape</span><br>&nbsp;&nbsp;&nbsp;&nbsp;
<span class="keyword">&nbsp;final</span> Rectangle rectangle =
gaService.createPlainRectangle(boxAnchor);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rectangle.setForeground(manageColor(<span class="string"><em>E_CLASS_FOREGROUND</em></span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rectangle.setBackground(manageColor(<span class="string"><em>E_CLASS_BACKGROUND</em></span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rectangle.setLineWidth(2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
gaService.setLocationAndSize(rectangle, -12, -6, 12, 12);<br>&nbsp;&nbsp;&nbsp;&nbsp;&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> 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 &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). 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>
<h1>Use an Anchor Location as Connection End-Point</h1>
<p>&nbsp;</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>&nbsp;</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>&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">// create an 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.38); <span class="comment">//use golden section</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
boxAnchor.setUseAnchorLocationAsConnectionEndpoint(<span class="keyword">true</span>);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
boxAnchor.setReferencedGraphicsAlgorithm(roundedRectangle);<br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<span class="comment">// assign a rectangle graphics algorithm for the
box relative anchor<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // note, that the
rectangle is inside the border of the rectangle shape</span><br>&nbsp;&nbsp;&nbsp;&nbsp;
<span class="keyword">&nbsp;final</span> Rectangle rectangle =
gaService.createPlainRectangle(boxAnchor);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ellipse.setForeground(manageColor(<span class="string"><em>E_CLASS_FOREGROUND</em></span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ellipse.setBackground(manageColor(<span class="string"><em>E_CLASS_BACKGROUND</em></span>));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ellipse.setLineWidth(2);<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;&nbsp;&nbsp;&nbsp;&nbsp;
gaService.setLocationAndSize(rectangle, -12, -6, 12, 12);<br>&nbsp;&nbsp;&nbsp;&nbsp;&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 ------------------------------------------------------------------------------- -->
</body>
</html>