Dynamic terminals and connections 83/683/1
authorjsimomaa <jani.simomaa@gmail.com>
Fri, 7 Jul 2017 06:32:24 +0000 (09:32 +0300)
committerjsimomaa <jani.simomaa@gmail.com>
Fri, 7 Jul 2017 06:32:24 +0000 (09:32 +0300)
Change-Id: I15242c8bf58a5b16529f924987fd8bf51cf69d0b

16 files changed:
bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph
bundles/org.simantics.diagram.ontology/graph/DiagramProfiles.pgraph
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/DefinedElementTerminals.java
bundles/org.simantics.document.base.ontology/graph/Elements.pgraph
bundles/org.simantics.modeling.ontology/graph/Modeling.pgraph
bundles/org.simantics.modeling/scl/Simantics/Scenegraph.scl
bundles/org.simantics.modeling/src/org/simantics/modeling/ModelingUtils.java
bundles/org.simantics.modeling/src/org/simantics/modeling/NewComponentType.java
bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/SymbolCodeStyle.java
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/request/ProfileEntryContributions.java
bundles/org.simantics.scenegraph/META-INF/MANIFEST.MF
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DNodeModification.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TargetedSVGNodeAssignment.java [new file with mode: 0644]
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/ColorUtil.java

index 7b7bb6b2e2d7eca5b83bcc764733423b8c385e4e..bd99e8f988a2ba46cdef5d31a74cb0b0de9c45c4 100644 (file)
@@ -41,6 +41,8 @@ DIA.Element <T STR.Component : DIA.ElementClass
       L0.HasLabel "Hide Profile Monitors?"
     >-- DIA.Element.upProfileMonitors --> L0.Boolean <R L0.HasProperty : L0.FunctionalRelation : SEL.GenericParameterType
       L0.HasLabel "Grow Profile Monitors Upward?"
+    
+DIA.symbolFunction <R L0.HasProperty : L0.FunctionalRelation
 
 DIA.DiagramContainer <T L0.Entity
     @L0.singleProperty L0.HasName
index 6413e8019f6cb6cd656066839f291e3e962eb30a..e1e48e03b4eac8f10b92b81c31b8ce93a204cd57 100644 (file)
@@ -88,3 +88,5 @@ DIA.Groups : L0.Library
 DIA.Groups.DefinedElementGroup : DIA.TypeGroup
   DIA.TypeGroup.HasType DIA.DefinedElement
 
+DIA.Groups.RouteGraphConnectionElementGroup : DIA.TypeGroup
+  DIA.TypeGroup.HasType DIA.RouteGraphConnection
index d67f9f547f9c5a27a2ad552849f5842e0746bdd8..33e831afcf1b69f638c6a3ce66699957273e9713 100644 (file)
@@ -11,6 +11,7 @@
  *******************************************************************************/
 package org.simantics.diagram.adapter;
 
+import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.util.Collection;
 
@@ -73,5 +74,20 @@ public class DefinedElementTerminals extends Terminals {
             return null;
         return ti.getTransform();
     }
+    
+    @Override
+    public Shape getTerminalShape(IElement e, Terminal t) {
+        if (t instanceof ResourceTerminal) {
+            ResourceTerminal rt = (ResourceTerminal) t;
+            IG2DNode node = e.getHint(DefinedElementHandler.KEY_SG_NODE);
+            if (node != null) {
+                IG2DNode n = findResourceTerminalNode(node, rt);
+                if (n != null) {
+                    return n.getBoundsInLocal();
+                }
+            }
+        }
+        return super.getTerminalShape(e, t);
+    }
 
 }
