1 package org.simantics.district.network.ui.styles;
3 import java.awt.geom.Point2D;
4 import java.util.Collections;
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.stubs.DiagramResource;
21 import org.simantics.district.network.DistrictNetworkUtil;
22 import org.simantics.district.network.ontology.DistrictNetworkResource;
23 import org.simantics.district.network.ui.nodes.DistrictNetworkEdgeNode;
24 import org.simantics.district.network.ui.nodes.DistrictNetworkNodeUtils;
25 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
26 import org.simantics.layer0.Layer0;
27 import org.simantics.scenegraph.INode;
28 import org.simantics.scl.compiler.top.ValueNotFound;
29 import org.simantics.scl.osgi.SCLOsgi;
30 import org.simantics.scl.runtime.SCLContext;
31 import org.simantics.scl.runtime.function.Function1;
32 import org.simantics.scl.runtime.tuple.Tuple3;
33 import org.simantics.structural.stubs.StructuralResource2;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 public class DistrictNetworkHoverInfoStyle {
39 private static final Logger LOGGER = LoggerFactory.getLogger(DistrictNetworkHoverInfoStyle.class);
41 private static final String ACTIONS_MODULE = "Actions";
42 private static final String HOVER_CONTRIBUTION = "hoverContribution";
44 public static class StyleResult {
48 public StyleResult(Point2D origin, List<Tuple3> labels) {
53 public Point2D getOrigin() {
57 public List<Tuple3> getLabels() {
62 public static StyleResult doCalculateStyleResult(ReadGraph graph, Resource runtimeDiagram, Resource mapElement) throws DatabaseException {
63 DiagramResource DIA = DiagramResource.getInstance(graph);
64 StructuralResource2 STR = StructuralResource2.getInstance(graph);
66 String variableURI = graph.getPossibleRelatedValue(runtimeDiagram, DIA.RuntimeDiagram_HasVariable,
68 Variable activeVariable = org.simantics.db.layer0.variable.Variables.getPossibleVariable(graph, variableURI);
69 if (activeVariable == null)
72 Resource module = DistrictNetworkUtil.getMappedComponentCached(graph, mapElement);
76 Resource moduleType = graph.getPossibleType(module, STR.Component);
77 if (moduleType == null)
80 Function1<Variable, List<Tuple3>> function = getUCTextGridFunctionCached(graph, moduleType);
86 Variable variable = Variables.getVariable(graph, module);
87 Variable moduleVariable = Variables.possibleActiveVariable(graph, variable);
88 if (moduleVariable == null)
89 moduleVariable = variable;
91 result = Simantics.applySCLRead(graph, function, moduleVariable);
92 } catch (PendingVariableException | MissingVariableValueException e) {
93 result = Collections.singletonList(new Tuple3("<pending>", "", ""));
94 } catch (MissingVariableException e) {
95 // the requested variable is missing from the UC
96 String message = e.getMessage();
97 LOGGER.warn("Missing variable for calculating style with function {} {}", function, message);
98 result = Collections.singletonList(new Tuple3("<" + message + ">", "", ""));
101 Point2D point = calculatePoint(graph, mapElement);
103 return new StyleResult(point, result);
106 public static Point2D calculatePoint(ReadGraph graph, Resource mapElement) throws DatabaseException {
108 DiagramResource DIA = DiagramResource.getInstance(graph);
109 DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
110 if (graph.isInstanceOf(mapElement, DN.Vertex)) {
111 double[] coords = graph.getRelatedValue(mapElement, DIA.HasLocation);
112 point = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords[0], coords[1]), null);
113 } else if (graph.isInstanceOf(mapElement, DN.Edge)) {
114 Resource v1 = graph.getSingleObject(mapElement, DN.HasStartVertex);
115 double[] coords1 = graph.getRelatedValue(v1, DIA.HasLocation);
116 Resource v2 = graph.getSingleObject(mapElement, DN.HasEndVertex);
117 double[] coords2 = graph.getRelatedValue(v2, DIA.HasLocation);
118 point = DistrictNetworkNodeUtils.calculatePoint2D(
119 new Point2D.Double((coords1[0] + coords2[0]) / 2, (coords1[1] + coords2[1]) / 2), null);
126 public static Point2D calculatePoint(INode node, int zoomLevel, Point2D result) {
127 if (node instanceof DistrictNetworkVertexNode) {
128 DistrictNetworkVertexNode vertex = (DistrictNetworkVertexNode) node;
129 return DistrictNetworkNodeUtils.calculatePoint2D(vertex.getVertex().getPoint(), result);
130 } else if (node instanceof DistrictNetworkEdgeNode) {
131 DistrictNetworkEdgeNode edge = (DistrictNetworkEdgeNode) node;
132 Point2D cp = edge.getCenterPoint(zoomLevel);
134 result = new Point2D.Double();
135 result.setLocation(cp);
141 private static Function1<Variable, List<Tuple3>> getUCTextGridFunctionCached(ReadGraph graph, Resource componentType)
142 throws DatabaseException {
143 return graph.syncRequest(new UCTextGridFunctionRequest(componentType), TransientCacheListener.instance());
146 private static final class UCTextGridFunctionRequest extends ResourceRead<Function1<Variable, List<Tuple3>>> {
147 public UCTextGridFunctionRequest(Resource resource) {
151 @SuppressWarnings("unchecked")
153 public Function1<Variable, List<Tuple3>> perform(ReadGraph graph) throws DatabaseException {
154 Resource actionsModule = Layer0Utils.getPossibleChild(graph, resource, ACTIONS_MODULE);
155 if (actionsModule == null || !graph.isInstanceOf(actionsModule, Layer0.getInstance(graph).SCLModule))
158 String uri = graph.getURI(actionsModule);
159 SCLContext sclContext = SCLContext.getCurrent();
160 Object oldGraph = sclContext.get("graph");
162 sclContext.put("graph", graph);
163 return (Function1<Variable, List<Tuple3>>) SCLOsgi.MODULE_REPOSITORY.getValue(uri, HOVER_CONTRIBUTION);
164 } catch (ValueNotFound e1) {
167 sclContext.put("graph", oldGraph);