From: jsimomaa Date: Fri, 31 Jan 2020 09:51:51 +0000 (+0200) Subject: Move edge arrow rendering to a separate node forcing render on top X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F51%2F3751%2F1;p=simantics%2Fdistrict.git Move edge arrow rendering to a separate node forcing render on top gitlab #76 Change-Id: Ib8f99e814588756e7e320e3d9c168ab4a67a3b27 (cherry picked from commit 47a6ef4077aacf0ac5753ee568183bbed5d27411) --- diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeArrayNode.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeArrayNode.java new file mode 100644 index 00000000..c387c435 --- /dev/null +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeArrayNode.java @@ -0,0 +1,104 @@ +package org.simantics.district.network.ui.nodes; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Line2D; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.district.network.ui.styles.DistrictNetworkStaticInfoStyle; +import org.simantics.scenegraph.ParentNode; +import org.simantics.scenegraph.g2d.G2DNode; +import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.utils.datastructures.Pair; + +public class DistrictNetworkEdgeArrayNode extends G2DNode implements DeferredNode { + + private static final long serialVersionUID = -8377444630205663419L; + + public static final String NODE_KEY = "DISTRICT_NETWORK_EDGE_ARRAY"; + + private static final String RENDERER_ID = "edgeArrayDeferredRenderer"; + + private DistrictNetworkEdgeNode edgeNode = null; + private Double arrowLength; + private Path2D arrowPath; + + @Override + public void render(Graphics2D g2d) { + ParentNode root = (ParentNode) NodeUtil.getNearestParentOfType(this, RTreeNode.class); + DeferredRenderingNode deferred = root != null ? (DeferredRenderingNode) root.getNode(DistrictNetworkStaticInfoStyle.STATIC_INFO_DEFERRED) : null; + if (deferred != null) + deferred.deferNode(g2d.getTransform(), this); + else + renderDeferred(g2d); + } + + @Override + public void renderDeferred(Graphics2D g2d) { + + // Draw arrow + if (arrowLength != null) { + double scale = DistrictNetworkEdgeNode.scaleStroke ? (Double) g2d.getRenderingHint(DistrictRenderingHints.KEY_VIEW_SCALE_UNDER_SPATIAL_ROOT) : 1.0; + g2d.setColor(Color.BLACK); + float lw = DistrictNetworkEdgeNode.STROKE.getLineWidth() / (float)scale; + g2d.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); + + double l = arrowLength; + double w = 2 * (double) lw * Math.signum(l); + if (Math.abs(w) > Math.abs(l)) w = l; + double offset = 2 * (double) lw; + + int zoomLevel = (Integer) g2d.getRenderingHint(DistrictRenderingHints.KEY_VIEW_ZOOM_LEVEL); + + Point2D centerPoint = edgeNode.getCenterPoint(zoomLevel); + Point2D direction = edgeNode.getDirection(zoomLevel); + double centerX = centerPoint.getX(), centerY = centerPoint.getY(); + double deltaX = direction.getX(), deltaY = direction.getY(); + + // Ensure the line is always rendered on top of the edge + // to prevent overlap with static info rendered below it. + double odx = offset * deltaY; + double ody = offset * deltaX; + if (odx < 0) { + odx = -odx; + ody = -ody; + } + + double x0 = centerX - l/2 * deltaX + ody; + double y0 = centerY - l/2 * deltaY - odx; + double x1 = centerX + (l/2 - w) * deltaX + ody; + double y1 = centerY + (l/2 - w) * deltaY - odx; + + g2d.draw(new Line2D.Double(x0, y0, x1, y1)); + + arrowPath = new Path2D.Double(); + arrowPath.moveTo(x1 + w * deltaX, y1 + w * deltaY); + arrowPath.lineTo(x1 + w * deltaY, y1 - w * deltaX); + arrowPath.lineTo(x1 - w * deltaY, y1 + w * deltaX); + arrowPath.closePath(); + g2d.fill(arrowPath); + } + } + + @Override + public Rectangle2D getBoundsInLocal() { + return null; + } + + public void setEdgeNode(DistrictNetworkEdgeNode edgeNode) { + this.edgeNode = edgeNode; + } + + public void setArrowLength(Double length) { + this.arrowLength = length; + } + + public static Pair> renderer() { + return Pair.make(RENDERER_ID, DeferredRenderingNode.class); + } + +} diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeNode.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeNode.java index e724a68d..195472fc 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeNode.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkEdgeNode.java @@ -26,7 +26,7 @@ public class DistrictNetworkEdgeNode extends G2DParentNode implements ISelection private static final long serialVersionUID = 8049769475036519806L; - private static final BasicStroke STROKE = new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + public static final BasicStroke STROKE = new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); private static final Color SELECTION_COLOR = new Color(255, 0, 255, 96); private DistrictNetworkEdge edge; @@ -36,7 +36,7 @@ public class DistrictNetworkEdgeNode extends G2DParentNode implements ISelection private transient int zoomLevel = 0; - private static boolean scaleStroke = true; + static final boolean scaleStroke = true; private Color color; private Double stroke; private transient Color dynamicColor = null; @@ -59,15 +59,11 @@ public class DistrictNetworkEdgeNode extends G2DParentNode implements ISelection private boolean hidden = false; - private Double arrowLength; - private static double startX; private static double startY; private static double endX; private static double endY; - private Path2D arrowPath; - @Override public void init() { } @@ -119,46 +115,6 @@ public class DistrictNetworkEdgeNode extends G2DParentNode implements ISelection g2d.setStroke(bs); g2d.draw(path); - // Draw arrow - if (arrowLength != null) { - g2d.setColor(Color.BLACK); - float lw = STROKE.getLineWidth() / (float)scale; - g2d.setStroke(new BasicStroke(lw, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - - double l = arrowLength; - double w = 2 * (double) lw * Math.signum(l); - if (Math.abs(w) > Math.abs(l)) w = l; - double offset = 2 * (double) lw; - - Point2D centerPoint = getCenterPoint(zoomLevel); - Point2D direction = getDirection(zoomLevel); - double centerX = centerPoint.getX(), centerY = centerPoint.getY(); - double deltaX = direction.getX(), deltaY = direction.getY(); - - // Ensure the line is always rendered on top of the edge - // to prevent overlap with static info rendered below it. - double odx = offset * deltaY; - double ody = offset * deltaX; - if (odx < 0) { - odx = -odx; - ody = -ody; - } - - double x0 = centerX - l/2 * deltaX + ody; - double y0 = centerY - l/2 * deltaY - odx; - double x1 = centerX + (l/2 - w) * deltaX + ody; - double y1 = centerY + (l/2 - w) * deltaY - odx; - - g2d.draw(new Line2D.Double(x0, y0, x1, y1)); - - arrowPath = new Path2D.Double(); - arrowPath.moveTo(x1 + w * deltaX, y1 + w * deltaY); - arrowPath.lineTo(x1 + w * deltaY, y1 - w * deltaX); - arrowPath.lineTo(x1 - w * deltaY, y1 + w * deltaX); - arrowPath.closePath(); - g2d.fill(arrowPath); - } - // Reset g2d.setStroke(oldStroke); g2d.setColor(oldColor); @@ -315,7 +271,11 @@ public class DistrictNetworkEdgeNode extends G2DParentNode implements ISelection @PropertySetter(value = "arrowLength") public void setArrowLength(Double length) { - arrowLength = length; + // find if there is a child deferred arrow node + DistrictNetworkEdgeArrayNode child = getOrCreateNode(DistrictNetworkEdgeArrayNode.NODE_KEY, DistrictNetworkEdgeArrayNode.class); + child.setEdgeNode(this); + child.setArrowLength(length); + //arrowLength = length; } @PropertySetter(value = "SVG") diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java index d1a81088..36eaaf61 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DynamicVisualisationContributionsParticipant.java @@ -17,6 +17,8 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.district.network.profile.RuntimeDynamicVisualisationsRequest; import org.simantics.district.network.ui.DistrictDiagramViewer; +import org.simantics.district.network.ui.nodes.DeferredRenderingNode; +import org.simantics.district.network.ui.nodes.DistrictNetworkEdgeArrayNode; import org.simantics.district.network.ui.nodes.DistrictNetworkHoverInfoNode; import org.simantics.district.network.ui.nodes.DynamicVisualisationContributionsNode; import org.simantics.district.network.ui.styles.DistrictNetworkHoverInfoStyle; @@ -33,6 +35,7 @@ import org.simantics.scenegraph.INode; import org.simantics.scenegraph.g2d.G2DParentNode; import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; import org.simantics.scenegraph.g2d.events.command.CommandEvent; +import org.simantics.utils.datastructures.Pair; import org.simantics.utils.datastructures.hints.HintListenerAdapter; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintListener; @@ -59,6 +62,7 @@ public class DynamicVisualisationContributionsParticipant extends AbstractCanvas private DynamicVisualisationContributionsNode node; private AffineTransform transform; private DistrictNetworkHoverInfoNode hoverInfoNode; + private DeferredRenderingNode deferredEdgeArrowRendererNode; public DynamicVisualisationContributionsParticipant(AffineTransform tr) { this.transform = tr; @@ -98,6 +102,9 @@ public class DynamicVisualisationContributionsParticipant extends AbstractCanvas hoverInfoNode.setLookupId("districtNetworkHoverInfoNode"); hoverInfoNode.setTransform(transform); hoverInfoNode.setZIndex(Integer.MAX_VALUE - 500); + + Pair> dearn = DistrictNetworkEdgeArrayNode.renderer(); + deferredEdgeArrowRendererNode = parent.addNode(dearn.first, dearn.second); } @EventHandler(priority = 0) diff --git a/org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java b/org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java index e3ede04f..1a16ee55 100644 --- a/org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java +++ b/org.simantics.district.network/src/org/simantics/district/network/visualisations/DynamicVisualisationsContributions.java @@ -247,6 +247,19 @@ public class DynamicVisualisationsContributions { colorContributions = colorContributionSupplier.get().collect(Collectors.toMap(c -> c.getLabel(), c -> c)); return colorContributions; } + + @Override + public String toString() { + return getClass().getSimpleName() + " [" + coloringObject.getName() + " (" + coloringObject.getResource() + "), contributions=" + colorContributionsToString() + "]"; + } + + private String colorContributionsToString() { + + return colorContributions.keySet().stream().map(key -> { + DynamicColorContribution dynamicColorContribution = colorContributions.get(key); + return key + "=" + dynamicColorContribution.getLabel(); + }).collect(Collectors.joining(", ", "{", "}")); + } } public static class DynamicColoringMap {