\ No newline at end of file
index a2c9b7369bd41de90767cf0b90ad967a538f0f7c..c09e702723ed9f8814a9243e535dbb0426609fe4 100644 (file)
@@ -312,7 +312,13 @@ TERMINALS.ChildTerminal /* @ "Connection point to a child element" */ <T DIA.Def
         @L0.orderedSet
             _ : DIA.SVGElement
                 G2D.HasSVGDocument """<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" overflow="visible" version="1.1"><g transform="translate(-0.0,-0.0)"><ellipse cx="0.0" cy="0.0" rx="0.5" ry="0.5" fill="rgb(0,163,204)" stroke="black" stroke-width="0.1"/></g></svg>""" : L0.String
-  
+
+TERMINALS.TargetedDynamicTerminal /* @ "Connection point to a child element" */ <T DIA.DefinedElement <T DIA.Terminal
+    STR.IsDefinedBy _ : DIA.Composite
+        @L0.orderedSet
+            _ : DIA.SVGElement
+                G2D.HasSVGDocument """<svg display="none"><g display="none"></g></svg>""" : L0.String
+
 TERMINALS.CommandTerminal /* @ "Command termina" */ <T DIA.DefinedElement <T DIA.Terminal
     STR.IsDefinedBy _ : DIA.Composite
         @L0.orderedSet
