package org.simantics.district.network.ui.nodes; import java.awt.geom.Point2D; import java.util.Set; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.request.ResourceRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.exception.MissingVariableValueException; import org.simantics.db.layer0.exception.PendingVariableException; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.layer0.variable.Variables; import org.simantics.diagram.profile.StyleBase; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.district.network.DistrictNetworkUtil; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.district.network.profile.MidBranchEdgeSetRequest; import org.simantics.layer0.Layer0; import org.simantics.scenegraph.INode; import org.simantics.scenegraph.profile.EvaluationContext; import org.simantics.scenegraph.profile.common.ProfileVariables; import org.simantics.scl.compiler.top.ValueNotFound; import org.simantics.scl.osgi.SCLOsgi; import org.simantics.scl.runtime.SCLContext; import org.simantics.scl.runtime.function.Function1; import org.simantics.structural.stubs.StructuralResource2; public class DistrictNetworkStaticInfoStyle extends StyleBase { private static final String ACTIONS_MODULE = "Actions"; private static final String PIPELINE_INFO = "pipelineInfo"; public static class StyleResult { public StyleResult(Point2D p1, Point2D p2, String info) { this.p1 = p1; this.p2 = p2; this.info = info; } public Point2D p1; public Point2D p2; public String info; } public DistrictNetworkStaticInfoStyle(Resource style) { super(style); } @Override public StyleResult calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource mapElement) throws DatabaseException { DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); if (!graph.isInstanceOf(mapElement, DN.Edge)) return null; Resource diagram = graph.getSingleObject(mapElement, Layer0.getInstance(graph).PartOf); Set edgesToUse = graph.syncRequest(new MidBranchEdgeSetRequest(diagram), TransientCacheListener.instance()); if (!edgesToUse.contains(mapElement)) return null; DiagramResource DIA = DiagramResource.getInstance(graph); StructuralResource2 STR = StructuralResource2.getInstance(graph); Resource module = DistrictNetworkUtil.getMappedComponentCached(graph, mapElement); if (module == null) return null; Resource moduleType = graph.getPossibleType(module, STR.Component); if (moduleType == null) return null; Function1 function = getUCPipelineInfoFunctionCached(graph, moduleType); if (function == null) return null; String result; try { Variable variable = Variables.getVariable(graph, module); Variable moduleVariable = Variables.possibleActiveVariable(graph, variable); if (moduleVariable == null) moduleVariable = variable; result = Simantics.applySCLRead(graph, function, moduleVariable); } catch (PendingVariableException | MissingVariableValueException e) { result = null; } Resource v1 = graph.getSingleObject(mapElement, DN.HasStartVertex); double[] coords1 = graph.getRelatedValue(v1, DIA.HasLocation); Resource v2 = graph.getSingleObject(mapElement, DN.HasEndVertex); double[] coords2 = graph.getRelatedValue(v2, DIA.HasLocation); Point2D p1 = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords1[0], coords1[1]), null); Point2D p2 = DistrictNetworkNodeUtils.calculatePoint2D(new Point2D.Double(coords2[0], coords2[1]), null); return new StyleResult(p1, p2, result); } @Override public void applyStyleForNode(EvaluationContext evaluationContext, INode parent, StyleResult result) { if (result == null) { cleanupStyleForNode(evaluationContext, parent); return; } DistrictNetworkStaticInfoNode node = ProfileVariables.claimChild(parent, "*", DistrictNetworkStaticInfoNode.NODE_KEY, DistrictNetworkStaticInfoNode.class, evaluationContext); if (node == null) return; Point2D p1 = result.p1; Point2D p2 = result.p2; double sign = Math.signum(p1.getX() - p2.getX()); Point2D.Double origin = new Point2D.Double(0.5 * (p1.getX() + p2.getX()), 0.5 * (p1.getY() + p2.getY())); Point2D direction = new Point2D.Double(0.5 * sign * (p1.getX() - p2.getX()), 0.5 * sign * (p1.getY() - p2.getY())); node.setLocation(origin, direction); node.setInfo(result.info); } private static Function1 getUCPipelineInfoFunctionCached(ReadGraph graph, Resource componentType) throws DatabaseException { return graph.syncRequest(new UCPipelineInfoRequest(componentType), TransientCacheListener.instance()); } private static final class UCPipelineInfoRequest extends ResourceRead> { public UCPipelineInfoRequest(Resource resource) { super(resource); } @SuppressWarnings("unchecked") @Override public Function1 perform(ReadGraph graph) throws DatabaseException { Resource actionsModule = Layer0Utils.getPossibleChild(graph, resource, ACTIONS_MODULE); if (actionsModule == null || !graph.isInstanceOf(actionsModule, Layer0.getInstance(graph).SCLModule)) return null; String uri = graph.getURI(actionsModule); SCLContext sclContext = SCLContext.getCurrent(); Object oldGraph = sclContext.get("graph"); try { sclContext.put("graph", graph); return (Function1) SCLOsgi.MODULE_REPOSITORY.getValue(uri, PIPELINE_INFO); } catch (ValueNotFound e1) { return null; } finally { sclContext.put("graph", oldGraph); } } } @Override protected void cleanupStyleForNode(EvaluationContext evaluationContext, INode node) { ProfileVariables.denyChild(node, DistrictNetworkStaticInfoNode.NODE_KEY); } }