+ @Override
+ public void enter(IG2DNode node) {
+ if (node instanceof SingleElementNode) {
+ Object key = ((SingleElementNode) node).getKey();
+ if (key != null) {
+ keys.add(key);
+ }
+ }
+ }
+
+ @Override
+ public void leave(IG2DNode node) {
+ // Nothing to do
+ }
+
+ public Set<Object> getKeys() {
+ return keys;
+ }
+ }
+
+ private static class PrintingVisitor implements IG2DNodeVisitor {
+
+ int indent = 0;
+
+ HashMap<SingleElementNode,RenderSVGContext> senBuilders = new HashMap<>();
+
+ private RenderSVGContext result;
+ private SVGGraphics2D svgGenerator;
+
+ private Map<?, ?> mappings;
+
+ public PrintingVisitor(SVGGraphics2D svgGenerator, RenderSVGContext result, Map<?, ?> mappings) {
+ this.result = result;
+ this.mappings = mappings;
+ this.svgGenerator = svgGenerator;
+ }
+
+ private String getKey(SingleElementNode node) {
+ String key;
+ if(node.getKey() != null) {
+ if (mappings.containsKey(node.getKey()))
+ key = mappings.get(node.getKey()).toString();
+ else
+ key = node.getKey().toString();
+ } else {
+ key = Long.toString(node.getId());
+ }
+ return key;
+ }
+
+ @Override
+ public void enter(IG2DNode node) {
+
+ RenderSVGContext parentBuilder = getParentBuilder(node);
+
+ indent++;
+ if(node instanceof ConnectionNode) {
+
+ for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+ n.setIgnoreSelection(true);
+ }
+
+ String key = getKey((ConnectionNode) node);
+ parentBuilder.append(MAIN_SECTION, "\n<g class=\"connection\" id=\"" + key + "\">");
+ parentBuilder.append(SELECTION_SECTION, "\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
+ parentBuilder.append(SELECTION_MASK_SECTION, "\n<g class=\"selectionMask\" opacity=\"0.001\" id=\"" + key + "\">");
+
+ Element doc = renderSVGNode(svgGenerator, (IG2DNode)node);
+ String svg = printSVGDocument(doc);
+ parentBuilder.append(MAIN_SECTION, svg);
+
+ for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+ n.setIgnoreSelection(false);
+ }
+
+ doc = renderSVGNode(svgGenerator, (IG2DNode)node);
+ svg = printSVGDocument(doc);
+ parentBuilder.append(SELECTION_SECTION, svg);
+
+ BasicStroke bs = new BasicStroke(10f);
+
+ for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+ n.setDynamicStroke(bs);
+ }
+
+ doc = renderSVGNode(svgGenerator, (IG2DNode)node);
+ svg = printSVGDocument(doc);
+ parentBuilder.append(SELECTION_MASK_SECTION, svg);
+
+ parentBuilder.append(SELECTION_MASK_SECTION, "\n</g>");
+ parentBuilder.append(SELECTION_SECTION, "\n</g>");
+ parentBuilder.append(MAIN_SECTION, "\n</g>");
+
+ } else if (node instanceof SelectionNode) {
+
+ SelectionNode n = (SelectionNode)node;
+ SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
+ if(parentSEN != null) {
+
+ RenderSVGContext parentBuilder2 = getParentBuilder(parentSEN);
+
+ String key = getKey(parentSEN);
+ n.setIgnore(false);
+ Element doc = renderSVGNode(svgGenerator, (IG2DNode)node);
+ n.setIgnore(true);
+ String svg = printSVGDocument(doc);
+ parentBuilder2.append(SELECTION_SECTION, "\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
+ parentBuilder2.append(SELECTION_SECTION, svg);
+ parentBuilder2.append(SELECTION_SECTION, "\n</g>");
+ parentBuilder2.append(SELECTION_MASK_SECTION, "\n<g class=\"selectionMask\" id=\"" + key /*+ "\" transform=\"" + matrixString + "\"*/+ "\">");
+ Rectangle2D rect = n.getRect();
+ // NaN
+ if(rect.getHeight() == rect.getHeight() && rect.getWidth() == rect.getWidth()) {
+ parentBuilder2.append(SELECTION_MASK_SECTION,"<rect style=\"fill:#fff\" opacity=\"0.001\"");
+ parentBuilder2.append(SELECTION_MASK_SECTION," x=\"" + rect.getX() + "\" y=\"" + rect.getY() + "\"");
+ parentBuilder2.append(SELECTION_MASK_SECTION," width=\"" + rect.getWidth() + "\" height=\"" + rect.getHeight() + "\"");
+ parentBuilder2.append(SELECTION_MASK_SECTION,"></rect>");
+ }
+ parentBuilder2.append(SELECTION_MASK_SECTION,"\n</g>");
+
+ }
+ } else if (node instanceof SVGNode) {
+ SVGNode svg = (SVGNode)node;
+ parentBuilder.append(MAIN_SECTION, svg.getSVGText());
+ } else if (node instanceof G2DParentNode) {
+ AffineTransform at = node.getTransform();
+ if(node instanceof SingleElementNode) {
+ SingleElementNode sen = (SingleElementNode)node;
+ String key = getKey(sen);
+ String typeClass = sen.getTypeClass();
+ String clazz = "definedElement";
+ if(typeClass != null && !typeClass.isEmpty())
+ clazz = clazz + " " + typeClass;
+
+ parentBuilder.append(MAIN_SECTION, "\n<g class=\""+clazz+"\" id=\"" + key + "\">");
+ senBuilders.put(sen, new RenderSVGContext());
+ }
+ 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() + ")";
+ parentBuilder.append(ALL_SECTIONS, "\n<g transform=\"" + m + "\">");
+ } else {
+ double[] ds = new double[6];
+ at.getMatrix(ds);
+ String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")";
+ parentBuilder.append(ALL_SECTIONS, "\n<g transform=\"" + m + "\">");
+ }
+ }
+ }
+
+ //enters.put(node, b.length());
+
+ }
+
+ private RenderSVGContext getParentBuilder(IG2DNode node) {
+
+ INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
+ if(parentSEN instanceof G2DSceneGraph) return result;
+
+ RenderSVGContext 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) {
+
+ RenderSVGContext parentBuilder = getParentBuilder(node);
+
+ if(node instanceof SingleElementNode) {
+ SingleElementNode sen = (SingleElementNode)node;
+ RenderSVGContext b = senBuilders.get(sen);
+ String content = b.get(MAIN_SECTION);
+ if(content.isEmpty()) {
+ if(sen.getKey() != null) {
+
+ for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) {
+ n.setIgnore(true);
+ }
+
+ Element doc = renderSVGNode(svgGenerator, (IG2DNode)node);
+ String svg = printSVGDocument(doc);
+ parentBuilder.append(MAIN_SECTION, svg);
+ }
+ } else {
+ parentBuilder.append(b);
+ }
+ }
+
+ AffineTransform at = node.getTransform();
+ if(!at.isIdentity()) {
+ parentBuilder.append(ALL_SECTIONS, "</g>");
+ }
+ if(node instanceof SingleElementNode) {
+ SingleElementNode sen = (SingleElementNode)node;
+ //if(sen.getKey() != null) {
+ parentBuilder.append(MAIN_SECTION, "</g>");
+ //}
+ }
+ }
+ indent --;
+ }
+ }