1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.sysdyn.ui.elements2.connections;
\r
14 import java.awt.BasicStroke;
\r
15 import java.awt.Color;
\r
16 import java.awt.Font;
\r
17 import java.awt.Shape;
\r
18 import java.awt.Stroke;
\r
19 import java.awt.geom.Path2D;
\r
20 import java.awt.geom.Rectangle2D;
\r
21 import java.beans.PropertyChangeEvent;
\r
22 import java.beans.PropertyChangeListener;
\r
23 import java.util.HashMap;
\r
24 import java.util.Map;
\r
26 import org.simantics.db.Resource;
\r
27 import org.simantics.g2d.diagram.DiagramHints;
\r
28 import org.simantics.g2d.diagram.DiagramMutator;
\r
29 import org.simantics.g2d.diagram.DiagramUtils;
\r
30 import org.simantics.g2d.diagram.IDiagram;
\r
31 import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;
\r
32 import org.simantics.g2d.diagram.handler.Topology;
\r
33 import org.simantics.g2d.diagram.handler.Topology.Connection;
\r
34 import org.simantics.g2d.element.ElementClass;
\r
35 import org.simantics.g2d.element.ElementHints;
\r
36 import org.simantics.g2d.element.ElementUtils;
\r
37 import org.simantics.g2d.element.IElement;
\r
38 import org.simantics.g2d.element.SceneGraphNodeKey;
\r
39 import org.simantics.g2d.element.handler.EdgeVisuals;
\r
40 import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd;
\r
41 import org.simantics.g2d.element.handler.Pick;
\r
42 import org.simantics.g2d.element.handler.SceneGraph;
\r
43 import org.simantics.g2d.element.handler.TerminalLayout;
\r
44 import org.simantics.g2d.element.handler.Transform;
\r
45 import org.simantics.g2d.element.handler.impl.ConfigurableEdgeVisuals;
\r
46 import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;
\r
47 import org.simantics.g2d.element.handler.impl.FillColorImpl;
\r
48 import org.simantics.g2d.element.handler.impl.ParentImpl;
\r
49 import org.simantics.g2d.element.handler.impl.SimpleElementLayers;
\r
50 import org.simantics.g2d.element.handler.impl.TextColorImpl;
\r
51 import org.simantics.g2d.element.handler.impl.TextFontImpl;
\r
52 import org.simantics.g2d.element.handler.impl.TextImpl;
\r
53 import org.simantics.g2d.elementclass.connection.EdgeClass.EdgeHandler;
\r
54 import org.simantics.g2d.elementclass.connection.EdgeClass.FixedTransform;
\r
55 import org.simantics.g2d.utils.Alignment;
\r
56 import org.simantics.scenegraph.g2d.G2DParentNode;
\r
57 import org.simantics.scenegraph.utils.NodeUtil;
\r
58 import org.simantics.sysdyn.ui.editor.routing.DependencyRouter;
\r
59 import org.simantics.utils.datastructures.Callback;
\r
60 import org.simantics.utils.datastructures.Pair;
\r
61 import org.simantics.utils.datastructures.hints.IHintContext.Key;
\r
63 public class DependencyEdgeClass {
\r
65 public static class NodePick implements Pick {
\r
67 private static final long serialVersionUID = 1L;
\r
70 public boolean pickTest(IElement e, Shape s, PickPolicy policy) {
\r
71 Rectangle2D pickRect = null;
\r
72 if (s instanceof Rectangle2D)
\r
73 pickRect = (Rectangle2D) s;
\r
75 // FIXME: suboptimal, but works.
\r
76 pickRect = s.getBounds2D();
\r
78 DependencyNode node = e.getHint(SysdynEdgeSceneGraph.KEY_SG_NODE);
\r
80 System.out.println("pickTest no node!");
\r
83 return Arcs.hitTest(node.getBeginBounds(), node.getEndBounds(), node.getAngle(), pickRect.getCenterX(), pickRect.getCenterY(), 3.0);
\r
89 // TODO scale, rotate, move, transform
\r
90 public static final ElementClass CLASS =
\r
91 ElementClass.compile(
\r
92 SysdynEdgeSceneGraph.INSTANCE,
\r
93 EdgeHandler.INSTANCE,
\r
94 ConfigurableEdgeVisuals.DEFAULT,
\r
95 FillColorImpl.BLACK,
\r
96 FixedTransform.INSTANCE,
\r
98 TextColorImpl.BLACK,
\r
99 TextFontImpl.DEFAULT,
\r
101 ConnectionSelectionOutline.INSTANCE,
\r
102 SimpleElementLayers.INSTANCE,
\r
103 ParentImpl.INSTANCE
\r
104 ).setId("EdgeClass.STRAIGHT");
\r
106 public static class SysdynEdgeSceneGraph implements SceneGraph {
\r
108 private static final long serialVersionUID = 2914383071126238996L;
\r
110 public static final SysdynEdgeSceneGraph INSTANCE = new SysdynEdgeSceneGraph();
\r
112 public static final Stroke ARROW_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
\r
114 public static final Key KEY_SG_NODE = new SceneGraphNodeKey(DependencyNode.class, "EDGE_NODE");
\r
117 public void init(IElement e, G2DParentNode parent) {
\r
118 DependencyNode node = ElementUtils.getOrCreateNode(e, parent, KEY_SG_NODE, "edge_" + e.hashCode(), DependencyNode.class);
\r
120 Font font = ElementUtils.getTextFont(e);
\r
121 Color color = ElementUtils.getTextColor(e);
\r
123 HashMap<String, Object> properties = e.getHint(DiagramHints.PROPERTIES);
\r
124 Pair<?, ?> polarityPair = (Pair<?, ?>)properties.get("Polarity");
\r
125 Pair<?, ?> polarityLocationPair = (Pair<?, ?>)properties.get("PolarityLocation");
\r
128 if(polarityLocationPair == null)
\r
129 location = DependencyNode.INSIDE;
\r
131 location = (String) polarityLocationPair.second;
\r
133 if(polarityPair != null)
\r
134 node.init((String) polarityPair.second, location, font, color, 0, 0, 0.235);
\r
140 public void cleanup(IElement e) {
\r
141 ElementUtils.removePossibleNode(e, KEY_SG_NODE);
\r
144 public void update(final IElement e) {
\r
146 DependencyNode node = e.getHint(KEY_SG_NODE);
\r
147 if(node == null) return;
\r
148 final IDiagram diagram = ElementUtils.peekDiagram(e);
\r
150 node.setFieldListener(new PropertyChangeListener() {
\r
153 public void propertyChange(final PropertyChangeEvent event) {
\r
155 String field = event.getPropertyName();
\r
156 Map<String, Pair<Resource, Object>> properties = e.getHint(DiagramHints.PROPERTIES);
\r
157 if(properties == null) return;
\r
158 final Pair<Resource, Object> property = properties.get(field);
\r
159 if(property == null) return;
\r
161 DiagramUtils.mutateDiagram(diagram, new Callback<DiagramMutator>() {
\r
164 public void run(DiagramMutator mutator) {
\r
165 mutator.modifyProperty(e, property.first, event.getNewValue());
\r
176 Shape beginTerminalShape = null;
\r
177 Shape endTerminalShape = null;
\r
178 if (diagram != null) {
\r
179 Topology topology = diagram.getDiagramClass().getAtMostOneItemOfClass(Topology.class);
\r
180 if (topology != null) {
\r
181 Connection beginConnection = topology.getConnection(e, EdgeEnd.Begin);
\r
182 Connection endConnection = topology.getConnection(e, EdgeEnd.End);
\r
183 beginTerminalShape = getCanvasTerminalShape(beginConnection);
\r
184 endTerminalShape = getCanvasTerminalShape(endConnection);
\r
188 if(beginTerminalShape == null || endTerminalShape == null) return;
\r
190 EdgeVisuals vh = e.getElementClass().getSingleItem(EdgeVisuals.class);
\r
191 Stroke stroke = vh.getStroke(e);
\r
192 Font font = ElementUtils.getTextFont(e);
\r
193 Color color = ElementUtils.getTextColor(e);
\r
194 // Color fillColor = ElementUtils.getFillColor(e);
\r
195 Color borderColor = ElementUtils.getBorderColor(e, Color.BLACK);
\r
196 // String text = ElementUtils.getText(e);
\r
197 Alignment hAlign = ElementUtils.getHintOrDefault(e, ElementHints.KEY_HORIZONTAL_ALIGN, Alignment.CENTER);
\r
198 node.setBackgroundColor(null);
\r
199 node.setBorderColor(borderColor);
\r
200 node.setHorizontalAlignment((byte) hAlign.ordinal());
\r
201 node.setPadding(0, 0);
\r
202 node.setBorderWidth((float) 0);
\r
203 node.setEditable(false);
\r
204 node.setFont(font);
\r
206 node.setBeginBounds(beginTerminalShape.getBounds2D());
\r
207 node.setEndBounds(endTerminalShape.getBounds2D());
\r
208 node.setStroke(stroke);
\r
209 node.setColor(color);
\r
210 node.setShapes(DependencyRouter.createArrowShape(node.getShapes(), node.getBeginBounds(), node.getEndBounds(), node.getAngle()));
\r
212 Map<String, Pair<Resource, Object>> properties = e.getHint(DiagramHints.PROPERTIES);
\r
213 if(properties != null) {
\r
214 for(Map.Entry<String, Pair<Resource, Object>> entry : properties.entrySet()) {
\r
215 NodeUtil.setPropertyIfSupported(entry.getKey(), entry.getValue().second, node);
\r
216 // node.setProperty(entry.getKey(), entry.getValue().second);
\r
217 // System.out.println("setProperty " + entry.getKey() + " => " + entry.getValue().second);
\r
220 EdgeHandler eh = e.getElementClass().getAtMostOneItemOfClass(EdgeHandler.class);
\r
221 Path2D path = eh.getPath(e);
\r
223 path = new Path2D.Double();
\r
226 path.append(node.getShapes().first, false);
\r
227 eh.setPath(e, path);
\r
231 private static Shape getCanvasTerminalShape(Connection connection) {
\r
232 if (connection != null && connection.node != null && connection.terminal != null) {
\r
233 TerminalLayout layout = connection.node.getElementClass().getAtMostOneItemOfClass(TerminalLayout.class);
\r
234 if (layout != null) {
\r
235 //return layout.getTerminalShape(connection.node, connection.terminal);
\r
236 Shape shp = layout.getTerminalShape(connection.node, connection.terminal);
\r
237 Transform tr = connection.node.getElementClass().getAtMostOneItemOfClass(Transform.class);
\r
241 return tr.getTransform(connection.node).createTransformedShape(shp);
\r