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