From 5f0ad7a26810df602600c5eddad317588fce0ac4 Mon Sep 17 00:00:00 2001 From: Antti Villberg Date: Mon, 29 May 2017 15:06:26 +0300 Subject: [PATCH] Diagram to SVG enhancements refs #7253 Change-Id: I155f57928428f8ec4c39ffad90558396547dc10f --- .../ui/sg/DiagramSceneGraphProvider.java | 2 +- .../org/simantics/modeling/SCLScenegraph.java | 142 +++++++++++++++--- .../scenegraph/g2d/nodes/SelectionNode.java | 11 ++ .../g2d/nodes/connection/RouteGraphNode.java | 12 +- 4 files changed, 146 insertions(+), 21 deletions(-) diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java index 3d800d1f1..97d23f05f 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java @@ -244,7 +244,7 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi ctx.add( new ElementInteractor() ); ctx.add( new Selection() ); ctx.add( new DiagramParticipant() ); - ctx.add( new ElementPainter(false) ); + ctx.add( new ElementPainter(true) ); //ctx.add( new ElementHeartbeater() ); ctx.add( new ZOrderHandler() ); diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java index 358d50fb4..5dde0b081 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java @@ -1,5 +1,6 @@ package org.simantics.modeling; +import java.awt.BasicStroke; import java.awt.Dimension; import java.awt.RenderingHints; import java.awt.RenderingHints.Key; @@ -36,6 +37,7 @@ import org.simantics.g2d.diagram.participant.Selection; import org.simantics.g2d.element.IElement; import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider; import org.simantics.g2d.utils.CanvasUtils; +import org.simantics.scenegraph.INode; import org.simantics.scenegraph.ParentNode; import org.simantics.scenegraph.g2d.G2DParentNode; import org.simantics.scenegraph.g2d.G2DRenderingHints; @@ -50,7 +52,9 @@ import org.simantics.scenegraph.g2d.nodes.DataNode; import org.simantics.scenegraph.g2d.nodes.DecorationSVGNode; import org.simantics.scenegraph.g2d.nodes.NavigationNode; import org.simantics.scenegraph.g2d.nodes.SVGNode; +import org.simantics.scenegraph.g2d.nodes.SelectionNode; import org.simantics.scenegraph.g2d.nodes.SingleElementNode; +import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode; import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode; import org.simantics.scenegraph.utils.NodeUtil; import org.simantics.trend.impl.ItemNode; @@ -443,10 +447,18 @@ public class SCLScenegraph { // Create an instance of the SVG Generator. SVGGraphics2D svgGenerator = new Generator(document); - StringBuilder b = new StringBuilder(); + StringBuilder result = new StringBuilder(); try { + Selection selection = ctx.getAtMostOneItemOfClass(Selection.class); + if (selection != null) { + // This prevents workbench selection from being left over. + // Also prevents scene graph crap from being left on the screen. + IDiagram d = ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM); + selection.setSelection(0, d.getElements()); + } + G2DSceneGraph sg = ctx.getSceneGraph(); G2DParentNode root = (G2DParentNode) sg.getRootNode(); @@ -481,69 +493,161 @@ public class SCLScenegraph { double trX = -1 * content.getX(); double trY = -1 * content.getY(); - b.append(""); + result.append(""); IG2DNodeVisitor visitor = new IG2DNodeVisitor() { int indent = 0; - HashMap enters = new HashMap<>(); + HashMap senBuilders = new HashMap<>(); @Override public void enter(IG2DNode node) { + + StringBuilder parentBuilder = getParentBuilder(node); + indent++; if(node instanceof ConnectionNode) { + + for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) { + n.setIgnoreSelection(true); + } + + String key = ((ConnectionNode)node).getKey().toString(); + + parentBuilder.append("\n"); Element doc = renderSVGNode((IG2DNode)node); String svg = printSVGDocument(doc); - b.append(svg); + parentBuilder.append(svg); + + for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) { + n.setIgnoreSelection(false); + } + + parentBuilder.append("\n"); + doc = renderSVGNode((IG2DNode)node); + svg = printSVGDocument(doc); + parentBuilder.append(svg); + parentBuilder.append("\n"); + + BasicStroke bs = new BasicStroke(5f); + + for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) { + n.setDynamicStroke(bs); + } + + parentBuilder.append("\n"); + doc = renderSVGNode((IG2DNode)node); + svg = printSVGDocument(doc); + parentBuilder.append(svg); + parentBuilder.append("\n"); + + parentBuilder.append("\n"); + + } else if (node instanceof SelectionNode) { + + SelectionNode n = (SelectionNode)node; + SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class); + if(parentSEN != null && parentSEN.getKey() != null) { + + StringBuilder parentBuilder2 = getParentBuilder(parentSEN); + + String key = parentSEN.getKey().toString(); + Element doc = renderSVGNode((IG2DNode)node); + String svg = printSVGDocument(doc); + parentBuilder2.append("\n"); + parentBuilder2.append(svg); + parentBuilder2.append("\n"); + parentBuilder2.append("\n"); + Rectangle2D rect = n.getRect(); + parentBuilder2.append(""); + parentBuilder2.append("\n"); + } } else if (node instanceof SVGNode) { SVGNode svg = (SVGNode)node; - b.append(svg.getSVGText()); + parentBuilder.append(svg.getSVGText()); } else if (node instanceof G2DParentNode) { AffineTransform at = node.getTransform(); if(node instanceof SingleElementNode) { SingleElementNode sen = (SingleElementNode)node; if(sen.getKey() != null) { String key = sen.getKey().toString(); - b.append("\n"); + parentBuilder.append("\n"); } + senBuilders.put(sen, new StringBuilder()); } if(!at.isIdentity()) { if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) { String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")"; - b.append("\n"); + parentBuilder.append("\n"); } else { double[] ds = new double[6]; at.getMatrix(ds); String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")"; - b.append("\n"); + parentBuilder.append("\n"); } } } - enters.put(node, b.length()); + //enters.put(node, b.length()); } + + private StringBuilder getParentBuilder(IG2DNode node) { + + INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class); + if(parentSEN instanceof G2DSceneGraph) return result; + + StringBuilder parentBuilder = senBuilders.get(parentSEN); + if(parentBuilder == null) return result; + + return parentBuilder; + + } @Override public void leave(IG2DNode node) { + if(node instanceof ConnectionNode || node instanceof SVGNode) { // We are done } else if (node instanceof G2DParentNode) { + + StringBuilder parentBuilder = getParentBuilder(node); + + if(node instanceof SingleElementNode) { + SingleElementNode sen = (SingleElementNode)node; +// if(sen.getKey() != null) { + StringBuilder b = senBuilders.get(sen); + String content = b.toString(); + if(content.isEmpty()) { + if(sen.getKey() != null) { + + for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) { + n.setIgnore(true); + } + + Element doc = renderSVGNode((IG2DNode)node); + String svg = printSVGDocument(doc); + parentBuilder.append(svg); + } + } else { + parentBuilder.append(content); + } +// } + } + + AffineTransform at = node.getTransform(); if(!at.isIdentity()) { - b.append(""); + parentBuilder.append(""); } if(node instanceof SingleElementNode) { SingleElementNode sen = (SingleElementNode)node; if(sen.getKey() != null) { - int enterLength = enters.get(node); - if(b.length() == enterLength) { - Element doc = renderSVGNode((IG2DNode)node); - String svg = printSVGDocument(doc); - b.append(svg); - } - b.append(""); + parentBuilder.append(""); } } } @@ -557,10 +661,10 @@ public class SCLScenegraph { LOGGER.error("Problems rendering canvas context to SVG", t); } - b.append(""); + result.append(""); //System.err.println(" == FINAL RESULT == "); //System.err.println(b); - return b.toString(); + return result.toString(); } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SelectionNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SelectionNode.java index b5b8c4151..445a66fe3 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SelectionNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SelectionNode.java @@ -35,7 +35,12 @@ public class SelectionNode extends G2DNode implements Decoration { protected transient Rectangle2D rect; protected transient BasicStroke scaledStroke; protected transient double previousScaleRecip = Double.NaN; + private boolean ignore = false; + public void setIgnore(boolean value) { + ignore = value; + } + @SyncField({"transform", "bounds", "color"}) public void init(AffineTransform transform, Rectangle2D bounds, Color color) { this.transform = transform; @@ -46,6 +51,8 @@ public class SelectionNode extends G2DNode implements Decoration { @Override public void render(Graphics2D g) { if (bounds == null) return; + + if (ignore) return; // Prevent exceptions during rendering. if (transform.getDeterminant() == 0) @@ -84,6 +91,10 @@ public class SelectionNode extends G2DNode implements Decoration { g.setTransform(ot); } + + public Rectangle2D getRect() { + return transform.createTransformedShape(rect).getBounds2D(); + } @Override public Rectangle2D getBoundsInLocal() { diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java index 69268bad0..687731f4c 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/connection/RouteGraphNode.java @@ -124,12 +124,22 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In protected transient Map dynamicStyles = null; + private transient boolean ignoreSelection = false; + @Override public void initValues() { dynamicColor = null; wrapRenderer(); } + public void setIgnoreSelection(boolean value) { + ignoreSelection = value; + } + + public boolean getIgnoreSelection() { + return ignoreSelection; + } + @PropertySetter("color") @SyncField(value = {"dynamicColor"}) public void setDynamicColor(Color color) { @@ -347,7 +357,7 @@ public class RouteGraphNode extends G2DNode implements ISelectionPainterNode, In Object aaHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - boolean selected = NodeUtil.isSelected(this, 1); + boolean selected = ignoreSelection ? false : NodeUtil.isSelected(this, 1); rg.updateTerminals(); -- 2.43.2