edc7aa9e1e5757a7d822ba96c75bb83ca7506aa6
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / adapters / SymbolCodeStyle.java
1 /*******************************************************************************
2  * Copyright (c) 2017 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.adapters;
13
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;
19 import java.util.Map;
20
21 import org.simantics.db.ReadGraph;
22 import org.simantics.db.Resource;
23 import org.simantics.db.exception.DatabaseException;
24 import org.simantics.db.layer0.variable.Variable;
25 import org.simantics.db.layer0.variable.Variables;
26 import org.simantics.diagram.profile.StyleBase;
27 import org.simantics.diagram.stubs.DiagramResource;
28 import org.simantics.scenegraph.INode;
29 import org.simantics.scenegraph.g2d.G2DNodeModification;
30 import org.simantics.scenegraph.g2d.IG2DNode;
31 import org.simantics.scenegraph.g2d.nodes.SVGNode;
32 import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment;
33 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
34 import org.simantics.scenegraph.g2d.nodes.TransformationAssignment;
35 import org.simantics.scenegraph.profile.EvaluationContext;
36 import org.simantics.scenegraph.utils.NodeUtil;
37 import org.simantics.utils.datastructures.Pair;
38
39 /**
40  * @author Antti Villberg
41  * @since 1.29.0
42  */
43 public class SymbolCodeStyle extends StyleBase<Pair<G2DNodeModification, Object>> {
44
45     @Override
46     public Pair<G2DNodeModification, Object> calculateStyle(ReadGraph graph, Resource runtimeDiagram, Resource entry, Resource element, Variable configuration) throws DatabaseException {
47         DiagramResource DIA = DiagramResource.getInstance(graph);
48
49         // Find a component for the element 
50         Variable elementVariable = Variables.getPossibleVariable(graph, element);
51         if (elementVariable == null)
52             return null;
53         Object modi = elementVariable.getPossiblePropertyValue(graph, DIA.symbolCode);
54         if (modi == null)
55             return null;
56
57         // If element is moved, recalculate style
58         Object transform = graph.getPossibleRelatedValue(element, DIA.HasTransform);
59
60         if (modi instanceof G2DNodeModification) {
61             return Pair.make((G2DNodeModification)modi, transform);
62         } else if (modi instanceof List) {
63             @SuppressWarnings("unchecked")
64             List<String> styles = (List<String>)modi;
65             List<SVGNodeAssignment> assignments = new ArrayList<>(styles.size()/3);
66             for (int i = 0; i < styles.size()/3; i++)
67                 assignments.add(new SVGNodeAssignment(styles.get(3*i), styles.get(3*i+1), styles.get(3*i+2)));
68             return Pair.make(new G2DNodeModification(assignments, Collections.emptyList()), transform);
69         } else {
70             throw new DatabaseException("Invalid symbolCode value: " + modi);
71         }
72     }
73
74     @Override
75     public void applyStyleForNode(EvaluationContext evaluationContext, INode node, Pair<G2DNodeModification, Object> result) {
76         if (result == null || result.first == null)
77             return;
78
79         G2DNodeModification modification = result.first;
80         if (modification.svgAssignments != null && !modification.svgAssignments.isEmpty()) {
81             for (SVGNode p : NodeUtil.collectNodes(node, SVGNode.class)) {
82                 p.setAssignments(modification.svgAssignments);
83                 p.cleanDiagramCache();
84             }
85         }
86         if (modification.transformAssignments != null) {
87             Map<Object,AffineTransform> trs = new HashMap<>();
88             for (TransformationAssignment ass : modification.transformAssignments) 
89                 trs.put(ass.key, ass.transform);
90             NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
91                 Object key = n.getKey();
92                 AffineTransform tr = trs.get(key);
93                 if (tr != null) {
94                     IG2DNode[] children = n.getSortedNodes();
95                     if (children.length > 0)
96                         children[0].setTransform(tr);
97                 }
98                 return null;
99             });
100         }
101     }
102
103 }