From 53fb4ba6399e89bee6790244cbe051453ad41790 Mon Sep 17 00:00:00 2001 From: Laurent Redor Date: Tue, 9 Jul 2024 15:36:19 +0200 Subject: [PATCH] [426] Consider insets and border nodes around children for auto-size * Add method getBottomRightInsets to use it in auto-size computation * Consider shadow border * Consider border nodes when computing children bottom-right corner. Bug: https://github.com/eclipse-sirius/sirius-desktop/issues/426 --- .../ui/internal/refresh/GMFHelper.java | 89 +++++++++++++++---- 1 file changed, 70 insertions(+), 19 deletions(-) diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/GMFHelper.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/GMFHelper.java index f7956bed68..0e6bb63eea 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/GMFHelper.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/internal/refresh/GMFHelper.java @@ -27,6 +27,7 @@ import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Dimension; +import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.draw2d.geometry.Rectangle; @@ -111,9 +112,10 @@ public final class GMFHelper { /** * see org.eclipse.sirius.diagram.ui.internal.edit.parts. AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN - * the Y value is the DEFAULT_MARGIN + the InvisibleResizableCompartmentFigure top Inset (1px) + * the top value is the DEFAULT_MARGIN + the InvisibleResizableCompartmentFigure top Inset (1px) */ - private static Point CONTAINER_INSETS = new Point(AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN, IContainerLabelOffsets.LABEL_OFFSET); + private static Insets CONTAINER_INSETS = new Insets(IContainerLabelOffsets.LABEL_OFFSET, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN, + AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN); /** * The gap in pixels between the Label's icon and its text @@ -180,10 +182,10 @@ public static Dimension getTopLeftInsets(Node container) { // RegionContainer do not have containers insets if (ddec instanceof DNodeContainer) { if (new DNodeContainerExperimentalQuery((DNodeContainer) ddec).isRegionContainer() || hasFullLabelBorder(ddec)) { - result.setHeight(CONTAINER_INSETS.y + getLabelSize(container) + AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); + result.setHeight(CONTAINER_INSETS.top + getLabelSize(container) + AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); } else { - result.setWidth(CONTAINER_INSETS.x); - result.setHeight(CONTAINER_INSETS.y); + result.setWidth(CONTAINER_INSETS.left); + result.setHeight(CONTAINER_INSETS.top); } } Dimension borderSize = getBorderSize(ddec); @@ -219,6 +221,40 @@ public static Dimension getContainerTopLeftInsets(Node node, boolean searchFirst return result; } + /** + * Return the bottom-right insets of the container of this node. The insets also considers its border. + * + * @param container + * The container for which we wish to have the insets. This {@link Node} must correspond to a container, + * otherwise, {0,0} is returned + * @return the bottom-right insets of this container + */ + public static Dimension getBottomRightInsets(Node container) { + Dimension result = new Dimension(0, 0); + NodeQuery nodeQuery = new NodeQuery(container); + if (nodeQuery.isContainer()) { + EObject element = container.getElement(); + if (element instanceof DDiagramElementContainer) { + DDiagramElementContainer ddec = (DDiagramElementContainer) element; + // RegionContainer do not have containers insets + if (ddec instanceof DNodeContainer) { + if (new DNodeContainerExperimentalQuery((DNodeContainer) ddec).isRegionContainer() || hasFullLabelBorder(ddec)) { + // TODO : Not sure about that, to verify + result.setHeight(CONTAINER_INSETS.bottom); + } else { + result.setWidth(CONTAINER_INSETS.right); + result.setHeight(CONTAINER_INSETS.bottom); + } + } + Dimension borderSize = getBorderSize(ddec); + // Added twice as this insets is used to compute the "global" size including the border + result.setWidth(result.width() + (borderSize.width() * 2)); + result.setHeight(result.height() + (borderSize.height() * 2)); + } + } + return result; + } + /** * Return the top-left insets of the container of this node that is after the label. The insets also * considers its border. @@ -239,8 +275,8 @@ public static Dimension getContainerTopLeftInsetsAfterLabel(Node node, boolean s if (nodeQuery.isContainer()) { EObject element = parentNode.getElement(); if (element instanceof DDiagramElementContainer) { - result.setWidth(CONTAINER_INSETS.x); - result.setHeight(CONTAINER_INSETS.y); + result.setWidth(CONTAINER_INSETS.left); + result.setHeight(CONTAINER_INSETS.top); Dimension borderSize = getBorderSize((DDiagramElementContainer) element); result.setWidth(result.width() + borderSize.width()); @@ -436,7 +472,7 @@ public static Rectangle getAbsoluteBounds(Node node, boolean insetsAware) { */ public static Rectangle getAbsoluteBounds(Node node, boolean insetsAware, boolean boxForConnection) { Node currentNode = node; - Rectangle absoluteNodeBounds = getBounds(currentNode, false, false, boxForConnection); + Rectangle absoluteNodeBounds = getBounds(currentNode, false, false, boxForConnection, false); if (currentNode.eContainer() instanceof Node) { currentNode = (Node) currentNode.eContainer(); Point parentNodeLocation = getAbsoluteLocation(currentNode, insetsAware); @@ -572,7 +608,7 @@ public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstra * @return the bounds of the node. */ public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstraint, boolean forceFigureAutoSize) { - return getBounds(node, useFigureForAutoSizeConstraint, forceFigureAutoSize, false); + return getBounds(node, useFigureForAutoSizeConstraint, forceFigureAutoSize, false, false); } /** @@ -588,9 +624,12 @@ public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstra * @param boxForConnection * true if we want to have the bounds used to compute connection anchor from source or target, false * otherwise + * @param recursiveGetBounds + * true if this method is called from a parent "getBounds" call, false otherwise. + * * @return the bounds of the node. */ - public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstraint, boolean forceFigureAutoSize, boolean boxForConnection) { + public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstraint, boolean forceFigureAutoSize, boolean boxForConnection, boolean recursiveGetBounds) { PrecisionRectangle bounds = new PrecisionRectangle(0, 0, 0, 0); LayoutConstraint layoutConstraint = node.getLayoutConstraint(); EObject element = node.getElement(); @@ -619,10 +658,10 @@ public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstra } else { // Make a default size for label (this size is purely an average estimate) - replaceAutoSize(node, bounds, useFigureForAutoSizeConstraint, getLabelDimension(node, new Dimension(50, 20))); + replaceAutoSize(node, bounds, useFigureForAutoSizeConstraint, getLabelDimension(node, new Dimension(50, 20)), recursiveGetBounds); } } else { - replaceAutoSize(node, bounds, useFigureForAutoSizeConstraint, null); + replaceAutoSize(node, bounds, useFigureForAutoSizeConstraint, null, recursiveGetBounds); } if (boxForConnection) { @@ -684,8 +723,10 @@ public static boolean isShadowBorderNeeded(Node node) { * true to use draw2d figure to get size * @param providedDefaultSize * The size used for creation for this kind of node. It is the minimum size. + * @param recursive + * true if this method is called from a "parent" call, false otherwise. */ - private static void replaceAutoSize(Node node, Rectangle bounds, boolean useFigureForAutoSizeConstraint, Dimension providedDefaultSize) { + private static void replaceAutoSize(Node node, Rectangle bounds, boolean useFigureForAutoSizeConstraint, Dimension providedDefaultSize, boolean recursive) { if (bounds.width == -1 || bounds.height == -1) { Dimension defaultSize = providedDefaultSize; if (providedDefaultSize == null) { @@ -727,8 +768,15 @@ private static void replaceAutoSize(Node node, Rectangle bounds, boolean useFigu } else { // Compute the bounds of all children and use the lowest // one (y+height) for height and the rightmost one - // (x+width) for width. - Point bottomRight = getBottomRight(node); + // (x+width) for width plus the margin. + Point bottomRight = getBottomRight(node, recursive); + double shadowBorderSize = getShadowBorderSize(node); + Dimension topLeftInsets = getTopLeftInsets(node); + Dimension bottomRightInsets = getBottomRightInsets(node); + if (!recursive) { + bottomRight.setX(bottomRight.x + Double.valueOf(shadowBorderSize).intValue() + topLeftInsets.width() + bottomRightInsets.width()); + bottomRight.setY(bottomRight.y + Double.valueOf(shadowBorderSize).intValue() + topLeftInsets.height() + bottomRightInsets.height()); + } if (bounds.width == -1) { if (bottomRight.x > defaultSize.width) { bounds.setWidth(bottomRight.x); @@ -798,17 +846,20 @@ private static void lookForNextRegionLocation(Rectangle bounds, Node node) { * * @param node * the node whose bottom right corner is to compute. + * @param considerBorderNode + * true to consider border nodes when computing the bottom right corner point, false otherwise. * * @return Point at the bottom right of the rectangle */ - public static Point getBottomRight(Node node) { + public static Point getBottomRight(Node node, boolean considerBorderNodes) { int right = 0; int bottom = 0; for (Iterator children = Iterators.filter(node.getChildren().iterator(), Node.class); children.hasNext(); /* */) { Node child = children.next(); - // The border nodes are ignored - if (!(new NodeQuery(child).isBorderedNode())) { - Rectangle bounds = getBounds(child); + // The border nodes are ignored, except if it is expected to consider it (auto-size of a container with + // children having border nodes) + if (considerBorderNodes || !(new NodeQuery(child).isBorderedNode())) { + Rectangle bounds = getBounds(child, false, false, false, true); Point bottomRight = bounds.getBottomRight(); if (bottomRight.x > right) { right = bottomRight.x;