View Javadoc

1   /*
2    * This file is a part of CAST project.
3    * (c) Copyright 2007, AGH University of Science & Technology
4    * All rights reserved. Check the documentation for licensing terms.
5    * https://caribou.iisg.agh.edu.pl/trac/cast
6    */
7   package pl.edu.agh.cast.schema.figure;
8   
9   import org.eclipse.draw2d.AnchorListener;
10  import org.eclipse.draw2d.ConnectionAnchor;
11  import org.eclipse.draw2d.ConnectionAnchorBase;
12  import org.eclipse.draw2d.Graphics;
13  import org.eclipse.draw2d.IFigure;
14  import org.eclipse.draw2d.Label;
15  import org.eclipse.draw2d.PolygonDecoration;
16  import org.eclipse.draw2d.PolylineConnection;
17  import org.eclipse.draw2d.geometry.Dimension;
18  import org.eclipse.draw2d.geometry.Point;
19  import org.eclipse.draw2d.geometry.PointList;
20  import org.eclipse.draw2d.geometry.Rectangle;
21  import org.eclipse.swt.SWT;
22  import org.eclipse.swt.graphics.Color;
23  import org.eclipse.swt.widgets.Display;
24  
25  import pl.edu.agh.cast.common.HexColor;
26  import pl.edu.agh.cast.model.visual.backward.ConnectionGroup;
27  
28  /**
29   * Double two-way connection between suspects
30   *
31   * @author fox
32   */
33  public class DoublePolylineConnection extends ModifiablePolylineConnection {
34  
35      private final int LinesDistance = 10;
36  
37      private int BORDER_CONSTANT = 10;
38  
39      private PolylineConnection _secondPolyline;
40  
41      private Label _firstLabel;
42  
43      private Label _secondLabel;
44  
45      private InternalConnectionAnchor _sourceAnchor;
46  
47      private ConnectionGroup _connectionGroup;
48  
49      public DoublePolylineConnection(ConnectionGroup connectionGroup) {
50  
51          _connectionGroup = connectionGroup;
52  
53          _secondPolyline = new PolylineConnection();
54          _firstLabel = new Label(""); //$NON-NLS-1$
55          _firstLabel.setBackgroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
56          _firstLabel.setOpaque(true);
57          _secondLabel = new Label(""); //$NON-NLS-1$
58          _secondLabel.setBackgroundColor(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
59          _secondLabel.setOpaque(true);
60  
61          setTargetDecoration(new PolygonDecoration());
62          setLineStyle(Graphics.LINE_SOLID);
63          _secondPolyline.setSourceDecoration(new PolygonDecoration());
64          _secondPolyline.setLineStyle(Graphics.LINE_SOLID);
65  
66          _sourceAnchor = new InternalConnectionAnchor(_secondPolyline);
67  
68          add(_firstLabel);
69  
70          add(_secondLabel);
71  
72          add(_secondPolyline);
73  
74          refresh();
75      }
76  
77      @Override
78      public void setPoints(PointList points) {
79          float angle = getAngle(points);
80  
81          PointList firstLinePoints = new PointList();
82          PointList secondLinePoints = new PointList();
83  
84          Point firstPoint = points.getFirstPoint();
85          Point lastPoint = points.getLastPoint();
86          int xVector = firstPoint.x - lastPoint.x;
87          int yVector = firstPoint.y - lastPoint.y;
88          double vectorLength = (Math.sqrt(xVector * xVector + yVector * yVector));
89          if (vectorLength > 3 * BORDER_CONSTANT) {
90              double xUnitVector = xVector / vectorLength;
91              double yUnitVector = yVector / vectorLength;
92  
93              firstPoint = new Point(firstPoint.x - xUnitVector * BORDER_CONSTANT, firstPoint.y - yUnitVector
94                      * BORDER_CONSTANT);
95              lastPoint = new Point(lastPoint.x + xUnitVector * BORDER_CONSTANT, lastPoint.y + yUnitVector
96                      * BORDER_CONSTANT);
97              points = new PointList();
98              points.addPoint(firstPoint);
99              points.addPoint(lastPoint);
100         }
101 
102         for (int i = 0; i < points.size(); i++) {
103             Point original = points.getPoint(i);
104             firstLinePoints.addPoint(translateFirstLinePoint(original, angle));
105             secondLinePoints.addPoint(translateSecondLinePoint(original, angle));
106         }
107 
108         super.setPoints(firstLinePoints);
109         _secondPolyline.setPoints(secondLinePoints);
110         setLabelsBounds(firstLinePoints, secondLinePoints, angle);
111     }
112 
113     private float getAngle(PointList points) {
114         float dx = points.getLastPoint().x - points.getFirstPoint().x;
115         float dy = points.getLastPoint().y - points.getFirstPoint().y;
116         return (float)Math.atan2(dx, dy);
117     }
118 
119     private Point translateFirstLinePoint(Point original, float angle) {
120         int newX = (int)(original.x + LinesDistance * Math.cos(angle) / 2);
121         int newY = (int)(original.y - LinesDistance * Math.sin(angle) / 2);
122         return new Point(newX, newY);
123     }
124 
125     private Point translateSecondLinePoint(Point original, float angle) {
126         int newX = (int)(original.x - LinesDistance * Math.cos(angle) / 2);
127         int newY = (int)(original.y + LinesDistance * Math.sin(angle) / 2);
128         return new Point(newX, newY);
129     }
130 
131     private Point getMiddlePoint(PointList points) {
132         int x = (points.getLastPoint().x + points.getFirstPoint().x) / 2;
133         int y = (points.getLastPoint().y + points.getFirstPoint().y) / 2;
134         return new Point(x, y);
135     }
136 
137     @Override
138     public void setSourceAnchor(ConnectionAnchor anchor) {
139         if (getSourceAnchor() != null) {
140             getSourceAnchor().removeAnchorListener(_sourceAnchor);
141         }
142 
143         super.setSourceAnchor(anchor);
144 
145         if (anchor != null) {
146             anchor.addAnchorListener(_sourceAnchor);
147         }
148     }
149 
150     @Override
151     public void setTargetAnchor(ConnectionAnchor anchor) {
152         if (getTargetAnchor() != null) {
153             getTargetAnchor().removeAnchorListener(_sourceAnchor);
154         }
155 
156         super.setTargetAnchor(anchor);
157 
158         if (anchor != null) {
159             anchor.addAnchorListener(_sourceAnchor);
160         }
161     }
162 
163     private void setLabelsBounds(PointList firstLinePoints, PointList secondLinePoints, float angle) {
164         Point firstLabelPoint = getMiddlePoint(firstLinePoints);
165         Dimension firstLabelSize = _firstLabel.getPreferredSize();
166 
167         Point secondLabelPoint = getMiddlePoint(secondLinePoints);
168         Dimension secondLabelSize = _secondLabel.getPreferredSize();
169 
170         if (firstLabelPoint.x < secondLabelPoint.x) {
171             firstLabelPoint.x = (int)(firstLabelPoint.x - firstLabelSize.width * Math.abs(Math.cos(angle)));
172         } else if (secondLabelPoint.x < firstLabelPoint.x) {
173             secondLabelPoint.x = (int)(secondLabelPoint.x - secondLabelSize.width * Math.abs(Math.cos(angle)));
174         }
175 
176         if (firstLabelPoint.y < secondLabelPoint.y) {
177             firstLabelPoint.y = (int)(firstLabelPoint.y - firstLabelSize.height * Math.abs(Math.sin(angle)));
178         } else if (secondLabelPoint.y < firstLabelPoint.y) {
179             secondLabelPoint.y = (int)(secondLabelPoint.y - secondLabelSize.height * Math.abs(Math.sin(angle)));
180         }
181 
182         _firstLabel.setBounds(new Rectangle(firstLabelPoint, firstLabelSize));
183         _secondLabel.setBounds(new Rectangle(secondLabelPoint, secondLabelSize));
184     }
185 
186     private class InternalConnectionAnchor extends ConnectionAnchorBase implements AnchorListener {
187 
188         private Point _desiredLocation;
189 
190         private PolylineConnection _connection;
191 
192         public InternalConnectionAnchor(PolylineConnection connection) {
193             _connection = connection;
194             _connection.setSourceAnchor(this);
195         }
196 
197         public Point getLocation(Point location) {
198             return _desiredLocation;
199         }
200 
201         public IFigure getOwner() {
202             return null;
203         }
204 
205         public Point getReferencePoint() {
206             return _desiredLocation;
207         }
208 
209         public void anchorMoved(ConnectionAnchor anchor) {
210             _desiredLocation = _connection.getPoints().getFirstPoint();
211             _connection.getPoints().getLastPoint();
212             fireAnchorMoved();
213         }
214     }
215 
216     @Override
217     public void refresh() {
218         _firstLabel.setText((String)_connectionGroup.getAttributeValue(ConnectionGroup.DOUBLE_CONNECTION_SOURCE_LABEL)
219                 .getValue());
220         _secondLabel.setText((String)_connectionGroup.getAttributeValue(ConnectionGroup.DOUBLE_CONNECTION_TARGET_LABEL)
221                 .getValue());
222 
223         HexColor hexColor = (HexColor)_connectionGroup.getAttributeValue(ConnectionGroup.LINE_COLOR).getValue();
224         this.setForegroundColor(new Color(null, hexColor.getRed(), hexColor.getGreen(), hexColor.getBlue()));
225         _secondPolyline.setForegroundColor(new Color(null, hexColor.getRed(), hexColor.getGreen(), hexColor.getBlue()));
226 
227         revalidate();
228         repaint();
229     }
230 }