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
SingleElementNode diagramParent;
RTreeNode elementParent;
- boolean paintSelectionFrames;
+ ElementPainterConfiguration cfg;
/**
* Internally reused to avert constant reallocation.
}
public ElementPainter(boolean paintSelectionFrames) {
- this.paintSelectionFrames = paintSelectionFrames;
+ this(new ElementPainterConfiguration().paintSelectionFrames(paintSelectionFrames));
+ }
+
+ public ElementPainter(ElementPainterConfiguration cfg) {
+ this.cfg = cfg;
}
@Override
Object task = BEGIN("EP.updateSelections");
try {
- if (!paintSelectionFrames)
+ if (!cfg.paintSelectionFrames)
return;
if (selection == null)
return;
Object task = BEGIN("EP.updateSelection");
try {
- if (!paintSelectionFrames)
+ if (!cfg.paintSelectionFrames)
return;
G2DParentNode elementNode = (G2DParentNode) el.getHint(ElementHints.KEY_SG_NODE);
Color color = getSelectionColor(selectionId);
G2DParentNode selectionsNode = getSelectionsNode(selectionId);
+ Class<? extends G2DParentNode> 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);
--- /dev/null
+package org.simantics.g2d.diagram.participant;
+
+import org.simantics.scenegraph.g2d.G2DParentNode;
+
+public class ElementPainterConfiguration {
+
+ public boolean paintSelectionFrames = true;
+
+ public Class<? extends G2DParentNode> selectionNodeClass;
+
+ public ElementPainterConfiguration paintSelectionFrames(boolean paint) {
+ this.paintSelectionFrames = paint;
+ return this;
+ }
+
+ public ElementPainterConfiguration selectionNodeClass(Class<? extends G2DParentNode> clazz) {
+ this.selectionNodeClass = clazz;
+ return this;
+ }
+
+}
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);
+ }
}
}
}
//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()));
+ }
+
}