diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/NodeQuery.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/NodeQuery.java
index 1713fdd63d..9333a02600 100644
--- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/NodeQuery.java
+++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/business/api/query/NodeQuery.java
@@ -30,14 +30,7 @@
import org.eclipse.sirius.diagram.business.api.query.DDiagramElementQuery;
import org.eclipse.sirius.diagram.business.api.query.DNodeQuery;
import org.eclipse.sirius.diagram.ui.edit.internal.part.PortLayoutHelper;
-import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNode2EditPart;
-import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNode4EditPart;
-import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeContainer2EditPart;
-import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeContainerEditPart;
-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.refresh.GMFHelper;
-import org.eclipse.sirius.diagram.ui.part.SiriusVisualIDRegistry;
import org.eclipse.sirius.diagram.ui.tools.api.layout.LayoutUtils;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.ext.base.Options;
@@ -51,7 +44,7 @@
*
* @author lredor
*/
-public class NodeQuery {
+public class NodeQuery extends ViewQuery {
private Node node;
@@ -62,6 +55,7 @@ public class NodeQuery {
* the starting point.
*/
public NodeQuery(Node node) {
+ super(node);
this.node = node;
}
@@ -166,33 +160,12 @@ protected Dimension getDefaultDim(DDiagramElement element) {
return dim;
}
- /**
- * Tests whether the queried Node corresponds to a bordered node.
- *
- * @return true
if the queried View corresponds to a bordered node.
- */
- public boolean isBorderedNode() {
- int type = SiriusVisualIDRegistry.getVisualID(this.node.getType());
- boolean result = type == DNode2EditPart.VISUAL_ID || type == DNode4EditPart.VISUAL_ID;
- return result;
- }
-
- /**
- * Tests whether the queried Node corresponds to a container (list or not).
- *
- * @return true
if the queried View corresponds to a container node.
- */
- public boolean isContainer() {
- int type = SiriusVisualIDRegistry.getVisualID(this.node.getType());
- boolean result = type == DNodeContainer2EditPart.VISUAL_ID || type == DNodeContainerEditPart.VISUAL_ID || type == DNodeList2EditPart.VISUAL_ID || type == DNodeListEditPart.VISUAL_ID;
- return result;
- }
-
/**
* Return the compartment of the GMF node container with "free form" layout.
*
* @return the compartment or Optional.empty if view is not container or compartment not found
*/
+ @Override
public Optional getFreeFormContainerCompartment() {
if (new ViewQuery(this.node).isFreeFormContainer()) {
List children = this.node.getChildren();
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..0b53869cb7 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,31 @@ 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.
*/
@@ -416,7 +444,7 @@ public boolean isNodeLabel() {
*
* @return the compartment or Optional.empty if view is not container or compartment not found
*/
- public Optional getFreeFormContainerCompartment() {
+ public Optional extends View> getFreeFormContainerCompartment() {
if (this.isFreeFormContainer()) {
List children = this.view.getChildren();
return children.stream() //
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 9be9a8df1a..c6ba88f4f7 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
@@ -119,9 +119,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 final Insets FREEFORM_CONTAINER_INSETS = new Insets(IContainerLabelOffsets.LABEL_OFFSET, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN,
AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN, AbstractDNodeContainerCompartmentEditPart.DEFAULT_MARGIN);
+ private static final 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()).
@@ -181,8 +183,29 @@ public static Point getAbsoluteLocation(Node node, boolean insetsAware) {
}
}
}
-
- if (node.eContainer() instanceof Node container) {
+ ViewQuery viewQuery = new ViewQuery(node);
+ if (viewQuery.isListCompartment()) {
+ // Translate the compartment to be just below the the title, the x coordinate is also the same (same parent
+ // insets)
+ Rectangle titleBounds = getAbsoluteBounds(getPreviousChild(node), true);
+ location.translate(titleBounds.preciseX(), titleBounds.preciseY() + titleBounds.preciseHeight());
+ // Translate from the spacing (5 pixels)
+ location.translate(0, IContainerLabelOffsets.LABEL_OFFSET);
+ } else if (viewQuery.isListItem()) {
+ if (node.eContainer() instanceof Node container) {
+ if (container.getChildren().get(0) == node) {
+ Point parentNodeLocation = getAbsoluteLocation(container, insetsAware);
+ location.translate(parentNodeLocation);
+ if (insetsAware) {
+ translateWithInsets(location, node);
+ }
+ } else {
+ // Translate from the previous children
+ Rectangle previousChildBounds = getAbsoluteBounds(getPreviousChild(node), true);
+ location.translate(previousChildBounds.preciseX(), previousChildBounds.preciseY() + previousChildBounds.preciseHeight());
+ }
+ }
+ } else if (node.eContainer() instanceof Node container) {
Point parentNodeLocation = getAbsoluteLocation(container, insetsAware);
location.translate(parentNodeLocation);
if (insetsAware) {
@@ -192,6 +215,26 @@ public static Point getAbsoluteLocation(Node node, boolean insetsAware) {
return location;
}
+ private static Node getPreviousChild(Node node) {
+ Node previousChild = null;
+ boolean found = false;
+ if (node.eContainer() instanceof Node container) {
+ for (Iterator children = Iterators.filter(container.getChildren().iterator(), Node.class); children.hasNext() && !found; /* */) {
+ Node child = children.next();
+ if (node == child) {
+ found = true;
+ } else {
+ previousChild = child;
+ }
+ }
+ }
+ if (found) {
+ return previousChild;
+ } else {
+ return null;
+ }
+ }
+
/**
* Return the top-left insets of this container
. The insets also considers its border.
*
@@ -210,16 +253,24 @@ 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 + getLabelDimension(container, new Dimension(50, 20)).width() + AbstractDiagramElementContainerEditPart.DEFAULT_SPACING);
+ result.setHeight(FREEFORM_CONTAINER_INSETS.top + getLabelDimension(container, new Dimension(50, 20)).width() + 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());
result.setHeight(result.height() + borderSize.height());
}
+ } else if (nodeQuery.isListCompartment()) {
+ // Add the corresponding margin of {1, 4, 0, 4} of
+ // org.eclipse.sirius.diagram.ui.internal.edit.parts.AbstractDNodeListCompartmentEditPart.createFigure()
+ result.setWidth(4);
+ result.setHeight(1);
}
return result;
}
@@ -241,7 +292,7 @@ public static Dimension getContainerTopLeftInsets(Node node, boolean searchFirst
if (nodeContainer instanceof Node) {
Node parentNode = (Node) nodeContainer;
NodeQuery nodeQuery = new NodeQuery(parentNode);
- if (nodeQuery.isContainer()) {
+ if (nodeQuery.isContainer() || nodeQuery.isListCompartment()) {
result = getTopLeftInsets(parentNode);
} else if (searchFirstParentContainer) {
result = getContainerTopLeftInsets(parentNode, searchFirstParentContainer);
@@ -269,17 +320,29 @@ private 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));
}
+ } else if (nodeQuery.isListCompartment()) {
+ // Add the corresponding margin of {1, 4, 0, 4} of
+ // org.eclipse.sirius.diagram.ui.internal.edit.parts.AbstractDNodeListCompartmentEditPart.createFigure()
+ result.setWidth(4);
+ result.setHeight(0);
}
return result;
}
@@ -304,8 +367,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());
@@ -359,6 +422,12 @@ private static void translateWithInsets(Point locationToTranslate, Node currentN
// Border nodes are not concerned by those insets.
if (!nodeQuery.isBorderedNode()) {
locationToTranslate.translate(getContainerTopLeftInsets(currentNode, false));
+ if (currentNode.eContainer() instanceof Node container) {
+ if (new ViewQuery(currentNode).isListItem() && container.getChildren().get(0) == currentNode) {
+ // This is the first list item, add a one margin border over it.
+ locationToTranslate.translate(0, 1);
+ }
+ }
}
}
@@ -648,8 +717,8 @@ public static Rectangle getBounds(Node node, boolean useFigureForAutoSizeConstra
bounds.setWidth(-1);
bounds.setHeight(-1);
}
-
- if (new ViewQuery(node).isForNameEditPart()) {
+ ViewQuery viewQuery = new ViewQuery(node);
+ if (viewQuery.isForNameEditPart() || viewQuery.isListItem()) {
if (abstractDNode.getName() == null || abstractDNode.getName().length() == 0) {
if (bounds.width == -1) {
bounds.setWidth(0);
@@ -707,7 +776,7 @@ private static boolean isShadowBorderNeeded(Node node) {
boolean needShadowBorder = false;
EObject element = node.getElement();
ViewQuery viewQuery = new ViewQuery(node);
- if (!viewQuery.isFreeFormCompartment() && element instanceof DDiagramElementContainer) {
+ if (!viewQuery.isFreeFormCompartment() && !viewQuery.isListCompartment() && !viewQuery.isForNameEditPart() && element instanceof DDiagramElementContainer) {
DDiagramElementContainer ddec = (DDiagramElementContainer) element;
needShadowBorder = !(new DDiagramElementContainerExperimentalQuery(ddec).isRegion() || ddec.getOwnedStyle() instanceof WorkspaceImage);
}
@@ -736,8 +805,15 @@ private static void replaceAutoSize(Node node, PrecisionRectangle bounds, boolea
// if there is no default size, we compute it from the given
// node.
EObject element = node.getElement();
- if (new ViewQuery(node).isFreeFormCompartment()) {
+ ViewQuery nodeQuery = new ViewQuery(node);
+ if (nodeQuery.isFreeFormCompartment() || nodeQuery.isListCompartment()) {
defaultSize = new Dimension(ResizableCompartmentFigure.MIN_CLIENT_DP, ResizableCompartmentFigure.MIN_CLIENT_DP);
+ if (node.getChildren().isEmpty()) {
+ if (nodeQuery.isListCompartment()) {
+ // Add one margin border (even if empty)
+ defaultSize.expand(0, 1);
+ }
+ }
} else if (element instanceof AbstractDNode) {
defaultSize = getDefaultSize((AbstractDNode) element);
}
@@ -887,23 +963,41 @@ private static Rectangle getChildrenBounds(Node container, boolean considerBorde
if (container.getChildren().isEmpty()) {
result = new PrecisionRectangle();
}
- for (Iterator children = Iterators.filter(container.getChildren().iterator(), Node.class); children.hasNext(); /* */) {
- 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 childAbsoluteBounds = getAbsoluteBounds(child, true, false, true);
- if (result == null) {
- result = childAbsoluteBounds.getCopy();
- } else {
- // Make union of the child bounds and its parent bounds
- result.union(childAbsoluteBounds);
+ ViewQuery containerViewQuery = new ViewQuery(container);
+ if (containerViewQuery.isListContainer() || containerViewQuery.isListCompartment()) {
+ if (!container.getChildren().isEmpty()) {
+ Node lastChild = getLastChild(container, considerBorderNodes);
+ result = getAbsoluteBounds(lastChild, true, false, true);
+ }
+ } else {
+ for (Iterator children = Iterators.filter(container.getChildren().iterator(), Node.class); children.hasNext(); /* */) {
+ 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 childAbsoluteBounds = getAbsoluteBounds(child, true, false, true);
+ if (result == null) {
+ result = childAbsoluteBounds.getCopy();
+ } else {
+ // Make union of the child bounds and its parent bounds
+ result.union(childAbsoluteBounds);
+ }
}
}
}
return result;
}
+ private static Node getLastChild(Node container, boolean considerBorderNodes) {
+ for (int i = container.getChildren().size() - 1; i >= 0; i--) {
+ Node currentNode = (Node) container.getChildren().get(i);
+ if (considerBorderNodes || !new NodeQuery(currentNode).isBorderedNode()) {
+ return currentNode;
+ }
+ }
+ return null;
+ }
+
private static Dimension getDefaultSize(AbstractDNode abstractDNode) {
Dimension defaultSize = new Dimension(-1, -1);
if (abstractDNode instanceof DNode) {
diff --git a/plugins/org.eclipse.sirius.ui.debug/src/org/eclipse/sirius/ui/debug/SiriusDebugView.java b/plugins/org.eclipse.sirius.ui.debug/src/org/eclipse/sirius/ui/debug/SiriusDebugView.java
index 1f6357d38e..1a12fe7875 100644
--- a/plugins/org.eclipse.sirius.ui.debug/src/org/eclipse/sirius/ui/debug/SiriusDebugView.java
+++ b/plugins/org.eclipse.sirius.ui.debug/src/org/eclipse/sirius/ui/debug/SiriusDebugView.java
@@ -122,6 +122,7 @@
import org.eclipse.sirius.diagram.ui.business.internal.query.EdgeTargetQuery;
import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramContainerEditPart;
import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramElementContainerEditPart;
+import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramListEditPart;
import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramNameEditPart;
import org.eclipse.sirius.diagram.ui.edit.api.part.IAbstractDiagramNodeEditPart;
import org.eclipse.sirius.diagram.ui.edit.api.part.IDiagramEdgeEditPart;
@@ -255,7 +256,12 @@ private String getTextFor(IDiagramElementEditPart part) {
appendSequenceEventInfo(part, sb);
appendBoundsDetails(part, sb);
- if (part instanceof AbstractDiagramContainerEditPart && ((AbstractDiagramContainerEditPart) part).isRegionContainer()) {
+ if (part instanceof AbstractDiagramListEditPart) {
+ for (IGraphicalEditPart child : Iterables.filter(part.getChildren(), IGraphicalEditPart.class)) {
+ sb.append("Children bounds (" + child.getClass().getSimpleName() + "):\n");
+ appendBoundsDetails(child, sb);
+ }
+ } else if (part instanceof AbstractDiagramContainerEditPart && ((AbstractDiagramContainerEditPart) part).isRegionContainer()) {
IGraphicalEditPart compartment = null;
for (IGraphicalEditPart child : Iterables.filter(part.getChildren(), IGraphicalEditPart.class)) {
sb.append("Children bounds:\n");