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