]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "Add more debug for AsyncBarrierImpl" into release/1.43.1
authorJani Simomaa <jani.simomaa@semantum.fi>
Fri, 2 Oct 2020 09:53:20 +0000 (09:53 +0000)
committerGerrit Code Review <gerrit2@simantics>
Fri, 2 Oct 2020 09:53:20 +0000 (09:53 +0000)
17 files changed:
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java [new file with mode: 0644]
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java [new file with mode: 0644]
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java [new file with mode: 0644]
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/StyledRouteGraphRenderer.java
bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph
bundles/org.simantics.diagram/src/org/simantics/diagram/connection/ConnectionVisuals.java
bundles/org.simantics.diagram/src/org/simantics/diagram/elements/TextElementHandler.java
bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectionCrossingsParticipant.java [new file with mode: 0644]
bundles/org.simantics.document.base.ontology/graph/ConnectionPoints.pgraph
bundles/org.simantics.g2d.ontology/graph/G2D.pgraph
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewer.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ObserverGroupListener.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java [new file with mode: 0644]

index fe93717662b2220c840ca38d2be848ed2c542d3b..6357e537ac5c5d356b89803c25ad2ea3166c8706 100644 (file)
@@ -277,6 +277,12 @@ public class RouteGraph implements Serializable {
         transientLines.clear();
     }
     
+    protected void removeRouteTerminalsFromRouteLines() {
+        for(RouteLine line : lines) {
+            line.removeRouteTerminals();
+        }
+    }
+
     /**
      * Rotates given terminal clockwise by given amount
      * (also negative numbers are allowed). 
@@ -311,6 +317,7 @@ public class RouteGraph implements Serializable {
     public void update() {
         needsUpdate = false;
         removeTransientRouteLines();
+        removeRouteTerminalsFromRouteLines();
 
         //print();
         
index 50d6c85d496548f75b316b8f2011ec39d5536886..225c4abfe890ecb5250e724777fb5f2dc4659c97 100644 (file)
@@ -195,6 +195,10 @@ public class RouteLine implements RouteNode, Serializable {
        return lines;
     }
 
+    public void removeRouteTerminals() {
+        points.removeIf(p -> p instanceof RouteTerminal);
+    }
+
     public RouteTerminal getTerminal() {
         return terminal;
     }
index dd660d4aaa659df5bce98302794586549e423c04..3d6bd182f664b9146c5686155ac8d4f541e6f8cf 100644 (file)
@@ -164,18 +164,31 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
             boolean routeLineDoesNotIntersectTerminal;
             double linePosition = line.position;
             if(line.isHorizontal) { 
+                if (linePosition == y) {
+                    // direct route to terminal
+                    line.addPoint(this);
+                    return;
+                }
                 lineDir = linePosition < y ? 3 : 1;
                 routeLineDoesNotIntersectTerminal = linePosition <= minY || linePosition >= maxY 
                         || boundingBoxesIntersect /* we ignore intersection in this case */;
             }
             else {
+                if (linePosition == x) {
+                    // direct route to terminal
+                    line.addPoint(this);
+                    return;
+                }
                 lineDir = linePosition < x ? 2 : 0;
                 routeLineDoesNotIntersectTerminal = linePosition <= minX || linePosition >= maxX
                         || boundingBoxesIntersect /* we ignore intersection in this case */;
             }
                     
             // We can route the connection directly to the right direction
