]> gerrit.simantics Code Review - simantics/district.git/blob
8a4a143ce39050875d4d930b2f015420015024c8
[simantics/district.git] /
1 package org.simantics.district.network.ui.styles;
2
3 import java.awt.geom.Point2D;
4 import java.util.Set;
5
6 import org.simantics.Simantics;
7 import org.simantics.db.ReadGraph;
8 import org.simantics.db.Resource;
9 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
10 import org.simantics.db.common.request.ResourceRead;
11 import org.simantics.db.exception.DatabaseException;
12 import org.simantics.db.layer0.exception.MissingVariableException;
13 import org.simantics.db.layer0.exception.MissingVariableValueException;
14 import org.simantics.db.layer0.exception.PendingVariableException;
15 import org.simantics.db.layer0.util.Layer0Utils;
16 import org.simantics.db.layer0.variable.Variable;
17 import org.simantics.db.layer0.variable.Variables;
18 import org.simantics.diagram.profile.StyleBase;
19 import org.simantics.diagram.stubs.DiagramResource;
20 import org.simantics.district.network.DistrictNetworkUtil;
21 import org.simantics.district.network.ontology.DistrictNetworkResource;
22 import org.simantics.district.network.profile.MidBranchEdgeSetRequest;
23 import org.simantics.district.network.ui.nodes.DistrictNetworkNodeUtils;
24 import org.simantics.district.network.ui.nodes.DistrictNetworkStaticInfoNode;
25 import org.simantics.layer0.Layer0;
26 import org.simantics.scenegraph.INode;
27 import org.simantics.scenegraph.profile.EvaluationContext;
28 import org.simantics.scenegraph.profile.common.ProfileVariables;
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.structural.stubs.StructuralResource2;
34 import org.slf4j.LoggerFactory;
35 import org.slf4j.Logger;
36
37 public class DistrictNetworkStaticInfoStyle extends StyleBase<DistrictNetworkStaticInfoStyle.StyleResult> {
38
39     private static final Logger LOGGER = LoggerFactory.getLogger(DistrictNetworkStaticInfoStyle.class);
40
41         private static final String ACTIONS_MODULE = "Actions";
42         private static final String PIPELINE_INFO = "pipelineInfo";
43         
44         public static class StyleResult {
45                 public StyleResult(Point2D p1, Point2D p2, String info) {
46                         this.p1 = p1;
47                         this.p2 = p2;
48                         this.info = info;
49                 }
50                 
51                 public Point2D p1;
52                 public Point2D p2;
53                 public String info;
54         }
55         
56         public DistrictNetworkStaticInfoStyle(Resource style) {
57                 super(style);
58         }
59         
60         @Override
61         public StyleResult calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource mapElement)
62                         throws DatabaseException {
63                 DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
64                 
65                 boolean isEdge = graph.isInstanceOf(mapElement, DN.Edge);
66                 boolean isVertex = graph.isInstanceOf(mapElement, DN.Vertex);
67                 if (!isEdge && !isVertex)
68                         return null;
69                 
70                 if (isEdge) {
71                         Resource diagram = graph.getSingleObject(mapElement, Layer0.getInstance(graph).PartOf);
72                         Set<Resource> edgesToUse = graph.syncRequest(new MidBranchEdgeSetRequest(diagram), TransientCacheListener.instance());
73                         if (!edgesToUse.contains(mapElement))
74                                 return null;
75                 }
76                 
77                 DiagramResource DIA = DiagramResource.getInstance(graph);
78                 StructuralResource2 STR = StructuralResource2.getInstance(graph);
79                 
80                 Resource module = DistrictNetworkUtil.getMappedComponentCached(graph, mapElement);
81                 if (module == null)
82                         return null;
83
84                 Resource moduleType = graph.getPossibleType(module, STR.Component);
85                 if (moduleType == null)
86                         return null;
87                 
88                 Function1<Variable, String> function = getUCPipelineInfoFunctionCached(graph, moduleType);
89                 if (function == null)
90                         return null;
91                 
92                 String result;
93                 try {
94                         Variable variable = Variables.getVariable(graph, module);
95                         Variable moduleVariable = Variables.possibleActiveVariable(graph, variable);
96                         if (moduleVariable == null)
97                                 moduleVariable = variable;
98
99                         result = Simantics.applySCLRead(graph, function, moduleVariable);
100                 } catch (PendingVariableException | MissingVariableValueException e) {
101                         result = null;
102                 } catch (MissingVariableException e) {
103                     // the requested variable is missing from the UC
104                 String message = e.getMessage();
105                     LOGGER.warn("Missing variable for calculating style with function {} {}", function, message);
106                     result = "<" + message + ">";
107                 }
108                 
109                 if (isVertex) {
110                         double[] coords = graph.getRelatedValue(mapElement, DIA.HasLocation);
111                         Point2D p = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords[0], coords[1]), null);
112                         return new StyleResult(p, p, result);
113                 }
114                 else if (isEdge) {
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                         Point2D p1 = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords1[0], coords1[1]), null);
120                         Point2D p2 = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords2[0], coords2[1]), null);
121                         
122                         return new StyleResult(p1, p2, result);
123                 }
124                 
125                 return null;
126         }
127         
128         @Override
129         public void applyStyleForNode(EvaluationContext evaluationContext, INode parent, StyleResult result) {
130                 if (result == null) {
131                         cleanupStyleForNode(evaluationContext, parent);
132                         return;
133                 }
134                 
135                 DistrictNetworkStaticInfoNode node = ProfileVariables.claimChild(parent, "*", DistrictNetworkStaticInfoNode.NODE_KEY, DistrictNetworkStaticInfoNode.class, evaluationContext);
136                 if (node == null)
137                         return;
138
139                 Point2D p1 = result.p1;
140                 Point2D p2 = result.p2;
141                 
142                 if (p1.equals(p2)) {
143                         node.setLocation(p1, new Point2D.Double(1.0, 0.0));
144                 }
145                 else {
146                         double sign = Math.signum(p1.getX() - p2.getX());
147                         Point2D.Double origin = new Point2D.Double(0.5 * (p1.getX() + p2.getX()), 0.5 * (p1.getY() + p2.getY()));
148                         Point2D direction = new Point2D.Double(0.5 * sign * (p1.getX() - p2.getX()), 0.5 * sign * (p1.getY() - p2.getY()));
149                         
150                         node.setLocation(origin, direction);
151                 }
152                 
153                 node.setInfo(result.info);
154         }
155         
156         private static Function1<Variable, String> getUCPipelineInfoFunctionCached(ReadGraph graph, Resource componentType)
157                         throws DatabaseException {
158                 return graph.syncRequest(new UCPipelineInfoRequest(componentType), TransientCacheListener.instance());
159         }
160         
161         private static final class UCPipelineInfoRequest extends ResourceRead<Function1<Variable, String>> {
162                 public UCPipelineInfoRequest(Resource resource) {
163                         super(resource);
164                 }
165
166                 @SuppressWarnings("unchecked")
167                 @Override
168                 public Function1<Variable, String> perform(ReadGraph graph) throws DatabaseException {
169                         Resource actionsModule = Layer0Utils.getPossibleChild(graph, resource, ACTIONS_MODULE);
170                         if (actionsModule == null || !graph.isInstanceOf(actionsModule, Layer0.getInstance(graph).SCLModule))
171                                 return null;
172                         
173                         String uri = graph.getURI(actionsModule);
174                         SCLContext sclContext = SCLContext.getCurrent();
175                         Object oldGraph = sclContext.get("graph");
176                         try {
177                                 sclContext.put("graph", graph);
178                                 return (Function1<Variable, String>) SCLOsgi.MODULE_REPOSITORY.getValue(uri, PIPELINE_INFO);
179                         } catch (ValueNotFound e1) {
180                                 return null;
181                         } finally {
182                                 sclContext.put("graph", oldGraph);
183                         }
184                 }
185         }
186         
187         @Override
188         protected void cleanupStyleForNode(EvaluationContext evaluationContext, INode node) {
189                 ProfileVariables.denyChild(node, "*", DistrictNetworkStaticInfoNode.NODE_KEY);
190         }
191 }