Copyright 2003 International Business Machines Corp.
Draw a UML diagram using draw2d
Summary
The graphic editing framework (GEF) operates on draw2d. Draw2d is a plug-in that provides painting and layout management, providing graphics and layout manager for GEF applications to build programs.
Graphical presentation layer. This article only focuses on how to use draw2d to draw UML diagrams. Draw2d can be used independently, but it is not an editing framework. Most applications use the GEF plug-in.
Implement the editing function.
Introduction
Draw2d provides a lightweight Implementation of drawing and layout on the SWT canvas. Figure and Layout
Manager), and border (Border) can be combined and embedded to build complex graphics to adapt to any application. It is very refined to select the correct combination of images to create the desired image.
This article describes how to create a complex graph.
Due to the limitations of this article, the sample code in this article will use draw2d independently, but most applications will use GEF and draw2d in combination.
Example of creating a draw2d Image
Is a simple UML class diagram. This article is based on the creation of this graphic.
Design graphics
The first step in creating a graph is to determine what components are used to synthesize the graph and how they are arranged.
An example graph consists of three subgraphs. The image itself is umlclassfigure, its first sub-image is label, used to display the class name (in this example, "table"), the other two
A sub-graph is a container used to place attributes and methods. We will create a graph called compartmentfigure to achieve the container goal. Umlclassfigure and
Compartmentfigure uses toolbarlayout to place subgraphs. It is a conceptual upper-layer structure:
Create compartmentfigure class
Compartmentfigure is used to place methods and attributes. This class inherits the org. Eclipse. draw2d. Figure Class and uses
Toolbarlayout is used to manage the layout of sub-graphs. At the same time, compartmentfigure uses a custom border. This border simply draws a line at the top of it.
A line with a pixel width separated by two compartmentfigure. The compartmentfigure code is as follows:
public class CompartmentFigure extends Figure {
public CompartmentFigure() { ToolbarLayout layout = new ToolbarLayout(); layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT); layout.setStretchMinorAxis(false); layout.setSpacing(2); setLayoutManager(layout); setBorder(new CompartmentFigureBorder()); }
public class CompartmentFigureBorder extends AbstractBorder { public Insets getInsets(IFigure figure) { return new Insets(1,0,0,0); } public void paint(IFigure figure, Graphics graphics, Insets insets) { graphics.drawLine(getPaintRectangle(figure, insets).getTopLeft(), tempRect.getTopRight()); } } } |
Create umlclassfigure class
The umlclassfigure class is similar to the compartmentfigure class in many places. It contains three subgraphs-two of the placement methods and attributes.
Compartmentfigure and a draw2d label used to display the class name ). It also uses vertical-oriented toolbarlayout to manage child images.
. Umlclassfirgure uses the draw2d lineborder to draw a rectangular border on its own edge.
public class UMLClassFigure extends Figure { public static Color classColor = new Color(null,255,255,206); private CompartmentFigure attributeFigure = new CompartmentFigure(); private CompartmentFigure methodFigure = new CompartmentFigure(); public UMLClassFigure(Label name) { ToolbarLayout layout = new ToolbarLayout(); setLayoutManager(layout); setBorder(new LineBorder(ColorConstants.black,1)); setBackgroundColor(classColor); setOpaque(true);
add(name); add(attributeFigure); add(methodFigure); } public CompartmentFigure getAttributesCompartment() { return attributeFigure; } public CompartmentFigure getMethodsCompartment() { return methodFigure; } } |
Add connection
Draw2d provides a special connection image used to connect two images. To create a connection in draw2d, you must first create two endpoints for the connection.
(Endpoint ). This endpoint becomes the source anchor and target
Anchor ). The endpoint is created by a class that implements the connectionanchor interface. After the support point is created, you can call
Setsourceanchor (connectionanchor) method and settargetanchor (connectionanchor) Method
Set it as the endpoint. In this example, a support point called chopboxanchor is used to place the endpoint on the edge of the graph and direct it to the center of the graph.
The following code adds a connection:
PolylineConnection c = new PolylineConnection(); ChopboxAnchor sourceAnchor = new ChopboxAnchor(classFigure); ChopboxAnchor targetAnchor = new ChopboxAnchor(classFigure2); c.setSourceAnchor(sourceAnchor); c.setTargetAnchor(targetAnchor); |
Two umlclassfirgure connected by polylineconnection
Decoration of Connection
Draw2d also provides endpoints with arrows and other shapes that can be decorated with certain significance. Like UML, we will create a solid diamond decoration to represent the composite relationship. This will be caused
Polygondecoration. The default shape of polygondecoration is a solid arrow, but any shape can be achieved by creating a new template. Template
Pointlist definition, which is specified by calling settemplate (pointlist.
The following code demonstrates how to add polygondecoration to a connection:
PolygonDecoration decoration = new PolygonDecoration(); PointList decorationPointList = new PointList(); decorationPointList.addPoint(0,0); decorationPointList.addPoint(-2,2); decorationPointList.addPoint(-4,0); decorationPointList.addPoint(-2,-2); decoration.setTemplate(decorationPointList); c.setSourceDecoration(decoration); |
Connections with polygondecoration
Use locator to tag connections
In addition to decoration, we can also add other draw2d images to the connection. This can be done by calling the connection add (ifigure figure, Object
Constratint) method implementation, where figure is the image to be added, constraint is a class that implements the locator interface, by Locator
Place on the connection. We will use this technology to add labels to our class diagrams. Connectionendpointlocator can place a graph at the source or target endpoint of the connection.
So we use it to place labels. We can also specify the graphics and endpoints by calling the setudistance (INT) and setvdistance (INT) methods.
(Udistance is the distance from the connected image to the image to be added, while vdistance is an example of the image to be added to the connection itself ).
The following code demonstrates how to use connectionendpointlocator to tag a connection:
ConnectionEndpointLocator targetEndpointLocator = new ConnectionEndpointLocator(c, true); targetEndpointLocator.setVDistance(15); Label targetMultiplicityLabel = new Label("1..*"); c.add(targetMultiplicityLabel, targetEndpointLocator); ConnectionEndpointLocator sourceEndpointLocator = new ConnectionEndpointLocator(c, false); sourceEndpointLocator.setVDistance(15); Label sourceMultiplicityLabel = new Label("1"); c.add(sourceMultiplicityLabel, sourceEndpointLocator);
ConnectionEndpointLocator relationshipLocator = new ConnectionEndpointLocator(c,true); relationshipLocator.setUDistance(30); relationshipLocator.setVDistance(-20); Label relationshipLabel = new Label("contains"); c.add(relationshipLabel,relationshipLocator);
|
Added the tag connection.
Create test class
The test class contains a main method to create
Lightweightsystem (LWS, used to connect SWT and draw2d) SWT
Shell. In this example, the figure class of draw2d is used as the content of LWS, and two umlclassfigure values are added to figure. And then create
A connection with a diamond endpoint decoration and labels.
The test class uses several images {}. Please download them and put them in the root folder of the Java project.
import org.eclipse.draw2d.*; import org.eclipse.draw2d.geometry.PointList; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell;
/** * A test class to display a UMLFigure */ public class UMLClassFigureTest { public static void main(String args[]){ Display d = new Display(); final Shell shell = new Shell(d); shell.setSize(400, 400); shell.setText("UMLClassFigure Test"); LightweightSystem lws = new LightweightSystem(shell); Figure contents = new Figure(); XYLayout contentsLayout = new XYLayout(); contents.setLayoutManager(contentsLayout);
Font classFont = new Font(null, "Arial", 12, SWT.BOLD); Label classLabel1 = new Label("Table", new Image(d, UMLClassFigureTest.class.getResourceAsStream("class_obj.gif"))); classLabel1.setFont(classFont);
Label classLabel2 = new Label("Column", new Image(d, UMLClassFigureTest.class.getResourceAsStream("class_obj.gif"))); classLabel2.setFont(classFont);
final UMLClassFigure classFigure = new UMLClassFigure(classLabel1); final UMLClassFigure classFigure2 = new UMLClassFigure(classLabel2);
Label attribute1 = new Label("columns: Column[]", new Image(d, UMLClassFigure.class.getResourceAsStream("field_private_obj.gif"))); Label attribute2 = new Label("rows: Row[]", new Image(d, UMLClassFigure.class.getResourceAsStream("field_private_obj.gif"))); Label attribute3 = new Label("columnID: int", new Image(d, UMLClassFigure.class.getResourceAsStream("field_private_obj.gif"))); Label attribute4 = new Label("items: List", new Image(d, UMLClassFigure.class.getResourceAsStream("field_private_obj.gif")));
classFigure.getAttributesCompartment().add(attribute1); classFigure.getAttributesCompartment().add(attribute2); classFigure2.getAttributesCompartment().add(attribute3); classFigure2.getAttributesCompartment().add(attribute4);
Label method1 = new Label("getColumns(): Column[]", new Image(d, UMLClassFigure.class.getResourceAsStream("methpub_obj.gif"))); Label method2 = new Label("getRows(): Row[]", new Image(d, UMLClassFigure.class.getResourceAsStream("methpub_obj.gif"))); Label method3 = new Label("getColumnID(): int", new Image(d, UMLClassFigure.class.getResourceAsStream("methpub_obj.gif"))); Label method4 = new Label("getItems(): List", new Image(d, UMLClassFigure.class.getResourceAsStream("methpub_obj.gif")));
classFigure.getMethodsCompartment().add(method1); classFigure.getMethodsCompartment().add(method2); classFigure2.getMethodsCompartment().add(method3); classFigure2.getMethodsCompartment().add(method4);
contentsLayout.setConstraint(classFigure, new Rectangle(10,10,-1,-1)); contentsLayout.setConstraint(classFigure2, new Rectangle(200, 200, -1, -1));
/* Creating the connection */ PolylineConnection c = new PolylineConnection(); ChopboxAnchor sourceAnchor = new ChopboxAnchor(classFigure); ChopboxAnchor targetAnchor = new ChopboxAnchor(classFigure2); c.setSourceAnchor(sourceAnchor); c.setTargetAnchor(targetAnchor);
/* Creating the decoration */ PolygonDecoration decoration = new PolygonDecoration(); PointList decorationPointList = new PointList(); decorationPointList.addPoint(0,0); decorationPointList.addPoint(-2,2); decorationPointList.addPoint(-4,0); decorationPointList.addPoint(-2,-2); decoration.setTemplate(decorationPointList); c.setSourceDecoration(decoration);
/* Adding labels to the connection */ ConnectionEndpointLocator targetEndpointLocator = new ConnectionEndpointLocator(c, true); targetEndpointLocator.setVDistance(15); Label targetMultiplicityLabel = new Label("1..*"); c.add(targetMultiplicityLabel, targetEndpointLocator);
ConnectionEndpointLocator sourceEndpointLocator = new ConnectionEndpointLocator(c, false); sourceEndpointLocator.setVDistance(15); Label sourceMultiplicityLabel = new Label("1"); c.add(sourceMultiplicityLabel, sourceEndpointLocator);
ConnectionEndpointLocator relationshipLocator = new ConnectionEndpointLocator(c,true); relationshipLocator.setUDistance(10); relationshipLocator.setVDistance(-20); Label relationshipLabel = new Label("contains"); c.add(relationshipLabel,relationshipLocator);
contents.add(classFigure); contents.add(classFigure2); contents.add(c);
lws.setContents(contents); shell.open(); while (!shell.isDisposed()) while (!d.readAndDispatch()) d.sleep(); } } |
Conclusion
This article introduces the use of the visual component draw2d graphics using graphical editing framework, and also introduces the concepts of draw2d connection, decoration, and locator. For more information, visit the GEF homepage (Http://www.eclipse.org/gef)