1 /*******************************************************************************
2 * Copyright (c) 2017 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Semantum Oy - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling.adapters;
14 import java.awt.geom.AffineTransform;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
21 import org.simantics.Simantics;
22 import org.simantics.db.ReadGraph;
23 import org.simantics.db.Resource;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.db.layer0.variable.Variable;
26 import org.simantics.db.layer0.variable.Variables;
27 import org.simantics.diagram.profile.StyleBase;
28 import org.simantics.diagram.stubs.DiagramResource;
29 import org.simantics.scenegraph.INode;
30 import org.simantics.scenegraph.g2d.G2DNodeModification;
31 import org.simantics.scenegraph.g2d.IG2DNode;
32 import org.simantics.scenegraph.g2d.nodes.ConnectionNode;
33 import org.simantics.scenegraph.g2d.nodes.SVGNode;
34 import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment;
35 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
36 import org.simantics.scenegraph.g2d.nodes.TargetedSVGNodeAssignment;
37 import org.simantics.scenegraph.g2d.nodes.TransformationAssignment;
38 import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
39 import org.simantics.scenegraph.profile.EvaluationContext;
40 import org.simantics.scenegraph.utils.NodeUtil;
41 import org.simantics.scl.runtime.function.Function;
42 import org.simantics.structural.stubs.StructuralResource2;
43 import org.simantics.utils.datastructures.Pair;
46 * @author Antti Villberg
49 public class SymbolCodeStyle extends StyleBase<Pair<G2DNodeModification, Object>> {
52 public Pair<G2DNodeModification, Object> calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException {
53 DiagramResource DIA = DiagramResource.getInstance(graph);
55 // Find a component for the element
56 Variable elementVariable = Variables.getPossibleVariable(graph, element);
57 if (elementVariable == null)
59 Object modi = elementVariable.getPossiblePropertyValue(graph, DIA.symbolCode);
61 if(graph.isInstanceOf(element, DIA.RouteGraphConnection)) {
62 StructuralResource2 STR = StructuralResource2.getInstance(graph);
63 Resource connectionType = graph.getPossibleObject(element, STR.HasConnectionType);
64 if(connectionType != null) {
65 Variable connectionTypeVariable = Variables.getPossibleVariable(graph, connectionType);
66 Function fn = connectionTypeVariable.getPossiblePropertyValue(graph, DIA.symbolFunction);
67 modi = Simantics.applySCLRead(graph, fn, elementVariable);
72 if(modi == null) return null;
74 // If element is moved, recalculate style
75 Object transform = graph.getPossibleRelatedValue(element, DIA.HasTransform);
77 if (modi instanceof G2DNodeModification) {
78 return Pair.make((G2DNodeModification)modi, transform);
79 } else if (modi instanceof List) {
80 @SuppressWarnings("unchecked")
81 List<String> styles = (List<String>)modi;
82 List<SVGNodeAssignment> assignments = new ArrayList<>(styles.size()/3);
83 for (int i = 0; i < styles.size()/3; i++)
84 assignments.add(new SVGNodeAssignment(styles.get(3*i), styles.get(3*i+1), styles.get(3*i+2)));
85 return Pair.make(new G2DNodeModification(assignments, Collections.emptyList()), transform);
87 throw new DatabaseException("Invalid symbolCode value: " + modi);
91 private Map<Object,SingleElementNode> buildSingleElementMap(INode node) {
92 Map<Object,SingleElementNode> elements = new HashMap<>();
93 NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
94 elements.put(n.getKey(), n);
101 public void applyStyleForNode(EvaluationContext evaluationContext, INode node, Pair<G2DNodeModification, Object> result) {
103 if (result == null || result.first == null)
106 Map<Object,SingleElementNode> elements = null;
108 G2DNodeModification modification = result.first;
110 if(node instanceof ConnectionNode) {
112 if (modification.svgAssignments != null && !modification.svgAssignments.isEmpty()) {
113 INode child = NodeUtil.getFirstChild(node);
114 if(child instanceof RouteGraphNode) {
115 RouteGraphNode rgn = (RouteGraphNode)child;
116 rgn.setAssignments(modification.svgAssignments);
120 } else if(node instanceof SingleElementNode) {
122 Map<SVGNode, List<SVGNodeAssignment>> assignmentMap = new HashMap<>();
124 if (modification.svgAssignments != null && !modification.svgAssignments.isEmpty()) {
125 for (SVGNode p : NodeUtil.collectNodes(node, SVGNode.class)) {
126 List<SVGNodeAssignment> list = assignmentMap.get(p);
128 list = new ArrayList<>();
129 assignmentMap.put(p, list);
131 list.addAll(modification.svgAssignments);
135 if(modification.targetedSVGAssignments != null && !modification.targetedSVGAssignments.isEmpty()) {
136 elements = buildSingleElementMap(node);
137 for(TargetedSVGNodeAssignment ass : modification.targetedSVGAssignments) {
138 SingleElementNode sen = elements.get(ass.singleElementKey);
139 for (SVGNode p : NodeUtil.collectNodes(sen, SVGNode.class)) {
140 List<SVGNodeAssignment> list = assignmentMap.get(p);
142 list = new ArrayList<>();
143 assignmentMap.put(p, list);
150 for(Map.Entry<SVGNode, List<SVGNodeAssignment>> entry : assignmentMap.entrySet()) {
151 SVGNode p = entry.getKey();
152 p.setAssignments(entry.getValue());
153 p.cleanDiagramCache();
156 if (modification.transformAssignments != null) {
157 Map<Object,AffineTransform> trs = new HashMap<>();
158 for (TransformationAssignment ass : modification.transformAssignments)
159 trs.put(ass.key, ass.transform);
160 NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
161 Object key = n.getKey();
162 AffineTransform tr = trs.get(key);
164 IG2DNode[] children = n.getSortedNodes();
165 if (children.length > 0)
166 children[0].setTransform(tr);