diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/ViewQuery.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/ViewQuery.java index f9d183de61..cbf7d6bdcd 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/ViewQuery.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/ViewQuery.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2021 THALES GLOBAL SERVICES and others. + * Copyright (c) 2012, 2024 THALES GLOBAL SERVICES and others. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -61,8 +61,11 @@ import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeEditPart; import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeList2EditPart; import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeListEditPart; +import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeListElementEditPart; import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeListName2EditPart; import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeListNameEditPart; +import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeListViewNodeListCompartment2EditPart; +import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeListViewNodeListCompartmentEditPart; import org.eclipse.sirius.diagram.ui.internal.edit.parts.NotationViewIDs; import org.eclipse.sirius.diagram.ui.part.SiriusVisualIDRegistry; import org.eclipse.sirius.diagram.ui.provider.DiagramUIPlugin; @@ -380,6 +383,30 @@ public boolean isFreeFormCompartment() { || type == DNodeContainerViewNodeContainerCompartment2EditPart.VISUAL_ID; } + /** + * Return if this GMF node is associated to DNodeList Sirius diagram element. + */ + public boolean isListContainer() { + int type = SiriusVisualIDRegistry.getVisualID(this.view.getType()); + return type == DNodeListEditPart.VISUAL_ID || type == DNodeList2EditPart.VISUAL_ID; + } + + /** + * Return if this GMF node is compartment of node corresponding to a Sirius list container. + */ + public boolean isListCompartment() { + int type = SiriusVisualIDRegistry.getVisualID(this.view.getType()); + return type == DNodeListViewNodeListCompartmentEditPart.VISUAL_ID // + || type == DNodeListViewNodeListCompartment2EditPart.VISUAL_ID; + } + + /** + * Return if this GMF node is a list item. + */ + public boolean isListItem() { + int type = SiriusVisualIDRegistry.getVisualID(this.view.getType()); + return type == DNodeListElementEditPart.VISUAL_ID; + } /** * Return if this GMF node have vertical/horizontal stack layout. */ 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 d921174887..f94b4723ca 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 @@ -115,9 +115,11 @@ public final class GMFHelper { * see org.eclipse.sirius.diagram.ui.internal.edit.parts. AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN * the top value is the DEFAULT_MARGIN + the InvisibleResizableCompartmentFigure top Inset (1px) */ - private static Insets CONTAINER_INSETS = new Insets(IContainerLabelOffsets.LABEL_OFFSET, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN, + private static Insets FREEFORM_CONTAINER_INSETS = new Insets(IContainerLabelOffsets.LABEL_OFFSET, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN); + private static Insets LIST_CONTAINER_INSETS = new Insets(4, 0, 0, 0); + /** * The gap in pixels between the Label's icon and its text * (org.eclipse.sirius.ext.gmf.runtime.gef.ui.figures.SiriusWrapLabel.getIconTextGap()). @@ -183,11 +185,14 @@ 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.top + getLabelSize(container) + AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); + result.setHeight(FREEFORM_CONTAINER_INSETS.top + getLabelSize(container) + AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); } else { - result.setWidth(CONTAINER_INSETS.left); - result.setHeight(CONTAINER_INSETS.top); + result.setWidth(FREEFORM_CONTAINER_INSETS.left); + result.setHeight(FREEFORM_CONTAINER_INSETS.top); } + } else if (element instanceof DNodeList) { + result.setWidth(LIST_CONTAINER_INSETS.left); + result.setHeight(LIST_CONTAINER_INSETS.top); } Dimension borderSize = getBorderSize(ddec); result.setWidth(result.width() + borderSize.width()); @@ -241,16 +246,23 @@ public static Dimension getBottomRightInsets(Node container) { if (ddec instanceof DNodeContainer) { if (new DNodeContainerExperimentalQuery((DNodeContainer) ddec).isRegionContainer() || hasFullLabelBorder(ddec)) { // TODO : Not sure about that, to verify - result.setHeight(CONTAINER_INSETS.bottom); + result.setHeight(FREEFORM_CONTAINER_INSETS.bottom); } else { - result.setWidth(CONTAINER_INSETS.right); - result.setHeight(CONTAINER_INSETS.bottom); + result.setWidth(FREEFORM_CONTAINER_INSETS.right); + result.setHeight(FREEFORM_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)); + } else if (ddec instanceof DNodeList) { + result.setWidth(LIST_CONTAINER_INSETS.right); + result.setHeight(LIST_CONTAINER_INSETS.bottom); + // TODO: to verify + Dimension borderSize = getBorderSize(ddec); + result.setWidth(result.width() + borderSize.width()); + result.setHeight(result.height() + borderSize.height()); } - 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; @@ -276,8 +288,8 @@ public static Dimension getContainerTopLeftInsetsAfterLabel(Node node, boolean s if (nodeQuery.isContainer()) { EObject element = parentNode.getElement(); if (element instanceof DDiagramElementContainer) { - result.setWidth(CONTAINER_INSETS.left); - result.setHeight(CONTAINER_INSETS.top); + result.setWidth(FREEFORM_CONTAINER_INSETS.left); + result.setHeight(FREEFORM_CONTAINER_INSETS.top); Dimension borderSize = getBorderSize((DDiagramElementContainer) element); result.setWidth(result.width() + borderSize.width()); @@ -408,6 +420,15 @@ public static Point getLocation(Node node) { } } } + } else if (new ViewQuery(node).isListCompartment()) { + // Translate from the title (previous children) + Point titleBottomRightCorner = getBottomRight((Node) node.eContainer(), node, false); + location.translate(0, titleBottomRightCorner.preciseY()); + // Add the corresponding margin of {1, 4, 0, 4} of + // org.eclipse.sirius.diagram.ui.internal.edit.parts.AbstractDNodeListCompartmentEditPart.createFigure() + location.translate(4, 1); + // Translate from the spacing (5 pixels) + location.translate(0, 5); } return location; } @@ -481,6 +502,11 @@ public static Rectangle getAbsoluteBounds(Node node, boolean insetsAware, boolea if (insetsAware) { translateWithInsets(absoluteNodeBounds, node); } + if (new ViewQuery(currentNode).isListCompartment()) { + // Add upper brothers "margin" + Point topLeftCornerOfNode = getBottomRight(currentNode, node, false); + absoluteNodeBounds = absoluteNodeBounds.getTranslated(0, topLeftCornerOfNode.preciseY()); + } } return absoluteNodeBounds; } @@ -648,7 +674,7 @@ public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstra bounds.setHeight(-1); } - if (new ViewQuery(node).isForNameEditPart()) { + if (new ViewQuery(node).isForNameEditPart() || new ViewQuery(node).isListItem()) { if (abstractDNode.getName() == null || abstractDNode.getName().length() == 0) { if (bounds.width == -1) { bounds.setWidth(0); @@ -734,7 +760,7 @@ private static void replaceAutoSize(Node node, Rectangle bounds, boolean useFigu // if there is no default size, we compute it from the given // node. EObject element = node.getElement(); - if (new ViewQuery(node).isFreeFormCompartment()) { + if (new ViewQuery(node).isFreeFormCompartment() || new ViewQuery(node).isListCompartment()) { defaultSize = new Dimension(ResizableCompartmentFigure.MIN_CLIENT_DP, ResizableCompartmentFigure.MIN_CLIENT_DP); } else if (element instanceof AbstractDNode) { defaultSize = getDefaultSize((AbstractDNode) element); @@ -847,28 +873,73 @@ private static void lookForNextRegionLocation(Rectangle bounds, Node node) { * Returns a new Point representing the bottom right point of all bounds of children of this Node. Useful for Node * with size of -1x-1 to be more accurate (but it is still not necessarily the same size that draw2d). * - * @param node + * @param container + * 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 container, boolean considerBorderNodes) { + return getBottomRight(container, null, considerBorderNodes); + } + + /** + * Returns a new Point representing the bottom right point of all bounds of children of this Node. Useful for Node + * with size of -1x-1 to be more accurate (but it is still not necessarily the same size that draw2d). + * + * @param container * 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, boolean considerBorderNodes) { + public static Point getBottomRight(Node container, Node childToStopTo, boolean considerBorderNodes) { int right = 0; int bottom = 0; - for (Iterator children = Iterators.filter(node.getChildren().iterator(), Node.class); children.hasNext(); /* */) { + boolean stop = false; + for (Iterator children = Iterators.filter(container.getChildren().iterator(), Node.class); children.hasNext() && !stop; /* */) { + ViewQuery containerViewQuery = new ViewQuery(container); Node child = children.next(); - // 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; + if (child.equals(childToStopTo)) { + stop = true; + if (containerViewQuery.isListCompartment()) { + if (bottom == 0) { + // The bottom right is asked for the first list item of the list, add a one margin border over + // it. + bottom = 1; + } } - if (bottomRight.y > bottom) { - bottom = bottomRight.y; + } else { + // 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); + if (containerViewQuery.isListContainer() && new ViewQuery(child).isListCompartment()) { + // Add the corresponding margin of {1, 4, 0, 4} of + // org.eclipse.sirius.diagram.ui.internal.edit.parts.AbstractDNodeListCompartmentEditPart.createFigure() + bounds.translate(8, 1); + // Translate from the title (previous children) + bounds.translate(0, bottom); + // Translate from the spacing (5 pixels) + bounds.translate(0, 5); + } else if (containerViewQuery.isListCompartment()) { + if (bottom == 0) { + // Add a one margin border over the first list item + bounds.translate(0, 1); + } + // Translate from the previous list item + bounds.translate(0, bottom); + } + // TODO: Shift bounds for list, or Vertical and Horizontal compartment. + Point bottomRight = bounds.getBottomRight(); + if (bottomRight.x > right) { + right = bottomRight.x; + } + if (bottomRight.y > bottom) { + bottom = bottomRight.y; + } } } }