]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/styles/DistrictNetworkStaticInfoStyle.java
ad72279772c94321c8e82de362492414464e0125
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / styles / DistrictNetworkStaticInfoStyle.java
1 package org.simantics.district.network.ui.styles;
2
3 import java.awt.geom.Point2D;
4 import java.util.Set;
5
6 import org.simantics.Simantics;
7 import org.simantics.db.ReadGraph;
8 import org.simantics.db.Resource;
9 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
10 import org.simantics.db.common.request.ResourceRead;
11 import org.simantics.db.exception.DatabaseException;
12 import org.simantics.db.layer0.exception.MissingVariableException;
13 import org.simantics.db.layer0.exception.MissingVariableValueException;
14 import org.simantics.db.layer0.exception.PendingVariableException;
15 import org.simantics.db.layer0.util.Layer0Utils;
16 import org.simantics.db.layer0.variable.Variable;
17 import org.simantics.db.layer0.variable.Variables;
18 import org.simantics.diagram.profile.StyleBase;
19 import org.simantics.diagram.stubs.DiagramResource;
20 import org.simantics.district.network.DistrictNetworkUtil;
21 import org.simantics.district.network.ontology.DistrictNetworkResource;
22 import org.simantics.district.network.profile.MidBranchEdgeSetRequest;
23 import org.simantics.district.network.ui.nodes.DeferredRenderingNode;
24 import org.simantics.district.network.ui.nodes.DistrictNetworkEdgeNode;
25 import org.simantics.district.network.ui.nodes.DistrictNetworkNodeUtils;
26 import org.simantics.district.network.ui.nodes.DistrictNetworkStaticInfoNode;
27 import org.simantics.layer0.Layer0;
28 import org.simantics.scenegraph.INode;
29 import org.simantics.scenegraph.ParentNode;
30 import org.simantics.scenegraph.g2d.IG2DNode;
31 import org.simantics.scenegraph.g2d.nodes.ConnectionNode;
32 import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;
33 import org.simantics.scenegraph.profile.EvaluationContext;
34 import org.simantics.scenegraph.profile.common.ProfileVariables;
35 import org.simantics.scenegraph.utils.NodeUtil;
36 import org.simantics.scl.compiler.top.ValueNotFound;
37 import org.simantics.scl.osgi.SCLOsgi;
38 import org.simantics.scl.runtime.SCLContext;
39 import org.simantics.scl.runtime.function.Function1;
40 import org.simantics.structural.stubs.StructuralResource2;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 public class DistrictNetworkStaticInfoStyle extends StyleBase<DistrictNetworkStaticInfoStyle.StyleResult> {
45
46     private static final Logger LOGGER = LoggerFactory.getLogger(DistrictNetworkStaticInfoStyle.class);
47
48         private static final String ACTIONS_MODULE = "Actions";
49         private static final String PIPELINE_INFO = "pipelineInfo";
50
51         public static final String STATIC_INFO_DEFERRED = "staticInfo";
52         
53         public static class StyleResult {
54                 public StyleResult(Point2D p1, Point2D p2, String info) {
55                         this.p1 = p1;
56                         this.p2 = p2;
57                         this.info = info;
58                 }
59                 
60                 public Point2D p1;
61                 public Point2D p2;
62                 public String info;
63         }
64         
65         public DistrictNetworkStaticInfoStyle(Resource style) {
66                 super(style);
67         }
68         
69         @Override
70         public StyleResult calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource mapElement)
71                         throws DatabaseException {
72                 DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
73                 
74                 boolean isEdge = graph.isInstanceOf(mapElement, DN.Edge);
75                 boolean isVertex = graph.isInstanceOf(mapElement, DN.Vertex);
76                 if (!isEdge && !isVertex)
77                         return null;
78                 
79                 if (isEdge) {
80                         Resource diagram = graph.getSingleObject(mapElement, Layer0.getInstance(graph).PartOf);
81                         Set<Resource> edgesToUse = graph.syncRequest(new MidBranchEdgeSetRequest(diagram), TransientCacheListener.instance());
82                         if (!edgesToUse.contains(mapElement))
83                                 return null;
84                 }
85                 
86                 DiagramResource DIA = DiagramResource.getInstance(graph);
87                 StructuralResource2 STR = StructuralResource2.getInstance(graph);
88                 
89                 Resource module = DistrictNetworkUtil.getMappedComponentCached(graph, mapElement);
90                 if (module == null)
91                         return null;
92
93                 Resource moduleType = graph.getPossibleType(module, STR.Component);
94                 if (moduleType == null)
95                         return null;
96                 
97                 Function1<Variable, String> function = getUCPipelineInfoFunctionCached(graph, moduleType);
98                 if (function == null)
99                         return null;
100                 
101                 String result;
102                 try {
103                         Variable variable = Variables.getVariable(graph, module);
104                         Variable moduleVariable = Variables.possibleActiveVariable(graph, variable);
105                         if (moduleVariable == null)
106                                 moduleVariable = variable;
107
108                         result = Simantics.applySCLRead(graph, function, moduleVariable);
109                 } catch (PendingVariableException | MissingVariableValueException e) {
110                         result = null;
111                 } catch (MissingVariableException e) {
112                     // the requested variable is missing from the UC
113                 String message = e.getMessage();
114                     LOGGER.warn("Missing variable for calculating style with function {} {}", function, message);
115                     result = "<" + message + ">";
116                 }
117                 
118                 if (isVertex) {
119                         double[] coords = graph.getRelatedValue(mapElement, DIA.HasLocation);
120                         Point2D p = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords[0], coords[1]), null);
121                         return new StyleResult(p, p, result);
122                 }
123                 else if (isEdge) {
124                         Resource v1 = graph.getSingleObject(mapElement, DN.HasStartVertex);
125                         double[] coords1 = graph.getRelatedValue(v1, DIA.HasLocation);
126                         Resource v2 = graph.getSingleObject(mapElement, DN.HasEndVertex);
127                         double[] coords2 = graph.getRelatedValue(v2, DIA.HasLocation);
128                         Point2D p1 = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords1[0], coords1[1]), null);
129                         Point2D p2 = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords2[0], coords2[1]), null);
130                         
131                         return new StyleResult(p1, p2, result);
132                 }
133                 
134                 return null;
135         }
136         
137         @Override
138         public void applyStyleForNode(EvaluationContext evaluationContext, INode parent, StyleResult result) {
139                 if (result == null) {
140                         cleanupStyleForNode(evaluationContext, parent);
141                         return;
142                 }
143                 
144                 ParentNode<?> root = (ParentNode<?>) NodeUtil.getNearestParentOfType(parent, RTreeNode.class);
145                 if (root != null) {
146                         DeferredRenderingNode deferred = ProfileVariables.claimChild(root, "", STATIC_INFO_DEFERRED, DeferredRenderingNode.class, evaluationContext);
147                         deferred.setZIndex(Integer.MAX_VALUE-1);
148                 }
149                 
150                 DistrictNetworkStaticInfoNode node = ProfileVariables.claimChild(parent, "*", DistrictNetworkStaticInfoNode.NODE_KEY, DistrictNetworkStaticInfoNode.class, evaluationContext);
151                 if (node == null)
152                         return;
153
154                 Point2D p1 = result.p1;
155                 Point2D p2 = result.p2;
156                 
157                 if (p1.equals(p2)) {
158                         node.setLocation(p1, new Point2D.Double(1.0, 0.0));
159                 }
160                 else {
161                         double sign = Math.signum(p1.getX() - p2.getX());
162                         Point2D.Double origin = new Point2D.Double(0.5 * (p1.getX() + p2.getX()), 0.5 * (p1.getY() + p2.getY()));
163                         Point2D direction = new Point2D.Double(0.5 * sign * (p1.getX() - p2.getX()), 0.5 * sign * (p1.getY() - p2.getY()));
164                         
165                         node.setLocation(origin, direction);
166                         
167                         for (IG2DNode n : ((ConnectionNode)parent).getNodes()) {
168                                 if (n instanceof DistrictNetworkEdgeNode) {
169                                         node.setEdgeNode((DistrictNetworkEdgeNode) n);
170                                 }
171                         }
172                 }
173                 
174                 node.setInfo(result.info);
175         }
176         
177         private static Function1<Variable, String> getUCPipelineInfoFunctionCached(ReadGraph graph, Resource componentType)
178                         throws DatabaseException {
179                 return graph.syncRequest(new UCPipelineInfoRequest(componentType), TransientCacheListener.instance());
180         }
181         
182         private static final class UCPipelineInfoRequest extends ResourceRead<Function1<Variable, String>> {
183                 public UCPipelineInfoRequest(Resource resource) {
184                         super(resource);
185                 }
186
187                 @SuppressWarnings("unchecked")
188                 @Override
189                 public Function1<Variable, String> perform(ReadGraph graph) throws DatabaseException {
190                         Resource actionsModule = Layer0Utils.getPossibleChild(graph, resource, ACTIONS_MODULE);
191                         if (actionsModule == null || !graph.isInstanceOf(actionsModule, Layer0.getInstance(graph).SCLModule))
192                                 return null;
193                         
194                         String uri = graph.getURI(actionsModule);
195                         SCLContext sclContext = SCLContext.getCurrent();
196                         Object oldGraph = sclContext.get("graph");
197                         try {
198                                 sclContext.put("graph", graph);
199                                 return (Function1<Variable, String>) SCLOsgi.MODULE_REPOSITORY.getValue(uri, PIPELINE_INFO);
200                         } catch (ValueNotFound e1) {
201                                 return null;
202                         } finally {
203                                 sclContext.put("graph", oldGraph);
204                         }
205                 }
206         }
207         
208         @Override
209         protected void cleanupStyleForNode(EvaluationContext evaluationContext, INode node) {
210                 ProfileVariables.denyChild(node, "*", DistrictNetworkStaticInfoNode.NODE_KEY);
211         }
212 }