Skip to content

Commit

Permalink
[426] Consider insets and border nodes around children for auto-size
Browse files Browse the repository at this point in the history
* Add method getBottomRightInsets to use it in auto-size computation
* Consider shadow border
* Consider border nodes when computing children bottom-right corner.

Bug: #426
  • Loading branch information
lredor committed Jul 29, 2024
1 parent 0cf0236 commit 53fb4ba
Showing 1 changed file with 70 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -219,6 +221,40 @@ public static Dimension getContainerTopLeftInsets(Node node, boolean searchFirst
return result;
}

/**
* Return the bottom-right insets of the container of this <code>node</code>. 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 <code>container</code>
*/
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 <code>node</code> that is after the label. The insets also
* considers its border.
Expand All @@ -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());
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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();
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 <code>node</code>. 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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<Node> 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;
Expand Down

0 comments on commit 53fb4ba

Please sign in to comment.