]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/styles/DistrictNetworkHoverInfoStyle.java
bdb0b731350e4a2b526445a738704cd88d9825a0
[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.awt.geom.Rectangle2D;
5 import java.util.Collections;
6 import java.util.List;
7
8 import org.simantics.Simantics;
9 import org.simantics.databoard.Bindings;
10 import org.simantics.db.ReadGraph;
11 import org.simantics.db.Resource;
12 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
13 import org.simantics.db.common.request.ResourceRead;
14 import org.simantics.db.exception.DatabaseException;
15 import org.simantics.db.layer0.exception.MissingVariableException;
16 import org.simantics.db.layer0.exception.MissingVariableValueException;
17 import org.simantics.db.layer0.exception.PendingVariableException;
18 import org.simantics.db.layer0.util.Layer0Utils;
19 import org.simantics.db.layer0.variable.Variable;
20 import org.simantics.db.layer0.variable.Variables;
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.DistrictNetworkEdgeNode;
25 import org.simantics.district.network.ui.nodes.DistrictNetworkNodeUtils;
26 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
27 import org.simantics.layer0.Layer0;
28 import org.simantics.scenegraph.INode;
29 import org.simantics.scl.compiler.top.ValueNotFound;
30 import org.simantics.scl.osgi.SCLOsgi;
31 import org.simantics.scl.runtime.SCLContext;
32 import org.simantics.scl.runtime.function.Function1;
33 import org.simantics.scl.runtime.tuple.Tuple3;
34 import org.simantics.structural.stubs.StructuralResource2;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 public class DistrictNetworkHoverInfoStyle {
39
40     private static final Logger LOGGER = LoggerFactory.getLogger(DistrictNetworkHoverInfoStyle.class);
41
42     private static final String ACTIONS_MODULE = "Actions";
43     private static final String HOVER_CONTRIBUTION = "hoverContribution";
44
45     public static class StyleResult {
46         Point2D origin;
47         List<Tuple3> labels;
48
49         public StyleResult(Point2D origin, List<Tuple3> labels) {
50             this.origin = origin;
51             this.labels = labels;
52         }
53
54         public Point2D getOrigin() {
55             return origin;
56         }
57
58         public List<Tuple3> getLabels() {
59             return labels;
60         }
61     }
62
63     public static StyleResult doCalculateStyleResult(ReadGraph graph, Resource runtimeDiagram, Resource mapElement) throws DatabaseException {
64         DiagramResource DIA = DiagramResource.getInstance(graph);
65         StructuralResource2 STR = StructuralResource2.getInstance(graph);
66
67         String variableURI = graph.getPossibleRelatedValue(runtimeDiagram, DIA.RuntimeDiagram_HasVariable,
68                 Bindings.STRING);
69         Variable activeVariable = org.simantics.db.layer0.variable.Variables.getPossibleVariable(graph, variableURI);
70         if (activeVariable == null)
71             return null;
72
73         Resource module = DistrictNetworkUtil.getMappedComponentCached(graph, mapElement);
74         if (module == null)
75             return null;
76
77         Resource moduleType = graph.getPossibleType(module, STR.Component);
78         if (moduleType == null)
79             return null;
80
81         Function1<Variable, List<Tuple3>> function = getUCTextGridFunctionCached(graph, moduleType);
82         if (function == null)
83             return null;
84
85         List<Tuple3> result;
86         try {
87             Variable variable = Variables.getVariable(graph, module);
88             Variable moduleVariable = Variables.possibleActiveVariable(graph, variable);
89             if (moduleVariable == null)
90                 moduleVariable = variable;
91
92             result = Simantics.applySCLRead(graph, function, moduleVariable);
93         } catch (PendingVariableException | MissingVariableValueException e) {
94             result = Collections.singletonList(new Tuple3("<pending>", "", ""));
95         } catch (MissingVariableException e) {
96             // the requested variable is missing from the UC
97             String message = e.getMessage();
98             LOGGER.warn("Missing variable for calculating style with function {} {}", function, message);
99             result = Collections.singletonList(new Tuple3("<" + message + ">", "", ""));
100         }
101
102         Point2D point = calculatePoint(graph, mapElement);
103
104         return new StyleResult(point, result);
105     }
106
107     public static Point2D calculatePoint(ReadGraph graph, Resource mapElement) throws DatabaseException {
108         Point2D point;
109         DiagramResource DIA = DiagramResource.getInstance(graph);
110         DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
111         if (graph.isInstanceOf(mapElement, DN.Vertex)) {
112             double[] coords = graph.getRelatedValue(mapElement, DIA.HasLocation);
113             point = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords[0], coords[1]), null);
114         } else if (graph.isInstanceOf(mapElement, DN.Edge)) {
115             Resource v1 = graph.getSingleObject(mapElement, DN.HasStartVertex);
116             double[] coords1 = graph.getRelatedValue(v1, DIA.HasLocation);
117             Resource v2 = graph.getSingleObject(mapElement, DN.HasEndVertex);
118             double[] coords2 = graph.getRelatedValue(v2, DIA.HasLocation);
119             point = DistrictNetworkNodeUtils.calculatePoint2D(
120                     new Point2D.Double((coords1[0] + coords2[0]) / 2, (coords1[1] + coords2[1]) / 2), null);
121         } else {
122             return null;
123         }
124         return point;
125     }
126
127     public static Point2D calculatePoint(INode node, int zoomLevel) {
128         if (node instanceof DistrictNetworkVertexNode) {
129             DistrictNetworkVertexNode vertex = (DistrictNetworkVertexNode) node;
130             Rectangle2D b = vertex.getBounds();
131             return new Point2D.Double(b.getCenterX(), b.getCenterY());
132         } else if (node instanceof DistrictNetworkEdgeNode) {
133             DistrictNetworkEdgeNode edge = (DistrictNetworkEdgeNode) node;
134             return (Point2D) edge.getCenterPoint(zoomLevel).clone();
135         }
136         return null;
137     }
138
139     private static Function1<Variable, List<Tuple3>> getUCTextGridFunctionCached(ReadGraph graph, Resource componentType)
140              throws DatabaseException {
141         return graph.syncRequest(new UCTextGridFunctionRequest(componentType), TransientCacheListener.instance());
142     }
143
144     private static final class UCTextGridFunctionRequest extends ResourceRead<Function1<Variable, List<Tuple3>>> {
145         public UCTextGridFunctionRequest(Resource resource) {
146             super(resource);
147         }
148
149         @SuppressWarnings("unchecked")
150         @Override
151         public Function1<Variable, List<Tuple3>> perform(ReadGraph graph) throws DatabaseException {
152             Resource actionsModule = Layer0Utils.getPossibleChild(graph, resource, ACTIONS_MODULE);
153             if (actionsModule == null || !graph.isInstanceOf(actionsModule, Layer0.getInstance(graph).SCLModule))
154                 return null;
155
156             String uri = graph.getURI(actionsModule);
157             SCLContext sclContext = SCLContext.getCurrent();
158             Object oldGraph = sclContext.get("graph");
159             try {
160                 sclContext.put("graph", graph);
161                 return (Function1<Variable, List<Tuple3>>) SCLOsgi.MODULE_REPOSITORY.getValue(uri, HOVER_CONTRIBUTION);
162             } catch (ValueNotFound e1) {
163                 return null;
164             } finally {
165                 sclContext.put("graph", oldGraph);
166             }
167         }
168     }
169
170 }