Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / ConnectionNode.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in 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.scenegraph.g2d.nodes;\r
13 \r
14 import java.awt.Color;\r
15 import java.awt.Composite;\r
16 import java.awt.Stroke;\r
17 import java.awt.geom.Point2D;\r
18 \r
19 import org.simantics.diagram.connection.RouteGraph;\r
20 import org.simantics.scenegraph.INode;\r
21 import org.simantics.scenegraph.g2d.IG2DNode;\r
22 import org.simantics.scenegraph.g2d.events.MouseEvent;\r
23 import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;\r
24 import org.simantics.scenegraph.utils.InitValueSupport;\r
25 import org.simantics.scenegraph.utils.NodeUtil;\r
26 import org.simantics.scenegraph.utils.NodeUtil.NodeProcedure;\r
27 \r
28 /**\r
29  * @author Tuukka Lehtonen\r
30  */\r
31 public class ConnectionNode extends SingleElementNode implements InitValueSupport {\r
32 \r
33     private static final long serialVersionUID = 8657421058765967521L;\r
34 \r
35     private static class SetAlphaCompositeProcedure implements NodeProcedure<Object> {\r
36         public Composite composite;\r
37         @Override\r
38         public Object execute(INode node, String id) {\r
39             if (node instanceof EdgeNode)\r
40                 ((EdgeNode) node).setAlphaComposite(composite);\r
41 //          NodeUtil.setPropertyIfSupported("alpha", alphaComposite, edge);\r
42             return null;\r
43         }\r
44     };\r
45 \r
46     private static class SetDynamicStrokeProcedure implements NodeProcedure<Object> {\r
47         public Stroke stroke;\r
48         @Override\r
49         public Object execute(INode node, String id) {\r
50             if (node instanceof EdgeNode)\r
51                 ((EdgeNode) node).setDynamicStroke(stroke);\r
52             else if (node instanceof RouteGraphNode)\r
53                 ((RouteGraphNode) node).setDynamicStroke(stroke);\r
54 //          NodeUtil.setPropertyIfSupported("width", stroke, edge);\r
55             return null;\r
56         }\r
57     };\r
58 \r
59     private static class SetDynamicColorProcedure implements NodeProcedure<Object> {\r
60         public Color color;\r
61         @Override\r
62         public Object execute(INode node, String id) {\r
63             if (node instanceof EdgeNode)\r
64                 ((EdgeNode) node).setDynamicColor(color);\r
65             else if (node instanceof RouteGraphNode)\r
66                 ((RouteGraphNode) node).setDynamicColor(color);\r
67 //          NodeUtil.setPropertyIfSupported("color", color, edge);\r
68             return null;\r
69         }\r
70     };\r
71 \r
72 //    private static class SetValueProcedure implements NodeProcedure<Object> {\r
73 //        public String key;\r
74 //        public Object value;\r
75 //        @Override\r
76 //        public Object execute(INode node, String id) {\r
77 //            NodeUtil.setPropertyIfSupported(key, value, node);\r
78 ////            edge.setValue(key, value);\r
79 //            return null;\r
80 //        }\r
81 //    };\r
82 \r
83     private static final SetAlphaCompositeProcedure setAlphaCompositeProcedure = new SetAlphaCompositeProcedure();\r
84     private static final SetDynamicStrokeProcedure  setDynamicStrokeProcedure  = new SetDynamicStrokeProcedure();\r
85     private static final SetDynamicColorProcedure   setDynamicColorProcedure   = new SetDynamicColorProcedure();\r
86 \r
87     private static NodeProcedure<?> initValuesProcedure = new NodeProcedure<Object>() {\r
88         @Override\r
89         public Object execute(INode node, String id) {\r
90             if (node instanceof InitValueSupport)\r
91                 ((InitValueSupport) node).initValues();\r
92             return null;\r
93         }\r
94     };\r
95 \r
96     @PropertySetter("alpha")\r
97     public void setAlphaComposite(Composite alphaComposite) {\r
98         setAlphaCompositeProcedure.composite = alphaComposite;\r
99         forEdges(this, setAlphaCompositeProcedure);\r
100     }\r
101     \r
102     @PropertySetter("width")\r
103     public void setDynamicStroke(Stroke stroke) {\r
104         setDynamicStrokeProcedure.stroke = stroke;\r
105         forEdges(this, setDynamicStrokeProcedure);\r
106     }\r
107 \r
108     @PropertySetter("color")\r
109     public void setDynamicColor(Color color) {\r
110         setDynamicColorProcedure.color = color;\r
111         forEdges(this, setDynamicColorProcedure);\r
112     }\r
113 \r
114     @Override\r
115     public void initValues() {\r
116         NodeUtil.forChildren(this, initValuesProcedure, null);\r
117     }\r
118 \r
119     private void forEdges(SingleElementNode node, NodeProcedure<?> procedure) {\r
120         for (String childId : node.getSortedNodesById()) {\r
121             IG2DNode child = node.getNode(childId);\r
122             if (child instanceof SingleElementNode) {\r
123                 forEdges((SingleElementNode) child, procedure);\r
124             } else if (child instanceof EdgeNode) {\r
125                 procedure.execute(child, childId);\r
126             } else if (child instanceof RouteGraphNode) {\r
127                 procedure.execute(child, childId);\r
128             }\r
129         }\r
130     }\r
131 \r
132     @Override\r
133     protected boolean hitTest(MouseEvent event) {\r
134         if (!super.hitTest(event))\r
135             return false;\r
136 \r
137         Point2D pos = NodeUtil.worldToLocal(this, event.controlPosition, new Point2D.Double());\r
138         double tolerance = 0.5;\r
139         // TODO: change tolerance based on zoom level\r
140 \r
141         for (IG2DNode child : getSortedNodes()) {\r
142             if (child instanceof RouteGraphNode) {\r
143                 RouteGraphNode rgn = (RouteGraphNode) child;\r
144                 RouteGraph rg = rgn.getRouteGraph();\r
145                 Object pick = rg.pickLine(pos.getX(), pos.getY(), tolerance);\r
146                 if (pick != null)\r
147                     return true;\r
148             }\r
149         }\r
150         return false;\r
151     }\r
152 \r
153 }\r