From 452670c58399d8054872655841ebb6e66d9c6b6e Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Wed, 20 Nov 2019 16:33:29 +0200 Subject: [PATCH] G2DParentNode handles "undefined" child bounds separately Previously nodes could only return null to say "I have no bounds". Now it is possible to return GeometryUtils.undefinedBounds() to say "ignore my bounds" to G2DParentNode. Also allow customization of the node class used by ElementPainter to mark selections under "element nodes" through a new configuration class ElementPainterConfiguration. This allows e.g. district to use its own node for this purpose to optimize the scene graph and customize the bounds it returns. gitlab #419 Change-Id: I210fd26be5d269847277616b9d5c52ef4f930dd7 (cherry picked from commit ad29e24f50e336add4c28df14312b3134ab93427) --- .../diagram/participant/ElementPainter.java | 16 +++-- .../ElementPainterConfiguration.java | 21 ++++++ .../scenegraph/g2d/G2DParentNode.java | 10 +-- .../scenegraph/utils/GeometryUtils.java | 72 ++++++++++++++++++- 4 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainterConfiguration.java diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java index 71b87c714..7896e52a7 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java @@ -158,7 +158,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos SingleElementNode diagramParent; RTreeNode elementParent; - boolean paintSelectionFrames; + ElementPainterConfiguration cfg; /** * Internally reused to avert constant reallocation. @@ -174,7 +174,11 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos } public ElementPainter(boolean paintSelectionFrames) { - this.paintSelectionFrames = paintSelectionFrames; + this(new ElementPainterConfiguration().paintSelectionFrames(paintSelectionFrames)); + } + + public ElementPainter(ElementPainterConfiguration cfg) { + this.cfg = cfg; } @Override @@ -828,7 +832,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos Object task = BEGIN("EP.updateSelections"); try { - if (!paintSelectionFrames) + if (!cfg.paintSelectionFrames) return; if (selection == null) return; @@ -934,7 +938,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos Object task = BEGIN("EP.updateSelection"); try { - if (!paintSelectionFrames) + if (!cfg.paintSelectionFrames) return; G2DParentNode elementNode = (G2DParentNode) el.getHint(ElementHints.KEY_SG_NODE); @@ -980,12 +984,14 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos Color color = getSelectionColor(selectionId); G2DParentNode selectionsNode = getSelectionsNode(selectionId); + Class selectionNodeClass = cfg.selectionNodeClass != null ? cfg.selectionNodeClass : G2DParentNode.class; + for (IElement e : selection) { Node elementNode = e.getHint(ElementHints.KEY_SG_NODE); // System.out.println("selectionNode: " + elementNode + " " + e); if (elementNode instanceof G2DParentNode) { G2DParentNode en = (G2DParentNode) elementNode; - G2DParentNode selectionNode = en.getOrCreateNode(NodeUtil.SELECTION_NODE_NAME, G2DParentNode.class); + G2DParentNode selectionNode = en.getOrCreateNode(NodeUtil.SELECTION_NODE_NAME, selectionNodeClass); selectionNode.setZIndex(SELECTION_PAINT_PRIORITY); if (selectionNodes != null) selectionNodes.add(selectionNode); diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainterConfiguration.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainterConfiguration.java new file mode 100644 index 000000000..304b4e6d3 --- /dev/null +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainterConfiguration.java @@ -0,0 +1,21 @@ +package org.simantics.g2d.diagram.participant; + +import org.simantics.scenegraph.g2d.G2DParentNode; + +public class ElementPainterConfiguration { + + public boolean paintSelectionFrames = true; + + public Class selectionNodeClass; + + public ElementPainterConfiguration paintSelectionFrames(boolean paint) { + this.paintSelectionFrames = paint; + return this; + } + + public ElementPainterConfiguration selectionNodeClass(Class clazz) { + this.selectionNodeClass = clazz; + return this; + } + +} diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java index de4631e77..af8c5630d 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/G2DParentNode.java @@ -353,10 +353,12 @@ public class G2DParentNode extends ParentNode implements IG2DNode, Ini if(b == null && !ignoreNulls) return null; if(b != null) { - if(bounds == null) { - bounds = b.getFrame(); - } else { - bounds.add(b); + if(!GeometryUtils.isUndefinedRectangle(b)) { + if(bounds == null) { + bounds = b.getFrame(); + } else { + bounds.add(b); + } } } } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/GeometryUtils.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/GeometryUtils.java index a3f4ec8be..cdda4f45c 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/GeometryUtils.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/GeometryUtils.java @@ -507,5 +507,75 @@ public final class GeometryUtils { //System.out.println("FIT TRANSFORM: " + at); return at; } - + + private static class UndefinedRectangle extends Rectangle2D { + + @Override + public void setRect(double x, double y, double w, double h) { + throw new UnsupportedOperationException("UndefinedRectangle is immutable"); + } + + @Override + public int outcode(double x, double y) { + return OUT_LEFT | OUT_TOP | OUT_RIGHT | OUT_BOTTOM; + } + + private Rectangle2D copy(Rectangle2D r) { + Rectangle2D dest; + if (r instanceof Float) { + dest = new Rectangle2D.Float(); + } else { + dest = new Rectangle2D.Double(); + } + dest.setFrame(r); + return dest; + } + + @Override + public Rectangle2D createIntersection(Rectangle2D r) { + return copy(r); + } + + @Override + public Rectangle2D createUnion(Rectangle2D r) { + return copy(r); + } + + @Override + public double getX() { + return java.lang.Double.NaN; + } + + @Override + public double getY() { + return java.lang.Double.NaN; + } + + @Override + public double getWidth() { + return 0; + } + + @Override + public double getHeight() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + } + + private static final UndefinedRectangle UNDEFINED_RECTANGLE = new UndefinedRectangle(); + + public static Rectangle2D undefinedRectangle() { + return UNDEFINED_RECTANGLE; + } + + public static boolean isUndefinedRectangle(Rectangle2D r) { + return r == UNDEFINED_RECTANGLE || (r.isEmpty() && Double.isNaN(r.getX()) && Double.isNaN(r.getY())); + } + } -- 2.43.2