]> gerrit.simantics Code Review - simantics/sysdyn.git/blob
529ca158889e3fcb469ce11c737e4e6515534efe
[simantics/sysdyn.git] /
1 /*******************************************************************************\r
2  * Copyright (c) 2010 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.sysdyn.ui.elements2.connections;\r
13 \r
14 import java.awt.BasicStroke;\r
15 import java.awt.Color;\r
16 import java.awt.Font;\r
17 import java.awt.Graphics2D;\r
18 import java.awt.Stroke;\r
19 import java.awt.event.MouseEvent;\r
20 import java.awt.event.MouseListener;\r
21 import java.awt.event.MouseMotionListener;\r
22 import java.awt.geom.Arc2D;\r
23 import java.awt.geom.Path2D;\r
24 import java.awt.geom.Point2D;\r
25 import java.awt.geom.Rectangle2D;\r
26 import java.beans.PropertyChangeEvent;\r
27 import java.beans.PropertyChangeListener;\r
28 \r
29 import org.simantics.diagram.elements.TextNode;\r
30 import org.simantics.scenegraph.ISelectionPainterNode;\r
31 import org.simantics.scenegraph.g2d.events.ISGMouseEvent;\r
32 import org.simantics.scenegraph.utils.NodeUtil;\r
33 import org.simantics.sysdyn.ui.editor.routing.DependencyRouter;\r
34 import org.simantics.utils.datastructures.Pair;\r
35 \r
36 public class DependencyNode extends TextNode implements ISelectionPainterNode, MouseListener, MouseMotionListener {\r
37 \r
38     public static final String INSIDE = "Inside";\r
39     public static final String OUTSIDE = "Outside";\r
40     \r
41     private static final long serialVersionUID = 1294351381209071074L;\r
42 \r
43     private static final BasicStroke STROKE = new BasicStroke(1.0f);\r
44 \r
45     private Color color;\r
46     private Stroke stroke;\r
47     private Rectangle2D beginBounds;\r
48     private Rectangle2D endBounds;\r
49     private double angle = 0.1;\r
50     private String side;\r
51     private transient Pair<Arc2D, Path2D> shapes = new Pair<Arc2D, Path2D>(new Arc2D.Double(), new Path2D.Double());\r
52 \r
53     transient public boolean hover = false;\r
54 \r
55     private transient PropertyChangeListener fieldListener = null;\r
56 \r
57     @Override\r
58     public void init() {\r
59         super.init();\r
60         NodeUtil.getEventDelegator(this).addMouseListener(this);\r
61         NodeUtil.getEventDelegator(this).addMouseMotionListener(this);\r
62     }\r
63     \r
64     \r
65     public void init(String text, String side, Font font, Color color, double x, double y, double scale) {\r
66         super.init(text, font, color, x, y, scale);\r
67         this.side = side;\r
68     }\r
69 \r
70     @Override\r
71     public void cleanup() {\r
72         NodeUtil.getEventDelegator(this).removeMouseListener(this);\r
73         NodeUtil.getEventDelegator(this).removeMouseMotionListener(this);\r
74         super.cleanup();\r
75     }\r
76 \r
77     public void setFieldListener(PropertyChangeListener listener) {\r
78         this.fieldListener = listener;\r
79     }\r
80 \r
81     @ServerSide\r
82     public void commitProperty(String field, Object value) {\r
83         if(fieldListener != null) {\r
84             fieldListener.propertyChange(new PropertyChangeEvent(this, field, null, value));\r
85         }\r
86     }\r
87 \r
88     @PropertySetter("color")\r
89     @SyncField("color")\r
90     public void setColor(Color color) {\r
91         this.color = color;\r
92     }\r
93 \r
94     @PropertySetter("stroke")\r
95     @SyncField("stroke")\r
96     public void setStroke(Stroke stroke) {\r
97         this.stroke = stroke;\r
98     }\r
99 \r
100     @PropertySetter("beginBounds")\r
101     @SyncField("beginBounds")\r
102     public void setBeginBounds(Rectangle2D beginBounds) {\r
103         this.beginBounds = beginBounds;\r
104     }\r
105 \r
106     @PropertySetter("endBounds")\r
107     @SyncField("endBounds")\r
108     public void setEndBounds(Rectangle2D endBounds) {\r
109         this.endBounds = endBounds;\r
110     }\r
111 \r
112     @PropertySetter("angle")\r
113     @SyncField("angle")\r
114     public void setAngle(Double angle) {\r
115         this.angle = angle.doubleValue();\r
116         if(this.beginBounds != null && this.endBounds != null)\r
117             this.shapes = DependencyRouter.createArrowShape(this.shapes, this.beginBounds, this.endBounds, this.angle);\r
118     }\r
119 \r
120     @PropertySetter("shapes")\r
121     @SyncField("shapes")\r
122     public void setShapes(Pair<Arc2D, Path2D> shapes) {\r
123         this.shapes = shapes;\r
124     }\r
125 \r
126     public Color getColor() {\r
127         return color;\r
128     }\r
129 \r
130     public Stroke getStroke() {\r
131         return stroke;\r
132     }\r
133 \r
134     public Rectangle2D getBeginBounds() {\r
135         return beginBounds;\r
136     }\r
137 \r
138     public Rectangle2D getEndBounds() {\r
139         return endBounds;\r
140     }\r
141 \r
142     public double getAngle() {\r
143         return angle;\r
144     }\r
145 \r
146     public Pair<Arc2D, Path2D> getShapes() {\r
147         return shapes;\r
148     }\r
149 \r
150 \r
151 \r
152     @Override\r
153     public void render(Graphics2D g) {\r
154         if(beginBounds == null || endBounds == null) return;\r
155 \r
156         // Removed to let the global control handle rendering quality issues.\r
157         //g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
158 \r
159         boolean selected = NodeUtil.isSelected(this, 2);\r
160         if(selected) {\r
161             g.setColor(Color.PINK);\r
162             g.setStroke(STROKE);\r
163             g.draw(shapes.first);\r
164             g.fill(shapes.second);\r
165             if(color != null) g.setColor(color);\r
166             g.setStroke(stroke);\r
167             g.draw(shapes.first);\r
168             g.fill(shapes.second);\r
169         } else if (hover){\r
170             g.setColor(Color.LIGHT_GRAY);\r
171             g.setStroke(STROKE);\r
172             g.draw(shapes.first);\r
173             g.fill(shapes.second);\r
174             if(color != null) g.setColor(color);\r
175             g.setStroke(stroke);\r
176             g.draw(shapes.first);\r
177             g.fill(shapes.second);\r
178         } else {\r
179             if(color != null) g.setColor(color);\r
180             if(stroke != null) g.setStroke(stroke);\r
181             g.draw(shapes.first);\r
182             g.fill(shapes.second);\r
183         }\r
184 \r
185         \r
186         double angleRad = angle > 0 ? \r
187                 Math.toRadians(shapes.first.getAngleStart() + shapes.first.getAngleExtent()) : \r
188                     Math.toRadians(shapes.first.getAngleStart());\r
189         Point2D point = angle > 0 ? shapes.first.getEndPoint() : shapes.first.getStartPoint();\r
190         \r
191         int angle1 = 225;\r
192         int angle2 = -75;\r
193         if(OUTSIDE.equals(side)) {\r
194             angle1 *= -1;\r
195             angle2 *= -1;\r
196         }\r
197         double a = Math.toRadians(angle < 0 ? angle1 : angle2);\r
198         double s = Math.sin(a) * 2;\r
199         double c = Math.cos(a) * 3;\r
200         \r
201         g.translate(point.getX(), point.getY());\r
202         g.rotate(-angleRad);\r
203         g.translate(s, c);\r
204         g.rotate(angleRad);\r
205         super.render(g);\r
206         g.rotate(-angleRad);\r
207         g.translate(-s, -c);\r
208         g.rotate(angleRad);\r
209         g.translate(-point.getX(), -point.getY());\r
210         \r
211     }\r
212 \r
213     boolean pressHit = false;\r
214 \r
215     private boolean hitTest(MouseEvent event, double tolerance) {\r
216         if(event instanceof ISGMouseEvent) {\r
217             if(beginBounds == null || endBounds == null) return false;\r
218 \r
219             return Arcs.hitTest(beginBounds, endBounds, angle, ((ISGMouseEvent)event).getDoubleX(), ((ISGMouseEvent)event).getDoubleY(), tolerance);\r
220         } else {\r
221             return false;\r
222         }\r
223     }\r
224 \r
225     @Override\r
226     public Rectangle2D getBoundsInLocal() {\r
227         return null;\r
228     }\r
229 \r
230     @Override\r
231     public void mouseDragged(MouseEvent e) {\r
232         if(pressHit && e instanceof ISGMouseEvent) {\r
233             setAngle(Arcs.angleOfArc(\r
234                     beginBounds.getCenterX(), beginBounds.getCenterY(),\r
235                     ((ISGMouseEvent)e).getDoubleX(), ((ISGMouseEvent)e).getDoubleY(),\r
236                     endBounds.getCenterX(), endBounds.getCenterY()));\r
237         }\r
238     }\r
239 \r
240     @Override\r
241     public void mouseMoved(MouseEvent e) {\r
242         boolean hit = hitTest(e, 3.0);\r
243         if(hit != hover) {\r
244             hover = hit;\r
245             repaint();\r
246         }\r
247     }\r
248 \r
249     @Override\r
250     public void mouseClicked(MouseEvent e) {\r
251         // TODO Auto-generated method stub\r
252 \r
253     }\r
254 \r
255     @Override\r
256     public void mousePressed(MouseEvent e) {\r
257         boolean hit = hitTest(e, 3.0);\r
258         pressHit = hit;\r
259         if(hit) {\r
260             commitProperty("angle", angle);\r
261         }\r
262 \r
263     }\r
264 \r
265     @Override\r
266     public void mouseReleased(MouseEvent e) {\r
267         boolean hit = hitTest(e, 3.0);\r
268         if(hit) {\r
269             commitProperty("angle", angle);\r
270         }\r
271     }\r
272 \r
273     @Override\r
274     public void mouseEntered(MouseEvent e) {\r
275         // TODO Auto-generated method stub\r
276 \r
277     }\r
278 \r
279     @Override\r
280     public void mouseExited(MouseEvent e) {\r
281         // TODO Auto-generated method stub\r
282 \r
283     }\r
284 \r
285 }\r