From cea7cf912e443b5d2752e711cf9ddbf4e8bc8a7b Mon Sep 17 00:00:00 2001 From: Laurent Redor Date: Wed, 17 Jul 2024 15:46:24 +0200 Subject: [PATCH] [426] Handle vertical stack container Before this commit, this kind of container was not correctly handled. Bug: https://github.com/eclipse-sirius/sirius-desktop/issues/426 --- .../ui/business/api/query/NodeQuery.java | 33 +--- .../ui/business/api/query/ViewQuery.java | 44 ++++- .../ui/internal/refresh/GMFHelper.java | 180 ++++++++++++------ .../sirius/ui/debug/SiriusDebugView.java | 16 +- 4 files changed, 183 insertions(+), 90 deletions(-) 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 cbf7d6bdcd..3c9d3ec99b 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 @@ -32,6 +32,7 @@ import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.JumpLinkStatus; import org.eclipse.gmf.runtime.notation.JumpLinkType; +import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.Shape; import org.eclipse.gmf.runtime.notation.Style; @@ -40,10 +41,12 @@ import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.sirius.diagram.DDiagram; import org.eclipse.sirius.diagram.DDiagramElement; +import org.eclipse.sirius.diagram.DDiagramElementContainer; import org.eclipse.sirius.diagram.LabelPosition; import org.eclipse.sirius.diagram.NodeStyle; import org.eclipse.sirius.diagram.business.api.query.ContainerMappingQuery; import org.eclipse.sirius.diagram.description.ContainerMapping; +import org.eclipse.sirius.diagram.model.business.internal.query.DDiagramElementContainerExperimentalQuery; import org.eclipse.sirius.diagram.tools.api.DiagramPlugin; import org.eclipse.sirius.diagram.tools.api.preferences.SiriusDiagramCorePreferences; import org.eclipse.sirius.diagram.ui.internal.edit.parts.DEdgeBeginNameEditPart; @@ -407,6 +410,22 @@ public boolean isListItem() { int type = SiriusVisualIDRegistry.getVisualID(this.view.getType()); return type == DNodeListElementEditPart.VISUAL_ID; } + + /** + * Return if this GMF node is a region. + */ + public boolean isRegion() { + return this.view.getElement() instanceof DDiagramElementContainer ddec // + && new DDiagramElementContainerExperimentalQuery(ddec).isRegion(); + } + + /** + * Return if this GMF node is contained in an vertical stack layout container. + */ + public boolean isVerticalRegion() { + return view.eContainer() instanceof View container && new ViewQuery(container).isVerticalRegionContainerCompartment(); + } + /** * Return if this GMF node have vertical/horizontal stack layout. */ @@ -416,6 +435,29 @@ public boolean isRegionContainer() { && new ContainerMappingQuery(mapping).isRegionContainer(); } + /** + * Return if this GMF node have vertical stack layout. + */ + public boolean isVerticalRegionContainer() { + return this.view.getElement() instanceof DDiagramElement element // + && element.getDiagramElementMapping() instanceof ContainerMapping mapping // + && new ContainerMappingQuery(mapping).isVerticalStackContainer(); + } + + /** + * Return if this GMF node is a compartment of a container having horizontal stack layout. + */ + public boolean isVerticalRegionContainerCompartment() { + if (isFreeFormCompartment()) { + if (view.eContainer() instanceof Node container) { + return new ViewQuery(container).isVerticalRegionContainer(); + } + + } + return false; + + } + /** * Return if this GMF node is associated to DNode Sirius diagram element. */ @@ -443,7 +485,7 @@ public boolean isNodeLabel() { * * @return the compartment or Optional.empty if view is not container or compartment not found */ - public Optional getFreeFormContainerCompartment() { + public Optional 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 350204b1f0..24fb82a0ca 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 @@ -30,6 +30,7 @@ import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.draw2d.geometry.Point; +import org.eclipse.draw2d.geometry.PrecisionPoint; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.common.util.EList; @@ -160,6 +161,8 @@ public static Point getAbsoluteLocation(Node node) { public static Point getAbsoluteLocation(Node node, boolean insetsAware) { Node currentNode = node; Point absoluteNodeLocation = getLocation(currentNode); + // TODO: Location of title "DNode*NameEditPart", x coordinate, can be wrong according to label alignment. This + // problem is not yet handled. if (currentNode.eContainer() instanceof Node) { currentNode = (Node) currentNode.eContainer(); Point parentNodeLocation = getAbsoluteLocation(currentNode, insetsAware); @@ -188,8 +191,15 @@ public static Dimension getTopLeftInsets(Node container) { DDiagramElementContainer ddec = (DDiagramElementContainer) element; // RegionContainer do not have containers insets if (ddec instanceof DNodeContainer) { - if (new DNodeContainerExperimentalQuery((DNodeContainer) ddec).isRegionContainer() || hasFullLabelBorder(ddec)) { - result.setHeight(FREEFORM_CONTAINER_INSETS.top + getLabelSize(container) + AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); + if (new DNodeContainerExperimentalQuery((DNodeContainer) ddec).isRegionContainer()) { + // TODO Replace by HStack INSETS + result.setHeight(LIST_CONTAINER_INSETS.top); + } else if (hasFullLabelBorder(ddec)) { + // result.setHeight(FREEFORM_CONTAINER_INSETS.top + getLabelSize(container) + + // AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); + result.setHeight(FREEFORM_CONTAINER_INSETS.top); + } else if (new DDiagramElementContainerExperimentalQuery(ddec).isRegion()) { + // No margin } else { result.setWidth(FREEFORM_CONTAINER_INSETS.left); result.setHeight(FREEFORM_CONTAINER_INSETS.top); @@ -198,16 +208,30 @@ public static Dimension getTopLeftInsets(Node container) { 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()); + if (!new DDiagramElementContainerExperimentalQuery(ddec).isRegion()) { + 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); + } else if (nodeQuery.isVerticalRegionContainerCompartment()) { + // Add the corresponding margin of {1, 0, 0, 0} of + // org.eclipse.sirius.diagram.ui.edit.internal.part.DiagramContainerEditPartOperation.refreshBorder(AbstractDiagramElementContainerEditPart, + // ViewNodeContainerFigureDesc, ContainerStyle) + result.setWidth(0); + result.setHeight(1); } return result; } /** - * Return the top-left insets of the container of this node. The insets also considers its border. + * Return the top-left insets of the container of this node. The insets also considers its border (the + * size of the border). * * @param node * The current node @@ -222,7 +246,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() || nodeQuery.isVerticalRegionContainerCompartment()) { result = getTopLeftInsets(parentNode); } else if (searchFirstParentContainer) { result = getContainerTopLeftInsets(parentNode, searchFirstParentContainer); @@ -248,17 +272,28 @@ public static Dimension getBottomRightInsets(Node container) { 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(FREEFORM_CONTAINER_INSETS.bottom); + if (new DNodeContainerExperimentalQuery((DNodeContainer) ddec).isRegionContainer()) { + 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()); + } else if (new DDiagramElementContainerExperimentalQuery(ddec).isRegion()) { + // No margin } else { - result.setWidth(FREEFORM_CONTAINER_INSETS.right); - result.setHeight(FREEFORM_CONTAINER_INSETS.bottom); + if (hasFullLabelBorder(ddec)) { + // TODO : Not sure about that, to verify + result.setHeight(FREEFORM_CONTAINER_INSETS.bottom); + } else { + 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)); } - 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); @@ -347,6 +382,15 @@ 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); + // } else if (new ViewQuery(currentNode).isVerticalRegionContainerCompartment()) { + // // This is the first list item, add a one margin border over it. + // locationToTranslate.translate(0, 1); + } + } } } @@ -355,23 +399,6 @@ private static boolean hasFullLabelBorder(DDiagramElementContainer ddec) { return labelBorderStyle.some() && LabelBorderStyleIds.LABEL_FULL_BORDER_STYLE_FOR_CONTAINER_ID.equals(labelBorderStyle.get().getId()); } - private static int getLabelSize(Node parentNode) { - int labelSize = 0; - for (Node child : Iterables.filter(parentNode.getVisibleChildren(), Node.class)) { - if (new ViewQuery(child).isForNameEditPart()) { - // TODO Compute the real label height - // It depends on the font size - // It might require to set the layout constraint of the label - // GMF node which will not be used by the - // ConstrainedToolbarLayout to locate the label but might be - // usefull to store the value in the model. - labelSize = 16; - break; - } - } - return labelSize; - } - private static boolean isFirstRegion(DDiagramElementContainer ddec) { EObject potentialRegionContainer = ddec.eContainer(); if (potentialRegionContainer instanceof DNodeContainer) { @@ -428,11 +455,36 @@ public static Point getLocation(Node node) { // 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); + location.translate(0, IContainerLabelOffsets.LABEL_OFFSET); + } else if (new ViewQuery(node).isVerticalRegionContainerCompartment()) { + // Translate from the previous children (including title) + Point titleBottomRightCorner = getBottomRight((Node) node.eContainer(), node, false); + location.translate(0, titleBottomRightCorner.preciseY()); + // Translate from the spacing (5 pixels) + location.translate(0, IContainerLabelOffsets.LABEL_OFFSET); + } else if (new ViewQuery(node).isListItem()) { + if (node.eContainer() instanceof Node container) { + if (container.getChildren().get(0) == node) { + // This is the first list item, add a one margin border over it. + // location.translate(0, 1); TODO: Here or in parent insets ? + } else { + // Translate from the previous children + Point childrenBottomRightCorner = getBottomRight(container, node, false); + location.translate(0, childrenBottomRightCorner.preciseY()); + } + } + } + if (new ViewQuery(node).isVerticalRegion()) { + if (node.eContainer() instanceof Node container) { + if (container.getChildren().get(0) == node) { + // This is the first vertical region. + // location.translate(0, 1); TODO: Here or in parent insets ? + } else { + // Replace location by the the previous children bottom corner + location = new PrecisionPoint(0, getBottomRight(container, node, false).preciseY()); + } + } } return location; } @@ -497,22 +549,9 @@ public static Rectangle getAbsoluteBounds(Node node, boolean insetsAware) { * @return the absolute bounds of the node relative to the origin (Diagram) */ public static Rectangle getAbsoluteBounds(Node node, boolean insetsAware, boolean boxForConnection) { - Node currentNode = node; - Rectangle absoluteNodeBounds = getBounds(currentNode, false, false, boxForConnection, false); - if (currentNode.eContainer() instanceof Node) { - currentNode = (Node) currentNode.eContainer(); - Point parentNodeLocation = getAbsoluteLocation(currentNode, insetsAware); - absoluteNodeBounds = absoluteNodeBounds.getTranslated(parentNodeLocation); - 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; + Rectangle bounds = getBounds(node, false, false, boxForConnection, false); + Point location = getAbsoluteLocation(node, insetsAware); + return new PrecisionRectangle(location.preciseX(), location.preciseY(), bounds.preciseWidth(), bounds.preciseHeight()); } /** @@ -908,7 +947,7 @@ public static Point getBottomRight(Node container, Node childToStopTo, boolean c Node child = children.next(); if (child.equals(childToStopTo)) { stop = true; - if (containerViewQuery.isListCompartment()) { + if (containerViewQuery.isListCompartment() || containerViewQuery.isVerticalRegionContainerCompartment()) { if (bottom == 0) { // The bottom right is asked for the first list item of the list, add a one margin border over // it. @@ -927,7 +966,38 @@ public static Point getBottomRight(Node container, Node childToStopTo, boolean c // Translate from the title (previous children) bounds.translate(0, bottom); // Translate from the spacing (5 pixels) - bounds.translate(0, 5); + bounds.translate(0, AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); + } else if (new ViewQuery(child).isVerticalRegionContainerCompartment()) { + // Add the corresponding margin of {1, 0, 0, 0} of + // org.eclipse.sirius.diagram.ui.edit.internal.part.DiagramContainerEditPartOperation.refreshBorder(AbstractDiagramElementContainerEditPart, + // ViewNodeContainerFigureDesc, ContainerStyle) + bounds.translate(0, 1); + // Translate from the title (previous children) + bounds.translate(0, bottom); + // Translate from the spacing (5 pixels) + bounds.translate(0, AbstractDiagramElementContainerEditPart.DEFAULT_SPACING); + } else if (containerViewQuery.isVerticalRegionContainerCompartment() && new ViewQuery(child).isFreeFormContainer()) { + if (bottom == 0) { + // This is the first region + // Add a one margin border over the first region + bounds.translate(0, 1); + } else { + // This is one of the following region + // Sometimes, we have not to translate from the previous children, as for region, the + // location is sometimes + // stored in the node. + boolean translateFromPreviousChildren = bounds.preciseY() == 0; + // TODO: Compute border size + int borderSize = 1; + // bounds.translate(0, Math.max(0, borderSize - 1) + IContainerLabelOffsets.LABEL_OFFSET); + bounds.translate(0, Math.max(0, borderSize - 1)); + // Sometimes, we have not to translate from the previous children, as for region, the + // location is sometimes + // stored in the node. + if (translateFromPreviousChildren) { + bounds.translate(0, bottom); + } + } } else if (containerViewQuery.isListCompartment()) { if (bottom == 0) { // Add a one margin border over the first list item 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..a5210e4eb3 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,24 +256,31 @@ private String getTextFor(IDiagramElementEditPart part) { appendSequenceEventInfo(part, sb); appendBoundsDetails(part, sb); + if (part instanceof AbstractDiagramListEditPart) { + for (IGraphicalEditPart child : Iterables.filter(part.getChildren(), IGraphicalEditPart.class)) { + sb.append("Children bounds (" + child.getClass().getSimpleName() + "):\n"); + appendBoundsDetails(child, sb); + } + } + if (part instanceof AbstractDiagramContainerEditPart && ((AbstractDiagramContainerEditPart) part).isRegionContainer()) { IGraphicalEditPart compartment = null; for (IGraphicalEditPart child : Iterables.filter(part.getChildren(), IGraphicalEditPart.class)) { - sb.append("Children bounds:\n"); + sb.append("Children bounds (" + child.getClass().getSimpleName() + "):\n"); appendBoundsDetails(child, sb); compartment = child; } for (IGraphicalEditPart child2 : Iterables.filter(compartment.getChildren(), IGraphicalEditPart.class)) { - sb.append("Region bounds:\n"); + sb.append("Region bounds (" + child2.getClass().getSimpleName() + "):\n"); appendBoundsDetails(child2, sb); } } else if (part instanceof AbstractDiagramElementContainerEditPart && ((AbstractDiagramElementContainerEditPart) part).isRegion()) { IGraphicalEditPart parent = (IGraphicalEditPart) part.getParent(); - sb.append("Compartment bounds:\n"); + sb.append("Compartment bounds (" + parent.getClass().getSimpleName() + "):\n"); appendBoundsDetails(parent, sb); parent = (IGraphicalEditPart) parent.getParent(); - sb.append("Region Container bounds:\n"); + sb.append("Region Container bounds (" + parent.getClass().getSimpleName() + "):\n"); appendBoundsDetails(parent, sb); } else if (part instanceof InstanceRoleEditPart) { LifelineEditPart lep = Iterables.filter(part.getChildren(), LifelineEditPart.class).iterator().next();