-            if(routeLineDoesNotIntersectTerminal && 
+            if((routeLineDoesNotIntersectTerminal ||
+                    (line.isHorizontal && (x == minX || x == maxX)) || // already on the top/bottom edge
+                    (!line.isHorizontal && (y == minY || y == maxY)) // already on the left/right edge
+                    ) && 
                     Directions.isAllowed(allowedDirections, lineDir)) {           
                 RouteLine line0 = createLine0(lineDir);
                 new RouteLink(line0, line);
diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java
new file mode 100644 (file)
index 0000000..3ccb492
--- /dev/null
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.connection.rendering;
+
+import java.awt.geom.Arc2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ConnectionCrossings implements PathModifier {
+    public enum Type {
+        NONE,
+        GAP,
+        ARC,
+        SQUARE
+    }
+
+    private List<Segment> segments = new ArrayList<>();
+    private double width;
+    private Type type;
+
+    public void setWidth(double gapWidth) {
+        this.width = gapWidth;
+    }
+
+    public double getWidth() {
+        return width;
+    }
+
+    public void setType(Type type) {
+        this.type = type;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    static class Segment {
+        public double x1, y1, x2, y2;
+
+        public Segment(double x1, double y1, double x2, double y2) {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+    };
+
+    public void reset() {
+        segments.clear();
+    }
+
+    static Double lineLineIntersection(Segment l1, Segment l2) { 
+        double epsilon = 0.001;
+
+        double d = (l1.x1 - l1.x2) * (l2.y1 - l2.y2) - (l1.y1 - l1.y2) * (l2.x1 - l2.x2);
+        if (d == 0.0) return null;
+        double s = ((l1.x1 - l2.x1) * (l2.y1 - l2.y2) - (l1.y1 - l2.y1) * (l2.x1 - l2.x2)) / d;
+        if ((s > epsilon) && (s < 1 - epsilon)) {
+            double t = -((l1.x1 - l1.x2) * (l1.y1 - l2.y1) - (l1.y1 - l1.y2) * (l1.x1 - l2.x1)) / d;
+            if ((t > epsilon) && (t < 1 - epsilon)) {
+                return t;
+            }
+        }
+        return null; 
+    }
+
+    public Path2D modify(Path2D path) {
+        Path2D.Double path2 = new Path2D.Double();
+        PathIterator iter = path.getPathIterator(null);
+
+        while (!iter.isDone()) {
+
+            double c[] = new double[6];
+            int i = iter.currentSegment(c);
+            switch (i) {
+            case PathIterator.SEG_MOVETO:
+                path2.moveTo(c[0], c[1]);
+                break;
+            case PathIterator.SEG_LINETO:
+                Segment l = new Segment(path2.getCurrentPoint().getX(), path2.getCurrentPoint().getY(), c[0], c[1]);
+                
+                List<Double> gaps = new ArrayList<>();
+                for (Segment old : segments) {
+                    Double t = lineLineIntersection(old, l);
+                    if (t != null) {
+                        gaps.add(t);
+                    }
+                }
+
+                if (gaps.isEmpty()) {
+                    path2.lineTo(c[0], c[1]);
+                } else {
+                    Collections.sort(gaps);
+                    double dx = l.x2 - l.x1;
+                    double dy = l.y2 - l.y1;
+
+                    double pos = 0.0;
+                    double len = Math.sqrt(dx*dx + dy*dy);
+
+                    boolean finish = true;
+                    Point2D prevGapEnd = null;
+                    for (Double gapCenter : gaps) {
+                        double pos2 = gapCenter - width / 2 / len;
+                        double pos3 = gapCenter + width / 2 / len;
+                        if (pos2 > pos) {
+                            handleGap(path2, prevGapEnd);
+                            prevGapEnd = null;
+                            path2.lineTo(l.x1 + pos2 * dx, l.y1 + pos2 * dy);
+                        }
+                        if (pos3 < 1.0) {
+                            double x = l.x1 + pos3 * dx;
+                            double y = l.y1 + pos3 * dy;
+                            prevGapEnd = new Point2D.Double(x, y);
+                        } else {
+                            finish = false;
+                        }
+                        pos = pos3;
+                    }
+                    
+                    if (finish) {
+                        handleGap(path2, prevGapEnd);
+                        path2.lineTo(l.x2, l.y2);
+                    } else {
+                        prevGapEnd = new Point2D.Double(l.x2, l.y2);
+                        handleGap(path2, prevGapEnd);
+                    }
+                }
+                segments.add(l);
+
+                break;
+            case PathIterator.SEG_QUADTO:
+                // TODO: implement gaps
+                path2.quadTo(c[0], c[1], c[2], c[3]);
+                break;
+            case PathIterator.SEG_CUBICTO:
+                // TODO: implement gaps
+                path2.curveTo(c[0], c[1], c[2], c[3], c[4], c[5]);
+                break;
+            case PathIterator.SEG_CLOSE:
+                // TODO: implement gaps
+                path2.closePath();
+                break;
+            default:
+                throw new RuntimeException("Unexpected segment type " + i);
+            }
+            iter.next();
+        }
+        return path2;
+    }
+
+    private void handleGap(Path2D path, Point2D prevGapEnd) {
+        if (prevGapEnd != null) {
+            switch (type) {
+            case ARC:
+                arcTo(path, prevGapEnd.getX(), prevGapEnd.getY());
+                break;
+            case SQUARE:
+                squareTo(path, prevGapEnd.getX(), prevGapEnd.getY(), width);
+                break;
+            case GAP:
+                path.moveTo(prevGapEnd.getX(), prevGapEnd.getY());
+                break;
+            case NONE:
+                break;
+            }
+        }
+    }
+
+    private static void arcTo(Path2D path, double x2, double y2) {
+        Arc2D arc = new Arc2D.Double();
+        double x1 = path.getCurrentPoint().getX();
+        double y1 = path.getCurrentPoint().getY();
+        double dx = x2 - x1;
+        double dy = y2 - y1;
+        double r = Math.sqrt(dx * dx + dy * dy) / 2;
+        double angle = Math.atan2(dx,  dy) * 180 / Math.PI + 90;
+        double span = (angle > 225 || angle < 45) ? 180 : -180;
+        arc.setArcByCenter((x1 + x2) / 2, (y1 + y2) / 2, r, angle, span, Arc2D.OPEN);
+        path.append(arc, true);
+    }
+    
+    private static void squareTo(Path2D path, double x2, double y2, double width) {
+        double x1 = path.getCurrentPoint().getX();
+        double y1 = path.getCurrentPoint().getY();
+        double dx = x2 - x1;
+        double dy = y2 - y1;
+        double l = Math.sqrt(dx * dx + dy* dy);
+        if (l > 0) {
+            double nx = -dy / l;
+            double ny = dx / l;
+            if (nx - ny < 0) {
+                nx = -nx;
+                ny = -ny;
+            }
+            path.lineTo(x1 + nx * width / 2, y1 + ny * width / 2);
+            path.lineTo(x2 + nx * width / 2, y2 + ny * width / 2);
+            path.lineTo(x2, y2);
+        }
+    }
+
+}
diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java
new file mode 100644 (file)
index 0000000..a78bec0
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.connection.rendering;
+
+import java.awt.RenderingHints.Key;
+
+public final class ConnectionRenderingHints {
+
+    public static final Key KEY_PATH_MODIFIER = new Key(0) {
+        @Override
+        public boolean isCompatibleValue(Object val) {
+            return val == null || val instanceof PathModifier;
+        }
+    };
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java
new file mode 100644 (file)
index 0000000..50d771a
--- /dev/null
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.connection.rendering;
+
+import java.awt.geom.Path2D;
+
+public interface PathModifier {
+       public Path2D modify(Path2D source);
+}
index dd9473042152d0c3af43244d9549d63e4c649e4b..fa14474691f281ad312df693dec50e242bdb9503 100644 (file)
@@ -62,6 +62,10 @@ public class StyledRouteGraphRenderer implements IRouteGraphRenderer, Serializab
 
                path.reset();
                rg.getPath2D(path);
+               PathModifier pm = (PathModifier) g.getRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER);
+               if (pm != null) {
+                       path = pm.modify(path);
+               }
                style.drawPath(g, path, false);
 
                branchPoints.clear();
index b26bfc698ee214ac9040b7228d2fe0a13c59b334..6ea207f88d754cd59825b9c2e533fadc6190cb4a 100644 (file)
@@ -68,6 +68,9 @@ DIA.IOTableRename <T L0.Entity
 DIA.Diagram <T DIA.Composite
     >-- DIA.Diagram.IOTableRenaming --> DIA.IOTableRename <T L0.DependsOn 
     @L0.optionalProperty DIA.HasModCount
+    @L0.assert DIA.ConnectionCrossingStyle ""
+    @L0.assert DIA.ConnectionCrossingStyle.Width 0.0
+    @L0.assert DIA.ConnectionCrossingStyle.HasType DIA.ConnectionCrossingStyle.Type.None
 
 DIA.HasModCount <R L0.HasProperty : L0.FunctionalRelation
     L0.HasLabel "Modification Counter"
@@ -143,4 +146,31 @@ DIA.diagramActivityCondition : L0.Template
 
 DIA.ProfileEntryContribution <T L0.Entity
   --> DIA.ProfileEntryContribution.HasEntry --> DIA.ProfileEntry <R L0.IsRelatedTo  
-                
\ No newline at end of file
+
+DIA.ConnectionCrossingStyle <R L0.HasProperty : L0.FunctionalRelation : SEL.GenericParameterType
+    L0.HasLabel "Connection Crossing Style"
+    SEL.HasDisplayValue ""
+    L0.readOnly true
+    SEL.canBeLifted false
+
+DIA.ConnectionCrossingStyle.Width <R L0.HasProperty : L0.FunctionalRelation : SEL.GenericParameterType
+    L0.HasLabel "Width"
+    L0.HasDescription "Width of connection crossings."
+    L0.HasDomain DIA.Diagram
+    L0.HasRange L0.Double
+    SEL.IsShownUnder DIA.ConnectionCrossingStyle
+
+DIA.ConnectionCrossingStyle.HasType <R L0.HasProperty : L0.FunctionalRelation : SEL.GenericParameterType
+    L0.HasLabel "Type"
+    L0.HasDescription "Type of connection crossings."
+    L0.HasDomain DIA.Diagram
+    L0.HasRange DIA.ConnectionCrossingStyle.Type
+    SEL.IsShownUnder DIA.ConnectionCrossingStyle
+
+DIA.ConnectionCrossingStyle.Type <T L0.Value
+    @L0.tag L0.Enumeration
+
+DIA.ConnectionCrossingStyle.Type.Arc : DIA.ConnectionCrossingStyle.Type
+DIA.ConnectionCrossingStyle.Type.Square : DIA.ConnectionCrossingStyle.Type
+DIA.ConnectionCrossingStyle.Type.Gap : DIA.ConnectionCrossingStyle.Type
+DIA.ConnectionCrossingStyle.Type.None : DIA.ConnectionCrossingStyle.Type
\ No newline at end of file
index 802881e1610efa52d787e0670edddb4c291e45de..d89c07c4f3a82034fa5700e819dc8a299f3c2224 100644 (file)
@@ -46,8 +46,8 @@ public class ConnectionVisuals {
         if (color == null)
             return null;
         if (color.length == 3)
-            return new Color(color[2], color[1], color[0]);
-        return new Color(color[2], color[1], color[0], color[3]);
+            return new Color(color[0], color[1], color[2]);
+        return new Color(color[0], color[1], color[2], color[3]);
     }
 
     @Override
index a50c190b9b27fdb13a2446bd89e6b36ee5c10214..f7dd3a0fda9f66aa675a6fcc7d31ac0f9f801db2 100644 (file)
  *******************************************************************************/
 package org.simantics.diagram.elements;
 
+import java.awt.Color;
 import java.awt.Font;
-import java.awt.font.FontRenderContext;
-import java.awt.font.TextLayout;
-import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
 
 import org.simantics.g2d.element.ElementHints;
@@ -65,13 +63,14 @@ public class TextElementHandler extends TextElementNoBounds implements InternalS
 
        @Override
     public Rectangle2D getBounds(IElement e, Rectangle2D size) {
-        return calculateBounds(e, size, horizontalAlignment, scale, paddingX, paddingY);
+        return calculateBounds(e, size, horizontalAlignment, verticalAlignment, scale, paddingX, paddingY);
     }
     
     public static Rectangle2D calculateBounds(
             IElement e,
             Rectangle2D size, 
             Alignment horizontalAlignment, 
+            Alignment verticalAlignment,
             double scale,
             double paddingX,
             double paddingY) {
@@ -89,16 +88,16 @@ public class TextElementHandler extends TextElementNoBounds implements InternalS
             String text = e.getHint(ElementHints.KEY_TEXT);
             Font font = e.getHint(ElementHints.KEY_FONT);
             if(text == null || font == null)
-                size.setFrame(0, 0, 0, 0);
+               size.setFrame(0, 0, 0, 0);
             else {
-                FontRenderContext FRC = new FontRenderContext(new AffineTransform(), true, true);
-                TextLayout tl = new TextLayout(text, font, FRC);
-                Rectangle2D bounds = tl.getLogicalHighlightShape(0, text.length()).getBounds2D();   
-                size.setFrame(
-                        getAlignedXCoordinate(bounds, horizontalAlignment) * scale - paddingX,
-                        bounds.getY() * scale -paddingY, 
-                        bounds.getWidth()* scale + paddingX + paddingX, 
-                        bounds.getHeight()* scale + paddingY + paddingY);
+                   TextNode n= new TextNode();
+                   n.init(text, font, Color.black, 0.0, 0.0, scale);
+                   n.setHorizontalAlignment((byte)horizontalAlignment.ordinal());
+                   n.setVerticalAlignment((byte)verticalAlignment.ordinal());
+                   
+                   Rectangle2D r = n.getBoundsInLocal();
+                   size.setFrame(r);
+                   return r;
             }
         }
         return size;
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectionCrossingsParticipant.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectionCrossingsParticipant.java
new file mode 100644 (file)
index 0000000..10949ca
--- /dev/null
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.diagram.participant;
+
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.procedure.Listener;
+import org.simantics.diagram.connection.rendering.ConnectionCrossings;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.SGDesignation;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
+import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
+import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.scenegraph.g2d.nodes.ConnectionCrossingsNode;
+import org.simantics.utils.datastructures.Pair;
+import org.simantics.utils.ui.ErrorLogger;
+
+public class ConnectionCrossingsParticipant extends AbstractDiagramParticipant {
+    private static final String CONNECTION_CROSSINGS_NODE_KEY = "connection-crossings";
+
+    private ConnectionCrossingsNode ccNode;
+    private final ConnectionCrossings crossings = new ConnectionCrossings();
+    private ConnectionCrossingStyleListener listener;
+    private Resource diagram;
+    
+    public ConnectionCrossingsParticipant(Resource diagram) {
+        this.diagram = diagram;
+    }
+    public ConnectionCrossingsParticipant(double width, ConnectionCrossings.Type type) {
+        crossings.setWidth(width);
+        crossings.setType(type);
+    }
+
+    @SGInit(designation = SGDesignation.CONTROL)
+    public void initSG(G2DParentNode parent) {
+        ccNode = parent.addNode(CONNECTION_CROSSINGS_NODE_KEY, ConnectionCrossingsNode.class);
+        ccNode.setCrossings(crossings);
+        ccNode.setZIndex(Integer.MIN_VALUE / 4);
+    }
+
+    @SGCleanup
+    public void cleanupSG() {
+        if (ccNode != null) {
+            ccNode.remove();
+            ccNode = null;
+        }
+    }
+
+    @Override
+    public void addedToContext(ICanvasContext ctx) {
+        super.addedToContext(ctx);
+
+        if (diagram != null) {
+            listener = new ConnectionCrossingStyleListener(ctx);
+            Simantics.getSession().async(new UnaryRead<Resource, Pair<Double, ConnectionCrossings.Type>>(diagram){
+    
+                @Override
+                public Pair<Double, ConnectionCrossings.Type> perform(ReadGraph graph) throws DatabaseException {
+                    DiagramResource DIA = DiagramResource.getInstance(graph);
+                    Double gap = graph.getPossibleRelatedValue(diagram, DIA.ConnectionCrossingStyle_Width);
+                    Resource typeRes = graph.getPossibleObject(diagram, DIA.ConnectionCrossingStyle_HasType);
+                    ConnectionCrossings.Type type;
+                    if (DIA.ConnectionCrossingStyle_Type_Gap.equals(typeRes)) {
+                        type = ConnectionCrossings.Type.GAP;
+                    } else if (DIA.ConnectionCrossingStyle_Type_Arc.equals(typeRes)) {
+                        type = ConnectionCrossings.Type.ARC;
+                    } else if (DIA.ConnectionCrossingStyle_Type_Square.equals(typeRes)) {
+                        type = ConnectionCrossings.Type.SQUARE;
+                    } else { 
+                        type = ConnectionCrossings.Type.NONE;
+                    }
+                    return new Pair<>(gap, type);
+                }
+                
+            }, listener);
+        }
+    }
+
+    @Override
+    public void removedFromContext(ICanvasContext ctx) {
+        if (listener != null) {
+            listener.dispose();
+            listener = null;
+        }
+        super.removedFromContext(ctx);
+    }
+
+    class ConnectionCrossingStyleListener implements Listener<Pair<Double, ConnectionCrossings.Type>> {
+        ICanvasContext context;
+        public ConnectionCrossingStyleListener(ICanvasContext context) {
+            this.context = context;
+        }
+        @Override
+        public void execute(final Pair<Double, ConnectionCrossings.Type> result) {
+            context.getThreadAccess().asyncExec(new Runnable() {
+                @Override
+                public void run() {
+                    ICanvasContext ctx = context;
+                    if (ctx == null)
+                        return;
+                    if (ctx.isDisposed())
+                        return;
+                    crossings.setWidth(result.first != null ? result.first : 0.0);
+                    crossings.setType(result.second);
+                    ccNode.repaint();
+                }
+            });
+        }
+        public void dispose() {
+            context = null;
+        }
+        @Override
+        public boolean isDisposed() {
+            return context == null || context.isDisposed();
+        }
+        @Override
+        public void exception(Throwable t) {
+            ErrorLogger.defaultLogError(t);
+        }
+    }
+
+}
index 73b795343d9c5d9b65acbf9643263a0948314690..01d730c0c30b0d2f14277434b3c29264caf7bc4d 100644 (file)
@@ -14,7 +14,7 @@ DOC.Document.ChildRelation <T STR.ConnectionRelation
 DOC.Document.IsConnectedToChild <R STR.IsConnectedTo : DOC.Document.ChildRelation
 
 DOC.ConnectionType : STR.ConnectionType
-    G2D.HasColor [0.8,0.64,0.0] : G2D.Color
+    G2D.HasColor [0.0,0.64,0.8,1.0] : G2D.Color
     G2D.HasStrokeType G2D.StrokeType.Scaling
     G2D.HasStroke _ : G2D.Stroke
         G2D.HasStrokeWidth 0.2 : L0.Float
@@ -166,7 +166,7 @@ DOC.Document.CommandRelation <T STR.ConnectionRelation
 DOC.Document.IsConnectedToCommand <R STR.IsConnectedTo : DOC.Document.CommandRelation
 
 DOC.CommandConnectionType : STR.ConnectionType
-    G2D.HasColor [1.0,0.0,1.0] : G2D.Color
+    G2D.HasColor [1.0,0.0,1.0,1.0] : G2D.Color
     G2D.HasStrokeType G2D.StrokeType.Scaling
     G2D.HasStroke _ : G2D.Stroke
         G2D.HasStrokeWidth 0.2 : L0.Float
@@ -683,7 +683,7 @@ DOC.DataStroke : G2D.Stroke
     G2D.HasLineJoin G2D.LineJoin.MiterJoin
 
 DOC.DataConnectionType : STR.ConnectionType
-    G2D.HasColor [0,0.65,1.0] : G2D.Color
+    G2D.HasColor [1,0.65,0.0,1.0] : G2D.Color
     G2D.HasStrokeType G2D.StrokeType.Scaling
     G2D.HasStroke DOC.DataStroke
     G2D.HasRounding 3.0
@@ -757,7 +757,7 @@ DOC.Document.DataDefinitionRelation <T STR.ConnectionRelation
 DOC.Document.IsConnectedToDataDefinition <R STR.IsConnectedTo : DOC.Document.DataDefinitionRelation
 
 DOC.DataDefinitionConnectionType : STR.ConnectionType
-    G2D.HasColor [0,0.65,1.0] : G2D.Color
+    G2D.HasColor [1.0,0.65,0.0,1.0] : G2D.Color
     G2D.HasStrokeType G2D.StrokeType.Scaling
     G2D.HasStroke DOC.DataStroke
     G2D.HasRounding 3.0
index b08fbdaaedafe459f24ae90a5e18698fcbf2e4b1..37deca7b3508dc1426f06845a9b850afdccc87d8 100644 (file)
@@ -211,7 +211,7 @@ G2D.HasVerticalAlignment <R L0.IsRelatedTo : L0.FunctionalRelation
 G2D.Color <T L0.Literal
     @L0.assert L0.HasDataType $(Float[4])
     @L0.assert L0.HasValueType "Vector Float"
-    L0.HasDescription "A 4-component BGRA color as floats."
+    L0.HasDescription "A 4-component RGBA color as floats."
     
 G2D.HasColor <R L0.HasProperty : L0.FunctionalRelation
     L0.HasLabel "Color"
index 409aecbea26dc04ef73d9851b5fa31f9eb0eb234..489ebd6c700a65a6dd7e70dcf8a42d6c9e93a2eb 100644 (file)
@@ -67,6 +67,7 @@ import org.simantics.diagram.handler.DeleteHandler;
 import org.simantics.diagram.handler.ExpandSelectionHandler;
 import org.simantics.diagram.handler.SimpleElementTransformHandler;
 import org.simantics.diagram.layer.ILayersViewPage;
+import org.simantics.diagram.participant.ConnectionCrossingsParticipant;
 import org.simantics.diagram.participant.ContextUtil;
 import org.simantics.diagram.participant.PointerInteractor2;
 import org.simantics.diagram.participant.SGFocusParticipant;
@@ -330,6 +331,7 @@ public class DiagramViewer
         //ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));
         //ctx.add(new TooltipParticipant());
         ctx.add(new TerminalTooltipParticipant());
+        ctx.add(new ConnectionCrossingsParticipant(getInputResource()));
     }
 
     protected void addPainterParticipants(ICanvasContext ctx) {
index 3ca0cf698f482d1b768c063c5e538285c0d35469..302e074fce35fe9a202c743119e15afd397eb23f 100644 (file)
@@ -36,6 +36,7 @@ import org.simantics.diagram.handler.CopyPasteStrategy;
 import org.simantics.diagram.handler.DefaultCopyPasteStrategy;
 import org.simantics.diagram.handler.DeleteHandler;
 import org.simantics.diagram.handler.SimpleElementTransformHandler;
+import org.simantics.diagram.participant.ConnectionCrossingsParticipant;
 import org.simantics.diagram.query.DiagramRequests;
 import org.simantics.diagram.runtime.RuntimeDiagramManager;
 import org.simantics.diagram.stubs.DiagramResource;
@@ -251,6 +252,7 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi
         ctx.add( new Selection() );
         ctx.add( new DiagramParticipant() );
         ctx.add( new ElementPainter(true) );
+        ctx.add( new ConnectionCrossingsParticipant(resource));
 
         //ctx.add( new ElementHeartbeater() );
         ctx.add( new ZOrderHandler() );
index 31295b9b692f60178c422ad7dda719089d87b76c..10e2abe67fb1f347ce8cc91dcf9553d9abc7c529 100644 (file)
@@ -44,7 +44,7 @@ public class ObserverGroupListener implements SetListener<Resource> {
     public void add(Resource item) {
         //System.out.println("Add to group(" + this + "): " + item);
         items.put(item, item);
-        observer.update();
+        observer.update(style, item);
     }
 
     @Override
@@ -52,7 +52,7 @@ public class ObserverGroupListener implements SetListener<Resource> {
 //        new Exception().printStackTrace();
         //System.out.println("Remove from group(" + this + "): " + item);
         items.remove(item);
-        observer.update();
+        observer.update(style, item);
     }
 
     @Override
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java
new file mode 100644 (file)
index 0000000..a46c4e7
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.scenegraph.g2d.nodes;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+import org.simantics.diagram.connection.rendering.ConnectionCrossings;
+import org.simantics.diagram.connection.rendering.ConnectionRenderingHints;
+import org.simantics.scenegraph.g2d.G2DNode;
+
+public class ConnectionCrossingsNode extends G2DNode {
+
+    private static final long serialVersionUID = -696142275610396889L;
+
+    private ConnectionCrossings crossings;
+    
+    @Override
+    public void render(Graphics2D g) {
+        crossings.reset();
+        if (crossings.getWidth() > 0 && crossings.getType() != ConnectionCrossings.Type.NONE)  {
+            g.setRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER, crossings);
+        } else {
+            g.setRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER, null);
+        }
+    }
+    
+    public void setCrossings(ConnectionCrossings crossings) {
+        this.crossings = crossings;
+    }
+
+    @Override
+    public Rectangle2D getBoundsInLocal() {
+        return null;
+    }
+    
+    public ConnectionCrossings getConnectionCrossings() {
+        return crossings;
+    }
+}