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