Tutorial: Creating Connections
Version: 0.1
|
Date: August 11, 2005
|
Contents
-
Overview
-
References
-
Introduction
-
Create a new connection
type
-
Drawing connections between
shapes
-
Connecting wires at fixed
anchors
-
Summary
[
back to top]
This tutorial provides the reader with the steps to create a new
connection within a diagram client.
[
back to top]
This tutorial references the following tutoral:
Create a shape
[
back to top]
In this tutorial, we will use the Logic Diagram Example to
illustrate how to add a connection edge to a diagram. We will use
the wire connection as the example. To gain familiarity with the
Logic Diagram Example, refer to the
Logic ExampleGuide.
Most diagrams have a need to display semantic relationships that
exist between elements. In the Logic example, this is also
the case. There is an element called ?Wire? which allows
logic elements to be connected to each other. It is literally
the wire that carries electricity between terminals on circuits and
LED elements in the circuit board. The mechanism for adding a
connection shape on a diagram is very similar to how a shape is
added except for some subtle difference in API. This is
summarized below.
See section
#Add entries tothe contribution for the palette provider.
A new condition needs to be added in the LogicPaletteFactory
class in the createTool method. For a connection a
ConnectionCreationTool instance is created passing in an
IElementType hint (wire) that will be sent in a request to return a
command for creating the connection.
In order to respond to the tool request we need to create a
provider for creating the notation (View) for the new shape.
First it is necessary to add plug-in.xml extension for the
org.eclipse.gmf.runtime.diagram.core.viewProviders extension
point. We indicate the viewClass context
(org.eclipse.gmf.runtime.notation.Edge) and provide a hint for our
provider to be invoked upon (wire). Similar to
#Add new Vie
w provider entry a mapping of
the hint to the view class that will construct the connection
notation is necessary in the getConnectionViewClass method.
The WireView.java class will serve this purpose. The WireView
class subclasses from AbstractConnectionView. Please refer to
the WireView class for details of what initialization is
needed.
Refer to
#Add new Editpartprovider entry on how to add a plugin.xml entry for a
org.eclipse.gmf.runtime.diagram.ui.editpartProviders extension. In
the LogicEditPartProvider class there is simply a mapping from the
View class to the EditPart class that needs to be created in the
getConnectionEditPartClass method. The WireEditPart class
contains code for managing creating the IFigure
(PolylineConnectionEx ) class and responding to property change
events.
[
back to top]
The notation meta-model stores all layout constraint units
(positions, bendpoints and anchors) in HiMetric units (0.1
millimeter). This allows for a high level of precision when
dealing with zoomed in diagrams. This adds some complexity to
the figure display since GEF assumes pixel units when drawing
figures onto the canvas.
In the case where we wish to connect 2 LED shapes via a wire
connection, we'll need to do some conversion of the pixel values to
HiMetric before the connection can accurately connect to the
LEDFigure. The function MapMode.DPtoLP(int deviceUnit) is
used to convert a Device Unit (pixels) into a Logical Unit.
This method needs to be instrumented in the LEDFigure when drawing
the connection nubs around the shape. Additionally by
abstracting the pixels through this MapMode, it will allow the
platform to support a different coordinate systems in the future
without affecting clients.
A somewhat unique aspect of the Logic example is that the wires
don't connect directly to the top level shapes. They always
connect via terminal elements that exist on the borders of the
shapes. If we consider the LED shape, it has 8 terminals
surrounding it where 4 are incoming terminals and 4 are outgoing
terminals. To accomplish this, it is necessary to have a
separate view represent the terminal on the border of the LED
view. The terminal views on the LED are essential to the
functionality of the LED so they need to be represented all the
time. This is referred to as a canonical
representation. The means that the children of a particular
view are always fully synchronized with the corresponding semantic
element children.
There is a facility in the diagram layer that can manage this
synchronization called the CanonicalEditPolicy. This
EditPolicy is installed on an EditPart and is responsible for
managing the creation of child views that need to be created if a
semantic child exists. The LEDEditPart has a subclass of this
EditPolicy called LogicCanonicalEditPolicy that discovers the
terminal children of the LED semantic element and creates
corresponding terminal views for each terminal element.
[
back to top]
The default behavior when connecting to a shape allows the end
of the connection to be anywhere around the source or target
shape. In the case of the wire connection, we want it to
connect at a very specific location on the terminal and don't need
to have the flexibility of moving it around the shape. The
anchoring behavior is handled in the IFigure hierarchy through the
ConnectionAnchor interface.
To change the default behavior, we need to override some methods
in the IFigure implementation to return a different anchor.
In the LEDFigure class the getSourceConnectionAnchorAt and
getTargetConnectionAnchorAt functions need to be overridden in
LEDFigure and return a anchor that will return a fixed point with
the figure bounds.
In LEDFigure:
/*
* @see
org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure#getSourceConnectionAnchorAt(org.eclipse.draw2d.geometry.Point)
*/
public ConnectionAnchor
getSourceConnectionAnchorAt(Point p) {
if (p == null) {
return getConnectionAnchor(szAnchor);
}
return fixedAnchor;
}
public Vector getSourceConnectionAnchors() {
return
outputConnectionAnchors;
}
Support for reconnection between two shapes at fixed
anchors
When creating or reconnecting a wire between terminals on the
logical example, this is not only
changing the notation by moving the end points, it is also
changing the underlying semantic model that the diagram is
representing. This behavior is centralized with-in the
EditHelper for wire metaModelType. The WireEditHelper
overrides the AbstractEditHelper#getReorientRelationshipCommand to
return the command that handles reorient of the logic wire
element. For instance, when a palette tool is invoked, it is
sending a request that is handled by the SemanticEditPolicy which
in terms handles the creation. Similarly when the user
reorients the end of a wire in the logic example, a request is sent
automatically by the infrastructure to the SemanticEditPolicy which
determines if there is a metaModelType registered that can handle
the request. In this case the wire metaModelType would be
found and would return the WireEditHelper which can provide a
command for this request that subsequently gets executed making the
changes against the logic semantic model.
In WireEditHelper.java:
/**
* Gets a command to
change the source or target of a wire.
*/
protected
IEditElementCommand getReorientRelationshipCommand(
ReorientRelationshipRequest req) {
return new ReorientWireCommand(req);
}
[
back to top]
In this tutorial, we did the following:
- Created a new connection wire for display on the diagram
editor..
- Learned how to connect 2 shapes using the new connection
type..
- Created fixed anchors for the connection to attach it's ends
to.
Copyright
(c) 2000,2005 IBM Corporation and others. All Rights
Reserved.