index 94b3b5df1dac85c289e7a3119c658ecfaca604a2..e9b91f71aeaba0aedf6369bb4d8119a53e4d9bbd 100644 (file)
@@ -45,7 +45,7 @@ created to the model."""
         L0.HasDescription """Specifies a template for a symbol that is created 
 by default for the new component type under the model."""
     >-- MOD.StructuralModel.HasSymbolDiagramType --> L0.Type <R L0.IsRelatedTo : L0.FunctionalRelation
-
+    >-- MOD.StructuralModel.HasSymbolType --> L0.Type <R L0.IsRelatedTo : L0.FunctionalRelation
     >-- MOD.StructuralModel.HasConfigurationType --> L0.Type <R L0.IsRelatedTo : L0.FunctionalRelation
 
     @L0.assert MOD.StructuralModel.HasComponentTypeSupertype STR.Component
index 92738469719e2a0a165a89378879701ab1146d7f..3c9c5579969cb61b1015f0d461cc5e9c50431d1a 100644 (file)
@@ -100,10 +100,19 @@ importJava "org.simantics.scenegraph.g2d.G2DNodeModification" where
     data G2DNodeModification
     @JavaName "<init>"
     createG2DNodeModification :: [SVGNodeAssignment] -> [TransformationAssignment] -> G2DNodeModification 
+    @JavaName "<init>"
+    createG2DNodeModification3 :: [SVGNodeAssignment] -> [TargetedSVGNodeAssignment] -> [TransformationAssignment] -> G2DNodeModification 
     
 importJava "org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment" where
     data SVGNodeAssignment
+    @JavaName "<init>"
+    createSVGNodeAssignment :: String -> String -> String -> SVGNodeAssignment 
     
+importJava "org.simantics.scenegraph.g2d.nodes.TargetedSVGNodeAssignment" where
+    data TargetedSVGNodeAssignment
+    @JavaName "<init>"
+    createTargetedSVGNodeAssignment :: a -> String -> String -> String -> TargetedSVGNodeAssignment 
+
 importJava "org.simantics.scenegraph.g2d.nodes.TransformationAssignment" where
     data TransformationAssignment
     @JavaName "<init>"
index 3054fcaa531c45fd3285719333062fb4d9a14041..511eeb3fa0e41fb0894b866d293cc330812c3923 100644 (file)
@@ -183,7 +183,11 @@ public class ModelingUtils {
        }
 
        @Deprecated
-       public Resource createSymbol2(String name, Resource type) throws DatabaseException {
+       public Resource createSymbol2(String name, Resource diagramType) throws DatabaseException {
+           return createSymbol2(name, diagramType, dr.DefinedElement);
+       }
+       @Deprecated
+       public Resource createSymbol2(String name, Resource diagramType, Resource symbolType) throws DatabaseException {
                G2DResource g2d = G2DResource.getInstance(g);
 
 //             Resource visibleTag = wg.newResource();
@@ -192,7 +196,7 @@ public class ModelingUtils {
 //             wg.claim(focusableTag, b.SubrelationOf, null, dr.IsFocusable);
 
                Double boxDimension = 6.0;
-               Collection<Statement> grid = g.getAssertedStatements(type, dr.HasGridSize);
+               Collection<Statement> grid = g.getAssertedStatements(diagramType, dr.HasGridSize);
                if(grid.size() == 1) {
                        Double d = g.getPossibleValue(grid.iterator().next().getObject(), Bindings.DOUBLE);
                        if(d != null) boxDimension = 2*d;
@@ -217,7 +221,7 @@ public class ModelingUtils {
 //             wg.claim(element, visibleTag, element);
 //             wg.claim(element, focusableTag, element);
 
-               Resource orderedSet = OrderedSetUtils.create(wg, type, element);
+               Resource orderedSet = OrderedSetUtils.create(wg, diagramType, element);
 
 //             wg.claim(orderedSet, dr.HasLayer, GraphUtils.create2(wg, dr.Layer,
 //                             b.HasName, "Default",
@@ -235,7 +239,7 @@ public class ModelingUtils {
                AddElement.claimFreshElementName(wg, orderedSet, element);
                wg.claim(orderedSet, b.ConsistsOf, element);
 
-               wg.claim(result, b.Inherits, null, dr.DefinedElement);
+               wg.claim(result, b.Inherits, null, symbolType);
                return result;
        }
 
index 920c30453f36d54f4befbb97f8115a392f67a21e..813b6c3c15538253097823fe15aa45f675517dc9 100644 (file)
@@ -62,9 +62,12 @@ public class NewComponentType {
 
         Resource symbolDiagramType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasSymbolDiagramType);
         if(symbolDiagramType == null) symbolDiagramType = DIA.Composite;
-        
+
+        Resource symbolType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasSymbolType);
+        if(symbolType == null) symbolType = DIA.DefinedElement;
+
         // Symbol
-        Resource symbol = new ModelingUtils(graph).createSymbol2("Symbol", symbolDiagramType);
+        Resource symbol = new ModelingUtils(graph).createSymbol2("Symbol", symbolDiagramType, symbolType);
         graph.claim(componentType, MOD.ComponentTypeToSymbol, symbol);
         graph.claim(componentType, L0.ConsistsOf, symbol);
         
index edc7aa9e1e5757a7d822ba96c75bb83ca7506aa6..4e7fe78d05f3caa39b16f408428562a7ad39bbf1 100644 (file)
@@ -18,6 +18,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.simantics.Simantics;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.exception.DatabaseException;
@@ -28,12 +29,17 @@ import org.simantics.diagram.stubs.DiagramResource;
 import org.simantics.scenegraph.INode;
 import org.simantics.scenegraph.g2d.G2DNodeModification;
 import org.simantics.scenegraph.g2d.IG2DNode;
+import org.simantics.scenegraph.g2d.nodes.ConnectionNode;
 import org.simantics.scenegraph.g2d.nodes.SVGNode;
 import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment;
 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
+import org.simantics.scenegraph.g2d.nodes.TargetedSVGNodeAssignment;
 import org.simantics.scenegraph.g2d.nodes.TransformationAssignment;
+import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
 import org.simantics.scenegraph.profile.EvaluationContext;
 import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.scl.runtime.function.Function;
+import org.simantics.structural.stubs.StructuralResource2;
 import org.simantics.utils.datastructures.Pair;
 
 /**
@@ -51,8 +57,19 @@ public class SymbolCodeStyle extends StyleBase<Pair<G2DNodeModification, Object>
         if (elementVariable == null)
             return null;
         Object modi = elementVariable.getPossiblePropertyValue(graph, DIA.symbolCode);
-        if (modi == null)
-            return null;
+        if (modi == null) {
+               if(graph.isInstanceOf(element, DIA.RouteGraphConnection)) {
+                       StructuralResource2 STR = StructuralResource2.getInstance(graph);
+                       Resource connectionType = graph.getPossibleObject(element, STR.HasConnectionType);
+                       if(connectionType != null) {
+                               Variable connectionTypeVariable = Variables.getPossibleVariable(graph, connectionType);
+                               Function fn = connectionTypeVariable.getPossiblePropertyValue(graph, DIA.symbolFunction);
+                               modi = Simantics.applySCLRead(graph, fn, elementVariable);
+                       }
+               }
+        }
+        
+        if(modi == null) return null;
 
         // If element is moved, recalculate style
         Object transform = graph.getPossibleRelatedValue(element, DIA.HasTransform);
@@ -71,33 +88,89 @@ public class SymbolCodeStyle extends StyleBase<Pair<G2DNodeModification, Object>
         }
     }
 
+    private Map<Object,SingleElementNode> buildSingleElementMap(INode node) {
+        Map<Object,SingleElementNode> elements = new HashMap<>();
+        NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
+            elements.put(n.getKey(), n);
+            return null;
+        });
+        return elements;
+    }
+    
     @Override
     public void applyStyleForNode(EvaluationContext evaluationContext, INode node, Pair<G2DNodeModification, Object> result) {
-        if (result == null || result.first == null)
+
+       if (result == null || result.first == null)
             return;
 
+       Map<Object,SingleElementNode> elements = null;
+       
         G2DNodeModification modification = result.first;
-        if (modification.svgAssignments != null && !modification.svgAssignments.isEmpty()) {
-            for (SVGNode p : NodeUtil.collectNodes(node, SVGNode.class)) {
-                p.setAssignments(modification.svgAssignments);
+        
+        if(node instanceof ConnectionNode) {
+               
+               if (modification.svgAssignments != null && !modification.svgAssignments.isEmpty()) {
+                       INode child = NodeUtil.getFirstChild(node);
+                       if(child instanceof RouteGraphNode) {
+                               RouteGraphNode rgn = (RouteGraphNode)child; 
+                               rgn.setAssignments(modification.svgAssignments);
+                       }
+               }
+               
+        } else if(node instanceof SingleElementNode) {
+
+               Map<SVGNode, List<SVGNodeAssignment>> assignmentMap = new HashMap<>();
+               
+            if (modification.svgAssignments != null && !modification.svgAssignments.isEmpty()) {
+                for (SVGNode p : NodeUtil.collectNodes(node, SVGNode.class)) {
+                       List<SVGNodeAssignment> list = assignmentMap.get(p);
+                       if(list == null) {
+                               list = new ArrayList<>();
+                               assignmentMap.put(p, list);
+                       }
+                       list.addAll(modification.svgAssignments);
+                }
+            }
+
+               if(modification.targetedSVGAssignments != null && !modification.targetedSVGAssignments.isEmpty()) {
+                       elements = buildSingleElementMap(node);
+                       for(TargetedSVGNodeAssignment ass : modification.targetedSVGAssignments) {
+                               SingleElementNode sen = elements.get(ass.singleElementKey);
+                    for (SVGNode p : NodeUtil.collectNodes(sen, SVGNode.class)) {
+                       List<SVGNodeAssignment> list = assignmentMap.get(p);
+                       if(list == null) {
+                               list = new ArrayList<>();
+                               assignmentMap.put(p, list);
+                       }
+                       list.add(ass);
+                    }
+                       }
+               }
+
+               for(Map.Entry<SVGNode, List<SVGNodeAssignment>> entry : assignmentMap.entrySet()) {
+                       SVGNode p = entry.getKey();
+               p.setAssignments(entry.getValue());
                 p.cleanDiagramCache();
+               }
+
+            if (modification.transformAssignments != null) {
+                Map<Object,AffineTransform> trs = new HashMap<>();
+                for (TransformationAssignment ass : modification.transformAssignments) 
+                    trs.put(ass.key, ass.transform);
+                NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
+                    Object key = n.getKey();
+                    AffineTransform tr = trs.get(key);
+                    if (tr != null) {
+                        IG2DNode[] children = n.getSortedNodes();
+                        if (children.length > 0)
+                            children[0].setTransform(tr);
+                    }
+                    return null;
+                });
             }
+               
         }
-        if (modification.transformAssignments != null) {
-            Map<Object,AffineTransform> trs = new HashMap<>();
-            for (TransformationAssignment ass : modification.transformAssignments) 
-                trs.put(ass.key, ass.transform);
-            NodeUtil.forChildrenDeep(node, SingleElementNode.class, n -> {
-                Object key = n.getKey();
-                AffineTransform tr = trs.get(key);
-                if (tr != null) {
-                    IG2DNode[] children = n.getSortedNodes();
-                    if (children.length > 0)
-                        children[0].setTransform(tr);
-                }
-                return null;
-            });
-        }
+        
     }
 
 }
index 4c3cd57b7e1e21efc297650bcba579368e2cc648..0cf54df3293a71d1e1ec7f0cfe9ae90bf583b913 100644 (file)
@@ -34,7 +34,10 @@ public class ProfileEntryContributions extends ResourceRead<Collection<Resource>
 
                ArrayList<Resource> result = new ArrayList<>();
                for(Resource contribution : query.find(graph, index)) {
-                       result.add(graph.getSingleObject(contribution, DIA.ProfileEntryContribution_HasEntry));
+                       for(Resource entry : graph.getObjects(contribution, DIA.ProfileEntryContribution_HasEntry)) {
+                               result.add(entry);      
+                       }
+                       
                }
 
                return result;
index dad71c00d9e81a7828071e1a15633fe11f1c0f11..610990a02a02e11a465ea9ca6935926f390c4349 100644 (file)
@@ -13,7 +13,8 @@ Require-Bundle: gnu.trove3;bundle-version="3.0.0",
  org.simantics.scl.runtime;bundle-version="0.1.4",
  org.simantics.databoard;bundle-version="0.6.3",
  com.lowagie.text;bundle-version="2.1.7";resolution:=optional,
- org.simantics.utils;bundle-version="1.1.0"
+ org.simantics.utils;bundle-version="1.1.0",
+ org.slf4j.api
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-ClassPath: .,
  lib/svgSalamander-tiny.jar,
index 4b68e179879f054a3d33fbdfb2b59c543f6c3b5f..75c64ca623da053e7265006fc37cc225ca30b05a 100644 (file)
@@ -14,6 +14,7 @@ package org.simantics.scenegraph.g2d;
 import java.util.List;
 
 import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment;
+import org.simantics.scenegraph.g2d.nodes.TargetedSVGNodeAssignment;
 import org.simantics.scenegraph.g2d.nodes.TransformationAssignment;
 
 /**
@@ -22,9 +23,18 @@ import org.simantics.scenegraph.g2d.nodes.TransformationAssignment;
  */
 public class G2DNodeModification {
        public List<SVGNodeAssignment> svgAssignments;
+       public List<TargetedSVGNodeAssignment> targetedSVGAssignments;
        public List<TransformationAssignment> transformAssignments;
        public G2DNodeModification(List<SVGNodeAssignment> svgAssignments, List<TransformationAssignment> transformAssignments) {
                this.svgAssignments = svgAssignments;
                this.transformAssignments = transformAssignments;
        }
+       public G2DNodeModification(List<SVGNodeAssignment> svgAssignments, List<TargetedSVGNodeAssignment> targetedSVGAssignments, List<TransformationAssignment> transformAssignments) {
+               this.svgAssignments = svgAssignments;
+               this.targetedSVGAssignments = targetedSVGAssignments;
+               this.transformAssignments = transformAssignments;
+       }
+       public static G2DNodeModification create3(List<SVGNodeAssignment> svgAssignments, List<TargetedSVGNodeAssignment> targetedSVGAssignments, List<TransformationAssignment> transformAssignments) {
+               return new G2DNodeModification(svgAssignments, targetedSVGAssignments, transformAssignments);
+       }
 }
index 2fc37b7d59ab6bc9179943ab80b60246118e08e3..ec85fd75c86e7893a8b7341bcfde6641e380d244 100644 (file)
@@ -27,6 +27,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.WeakHashMap;
 
 import org.simantics.scenegraph.ExportableWidget.RasterOutputWidget;
@@ -172,32 +173,55 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
                     diagramCache = null;
                 }
 
-                // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
-                byte[] dataBytes = data.getBytes("UTF-8");
+                
+                // Lets check for rootAssignment that contributes the whole SVG 
+                SVGNodeAssignment rootAssignment = null;
+                if (!assignments.isEmpty()) {
+                    for (SVGNodeAssignment ass : assignments) {
+                        if (ass.attributeNameOrId.equals("$root")) {
+                            rootAssignment = ass;
+                            break;
+                        }
+                    }
+                }
+                byte[] dataBytes;
+                if (rootAssignment != null) {
+                    dataBytes = rootAssignment.value.getBytes("UTF-8");
+                } else {
+                    // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
+                    dataBytes = data.getBytes("UTF-8");
+                }
                 dataHash = digest(dataBytes, assignments);
                 URI uri = univ.loadSVG(new ByteArrayInputStream(dataBytes), dataHash);
                 diagramCache = univ.getDiagram(uri, false);
 
                 if (diagramCache != null) {
                     univ.incRefCount(diagramCache.getXMLBase());
-
-                    if (diagramCache.getRoot() == null) {
+                    SVGRoot root = diagramCache.getRoot();
+                    if (root == null) {
                         univ.decRefCount(diagramCache.getXMLBase());
                         diagramCache = univ.getDiagram(univ.loadSVG(BROKEN_SVG_DATA), false);
                         dataHash = "broken";
                         univ.incRefCount(diagramCache.getXMLBase());
                         bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone();
                     } else {
-                        bbox = diagramCache.getRoot().getBoundingBox();
+                        bbox = root.getBoundingBox();
                         if (bbox.isEmpty()) {
-                            univ.decRefCount(diagramCache.getXMLBase());
-                            diagramCache = univ.getDiagram(univ.loadSVG(EMPTY_SVG_DATA), false);
-                            dataHash = "empty";
-                            univ.incRefCount(diagramCache.getXMLBase());
-                            bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone();
+                            // Lets check if this should be visible or not
+                            Set presentationAttributes = root.getPresentationAttributes();
+                            if (!presentationAttributes.contains("display")) {
+                                // TODO: fix this - How can one read values of attributes in SVG salamander???
+                                univ.decRefCount(diagramCache.getXMLBase());
+                                diagramCache = univ.getDiagram(univ.loadSVG(EMPTY_SVG_DATA), false);
+                                dataHash = "empty";
+                                univ.incRefCount(diagramCache.getXMLBase());
+                                bbox = (Rectangle2D) root.getBoundingBox().clone();
+                            } else {
+                                bbox = new Rectangle2D.Double(0, 0, 0, 0);
+                            }
                         } else {
                             if (applyAssignments(diagramCache, assignments)) {
-                                bbox = (Rectangle2D) diagramCache.getRoot().getBoundingBox().clone();
+                                bbox = (Rectangle2D) root.getBoundingBox().clone();
                             } else {
                                 bbox = (Rectangle2D) bbox.clone();
                             }
@@ -227,6 +251,9 @@ public class SVGNode extends G2DNode implements InitValueSupport, LoaderNode {
             return false;
         boolean changed = false;
         for (SVGNodeAssignment ass : assignments) {
+//             System.err.println("assign: " + ass.elementId + " " + ass.attributeNameOrId + " " + ass.value);
+//             if("opacity".equals(ass.attributeNameOrId))
+//                     System.err.println("faaf");
             SVGElement e = diagram.getElement(ass.elementId);
             if (e != null) {
                 if ("$text".equals(ass.attributeNameOrId)) {
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TargetedSVGNodeAssignment.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/TargetedSVGNodeAssignment.java
new file mode 100644 (file)
index 0000000..0f279a6
--- /dev/null
@@ -0,0 +1,55 @@
+package org.simantics.scenegraph.g2d.nodes;
+
+/**
+ * @author Antti Villberg
+ * @since 1.29.0
+ */
+public class TargetedSVGNodeAssignment extends SVGNodeAssignment {
+       public Object singleElementKey;
+       public TargetedSVGNodeAssignment(Object singleElementKey, String elementId, String attributeNameOrId, String value) {
+               super(elementId, attributeNameOrId, value);
+               this.singleElementKey = singleElementKey;
+       }
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((singleElementKey == null) ? 0 : singleElementKey.hashCode());
+               result = prime * result + ((attributeNameOrId == null) ? 0 : attributeNameOrId.hashCode());
+               result = prime * result + ((elementId == null) ? 0 : elementId.hashCode());
+               result = prime * result + ((value == null) ? 0 : value.hashCode());
+               return result;
+       }
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               TargetedSVGNodeAssignment other = (TargetedSVGNodeAssignment) obj;
+               if (singleElementKey == null) {
+                       if (other.singleElementKey != null)
+                               return false;
+               } else if (!singleElementKey.equals(other.singleElementKey))
+                       return false;
+               if (attributeNameOrId == null) {
+                       if (other.attributeNameOrId != null)
+                               return false;
+               } else if (!attributeNameOrId.equals(other.attributeNameOrId))
+                       return false;
+               if (elementId == null) {
+                       if (other.elementId != null)
+                               return false;
+               } else if (!elementId.equals(other.elementId))
+                       return false;
+               if (value == null) {
+                       if (other.value != null)
+                               return false;
+               } else if (!value.equals(other.value))
+                       return false;
+               return true;
+       }
+       
+}
\ No newline at end of file
index 687731f4c2f9d8528ab40cc0c6189151672828f4..0a2583fc6dd734552999376241b15b509f235086 100644 (file)
@@ -23,7 +23,9 @@ import java.awt.geom.Path2D;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.lang.reflect.Constructor;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 
 import org.simantics.diagram.connection.RouteGraph;
@@ -59,12 +61,16 @@ import org.simantics.scenegraph.g2d.events.command.CommandEvent;
 import org.simantics.scenegraph.g2d.events.command.Commands;
 import org.simantics.scenegraph.g2d.nodes.GridNode;
 import org.simantics.scenegraph.g2d.nodes.LinkNode;
+import org.simantics.scenegraph.g2d.nodes.SVGNodeAssignment;
 import org.simantics.scenegraph.g2d.nodes.connection.HighlightActionPointsAction.Action;
 import org.simantics.scenegraph.g2d.nodes.connection.HighlightActionPointsAction.Pick;
 import org.simantics.scenegraph.g2d.snap.ISnapAdvisor;
+import org.simantics.scenegraph.utils.ColorUtil;
 import org.simantics.scenegraph.utils.GeometryUtils;
 import org.simantics.scenegraph.utils.InitValueSupport;
 import org.simantics.scenegraph.utils.NodeUtil;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
 
 import gnu.trove.map.hash.THashMap;
 
@@ -73,7 +79,9 @@ import gnu.trove.map.hash.THashMap;
  */
 public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, InitValueSupport  {
 
-    private static final long       serialVersionUID = -917194130412280965L;
+    private static final Logger LOGGER = LoggerFactory.getLogger(RouteGraphNode.class);
+
+       private static final long       serialVersionUID = -917194130412280965L;
 
     private static final double     TOLERANCE        = IAction.TOLERANCE;
     private static final Stroke     SELECTION_STROKE = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
@@ -123,7 +131,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In
 
 
     protected transient Map<Object,ILineEndStyle> dynamicStyles = null;
-    
+
     private transient boolean ignoreSelection = false;
     
     @Override
@@ -132,6 +140,74 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In
         wrapRenderer();
     }
 
+    private static float tryParseFloat(String s, float def) {
+       try {
+               return Float.parseFloat(s);
+       } catch (NumberFormatException e) {
+               LOGGER.error("Could not parse '" + s + "' into float.");
+               return def;
+       }
+    }
+    
+    /*
+     * 1.0 BUTT MITER 1.0 0.0
+     */
+    private static Stroke parseStroke(String definition) {
+       
+       float width = 1.0f;
+       int cap = BasicStroke.CAP_BUTT;
+       int join = BasicStroke.JOIN_MITER;
+       float miterLimit = 1.0f;
+       float[] dash = { 1, 0};
+       float dash_phase = 0;
+
+       String[] parts = definition.split(" ");
+       
+       if(parts.length > 0) {
+               width = tryParseFloat(parts[0], width);
+       }
+       if(parts.length > 1) { 
+               if("BUTT".equals(parts[1])) cap = BasicStroke.CAP_BUTT;
+               else if("ROUND".equals(parts[1])) cap = BasicStroke.CAP_ROUND;
+               else if("SQUARE".equals(parts[1])) cap = BasicStroke.CAP_SQUARE;
+       }
+       if(parts.length > 2) { 
+               if("BEVEL".equals(parts[2])) cap = BasicStroke.JOIN_BEVEL;
+               else if("MITER".equals(parts[2])) cap = BasicStroke.JOIN_MITER;
+               else if("ROUND".equals(parts[2])) cap = BasicStroke.JOIN_ROUND;
+       }
+       if(parts.length > 3) {
+               miterLimit = tryParseFloat(parts[3], miterLimit);
+       } 
+       if(parts.length > 4) {
+               dash_phase = tryParseFloat(parts[4], dash_phase);
+       }
+       if(parts.length > 6) {
+               dash = new float[parts.length - 5];
+               for(int i=5;i<parts.length;i++) {
+                       dash[i-5] = tryParseFloat(parts[i], 1.0f);
+               }
+       }
+                       
+       
+       try {
+               return new BasicStroke(width, cap, join, miterLimit, dash, dash_phase);
+       } catch (IllegalArgumentException e) {
+               return new BasicStroke();
+       }
+       
+    }
+    
+    public void setAssignments(List<SVGNodeAssignment> assignments) {
+       for(SVGNodeAssignment ass : assignments) {
+               if("dynamicColor".equals(ass.elementId)) {
+                       setDynamicColor(ColorUtil.hexColor(ass.value));
+               } else if("dynamicStroke".equals(ass.elementId)) {
+                       setDynamicStroke(parseStroke(ass.value));
+               }
+       }
+    }
+
     public void setIgnoreSelection(boolean value) {
         ignoreSelection = value;
     }
index 8479cd717602650bf9531881cdb3156d1309e5de..300938261329fb6e98dc16073693c58ea15f7bb0 100644 (file)
@@ -81,6 +81,20 @@ public class ColorUtil {
            if ( b > 255 ) b = 255;     
        
        return new Color(r, g, b, c.getAlpha());
-    }    
+    }
+    
+    public static Color hexColor(String hex) {
+       if(hex.startsWith("#")) {
+               if(hex.length() == 4) {
+                       int r = Character.digit(hex.charAt(1), 16);
+                       int g = Character.digit(hex.charAt(2), 16);
+                       int b = Character.digit(hex.charAt(3), 16);
+                       return new Color(r+(r<<4), g+(g<<4), b+(b<<4));
+               } else if(hex.length() == 7) {
+                       return new Color(Integer.parseInt(hex.substring(1), 16));
+               }
+       }
+       return Color.BLACK;
+    }
 
 }