/***************************************************************************** * Copyright (c) 2010 CEA LIST. * * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.menu.actions; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.RequestConstants; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CompoundCommand; import org.eclipse.gef.commands.UnexecutableCommand; import org.eclipse.gef.editparts.AbstractConnectionEditPart; import org.eclipse.gef.requests.AlignmentRequest; import org.eclipse.gef.tools.ToolUtilities; import org.eclipse.gmf.runtime.diagram.ui.editparts.CompartmentEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.papyrus.uml.diagram.common.helper.AlignmentLinkHelper; import org.eclipse.papyrus.uml.diagram.common.layout.AlignmentTree; import org.eclipse.papyrus.uml.diagram.common.layout.EditPartTree; import org.eclipse.papyrus.uml.diagram.common.layout.LayoutUtils; /** * The Class provides actions for the objects alignment. * These actions work correctly only if the figure to align is owned by : * <ul> * <li>the diagram</li> * <li>by a {@link CompartmentEditPart}. This {@link CompartmentEditPart} is owned by a figure composed by : * <ul> * <li>a compartment for the name (name + stereotype)</li> * <li>a compartment for object, located under the name's compartment, with {@link EditPolicy#LAYOUT_ROLE }</li> * </ul> * </li> * </ul> * If the containing figure is different, a correct alignment is not guaranteed. * * With this class, we can align nodes, by selecting them, or by selecting the link between them, thanks to {@link AlignmentLinkHelper} */ public class CustomAlignAction { /** * the Tree used to sort editparts * It contains all the selected editpart AND the intermediate editparts which can exist between two selected editparts * */ private AlignmentTree rootTree; /** The alignment. */ private int alignment; /** the selected elements */ private List<IGraphicalEditPart> selectedElements; /** * * Constructor. * * @param alignment * @param selectedElements */ public CustomAlignAction(int alignment, List<IGraphicalEditPart> selectedElements) { this.alignment = alignment; this.selectedElements = selectedElements; } /** * Returns the command for this action * * @return * the command for this action */ public Command getCommand() { List<EditPart> editparts = new ArrayList<EditPart>(); for(IGraphicalEditPart current : this.selectedElements) { editparts.add(current); } if(!isMixedSelection(editparts)) {//if selection contains links and nodes, we do nothing if(isLinkSelection(editparts)) { AlignmentLinkHelper helper = new AlignmentLinkHelper(editparts, alignment); return helper.createCommand(); } if(editparts.size() >= 2) { rootTree = new AlignmentTree(editparts); createRequests(editparts); CompoundCommand command = new CompoundCommand("Alignment Command"); //$NON-NLS-1$ Enumeration eptEnum = rootTree.breadthFirstEnumeration(); while(eptEnum.hasMoreElements()) { EditPartTree ept = (EditPartTree)eptEnum.nextElement(); if(ept.getEditPart() != null) { AlignmentRequest currentReq = (AlignmentRequest)ept.getRequest(); if(currentReq != null) { Command curCommand = null; curCommand = ept.getEditPart().getCommand(currentReq); if(curCommand != null) { command.add(curCommand); } } } } return command.isEmpty() ? UnexecutableCommand.INSTANCE : (Command)command; } } return UnexecutableCommand.INSTANCE; } /** * <ul> * <li>Calculates the initial conditions to align each nodes owned by {@link #rootTree}</li> * <li>Call {@link #createConstrainedRequest(PrecisionRectangle, PrecisionRectangle, PrecisionRectangle, EditPartTree)} for each node to create * the request</li> * </ul> * * @param editparts * the editparts to align (the last editpart is the reference for the alignment) * @param request * the initial request */ protected void createRequests(List<?> editparts) { EditPart refEP = (EditPart)editparts.get(editparts.size() - 1); PrecisionRectangle boundsRef = LayoutUtils.getAbsolutePosition(refEP); int depth = this.rootTree.getDepth(); for(int i = 1; i <= depth; i++) {//we iterate by level in the rootTree List<EditPartTree> epTrees = rootTree.getChildLevel(i); for(EditPartTree ept : epTrees) {//we create the request for each children List<EditPart> nodeChild = new ArrayList<EditPart>(); //used to calculate the shift between each element! Enumeration vectorisedChildren = ((EditPartTree)ept.getPath()[1]).breadthFirstEnumeration(); while(vectorisedChildren.hasMoreElements()) { nodeChild.add(((EditPartTree)vectorisedChildren.nextElement()).getEditPart()); } if(ept.isSelected()) {//the edit part is selected if(ept.getEditPart() != refEP && (!ept.existsUnselectedChild())) { /* * calculus of the shift * * the shift is the first selected element when the reference is not a child of the editpart * the shift is the number of levels between the current editpart and the reference if this reference is a child */ int level = ept.getLevelForFirstSelectedElement(); if(ToolUtilities.isAncestorContainedIn(nodeChild, refEP)) { level = rootTree.getTree(refEP).getLevel(); int currentLevel = ept.getLevel(); level = level - currentLevel + 1; } /* collection used to test if the ept.getEditPart() contains the refEP */ List<EditPart> coll = new ArrayList<EditPart>(1); coll.add(ept.getEditPart()); /* the reference used for the alignment */ PrecisionRectangle alignRef = new PrecisionRectangle(boundsRef); PrecisionRectangle containerBounds = ((AlignmentTree)ept).getNewContainerBounds(); if(!containerBounds.equals(LayoutUtils.getAbsolutePosition(ept.getEditPart().getRoot()))) { containerBounds.setX(containerBounds.preciseX + LayoutUtils.scrollBarSize); containerBounds.setY(containerBounds.preciseY + LayoutUtils.scrollBarSize); containerBounds.setWidth(containerBounds.preciseWidth - 2 * LayoutUtils.scrollBarSize); containerBounds.setHeight(containerBounds.preciseHeight - 2 * LayoutUtils.scrollBarSize); } switch(this.alignment) { case PositionConstants.LEFT: alignRef.setX(boundsRef.preciseX - ((level - 1) * LayoutUtils.scrollBarSize)); alignRef.setWidth(boundsRef.preciseWidth + 2 * ((level - 1) * LayoutUtils.scrollBarSize)); break; case PositionConstants.CENTER://Useful? // alignRef.setX(boundsRef.preciseX - ((level - 1) * LayoutUtils.scrollBarSize)); // alignRef.setWidth(boundsRef.preciseWidth + 2 * ((level - 1) * LayoutUtils.scrollBarSize)); break; case PositionConstants.RIGHT: alignRef.setX(boundsRef.preciseX + ((-level + 1) * LayoutUtils.scrollBarSize)); alignRef.setWidth(boundsRef.preciseWidth - 2 * ((-level + 1) * LayoutUtils.scrollBarSize)); break; case PositionConstants.BOTTOM: alignRef.setY(boundsRef.preciseY + ((-level + 1) * LayoutUtils.scrollBarSize)); alignRef.setHeight(boundsRef.preciseHeight - 2 * ((-level + 1) * LayoutUtils.scrollBarSize)); break; case PositionConstants.MIDDLE://here we can have a problem with the label for the element inheriting from Package //useful? // alignRef.setY(boundsRef.preciseY - ((level - 1) * LayoutUtils.scrollBarSize)); // alignRef.setHeight(boundsRef.preciseHeight + 2 * ((level - 1) * LayoutUtils.scrollBarSize)); /* * we don't want that the scrollbar appears * with the top alignment, we need to consider the label of the container element */ /* obtain the size of the highest child */ double heightMax = 0; Enumeration children = ept.children(); while(children.hasMoreElements()) { EditPartTree currentChild = (EditPartTree)children.nextElement(); double height = LayoutUtils.getAbsolutePosition(currentChild.getEditPart()).preciseHeight(); heightMax = (height > heightMax) ? height : heightMax; } /* obtain the size of the compartment for this figure! */ List childrenEP = ept.getEditPart().getChildren(); double compartmentHeight = 0; for(int iter = 0; iter < childrenEP.size(); iter++) { if(childrenEP.get(iter) instanceof CompartmentEditPart) { CompartmentEditPart child = (CompartmentEditPart)childrenEP.get(iter); EditPolicy policy = child.getEditPolicy(EditPolicy.LAYOUT_ROLE); if(policy != null) { compartmentHeight = LayoutUtils.getAbsolutePosition(child).preciseHeight(); break; } } } double heightToRemove = getLabelHeightToRemove(ept); //test to know if the initial alignment is possible without seeing the scrollbar if(compartmentHeight < (heightMax + LayoutUtils.scrollBarSize + heightToRemove)) { alignRef.setY(alignRef.preciseY - heightToRemove); alignRef.setHeight(alignRef.preciseHeight + heightToRemove); } break; case PositionConstants.TOP: //here we can have a problem with the label for the element inheriting from Package alignRef.setY(boundsRef.preciseY - ((level - 1) * LayoutUtils.scrollBarSize)); alignRef.setHeight(boundsRef.preciseHeight + 2 * ((level - 1) * LayoutUtils.scrollBarSize)); /* * we don't want that the scrollbar appears * with the top alignment, we need to consider the label of the container element */ if(ept.children().hasMoreElements()) { double dist = getLabelHeightToRemove(ept); alignRef.setY(alignRef.preciseY() - dist); } break; default: break; } createConstrainedRequest(alignRef, containerBounds, null, (AlignmentTree)ept); } else if(ept.getEditPart() != refEP && (ept.existsUnselectedChild())) { List<EditPart> parent = new ArrayList<EditPart>(1); parent.add(ept.getEditPart()); int distance = ept.getDistanceWithTheFirstUnselectedChild(); EditPartTree unselectedTree = ept.getFirstUnselectedChild(); PrecisionRectangle boundsLimit = null; //we needn't correct unselected element location when the reference is not inside them if(ToolUtilities.isAncestorContainedIn(parent, refEP)) { boundsLimit = new PrecisionRectangle(LayoutUtils.getAbsolutePosition(unselectedTree.getEditPart())); //we increase the size of the child, to avoid scrollbar in its parent boundsLimit.setX(boundsLimit.preciseX - (distance * LayoutUtils.scrollBarSize)); boundsLimit.setY(boundsLimit.preciseY - (distance * LayoutUtils.scrollBarSize)); boundsLimit.setWidth(boundsLimit.width + (2 * distance * LayoutUtils.scrollBarSize)); boundsLimit.setHeight(boundsLimit.height + (2 * distance * LayoutUtils.scrollBarSize)); if(this.alignment == PositionConstants.TOP) { double dist = getLabelHeightToRemove(ept); boundsLimit.setY(boundsLimit.preciseY() - dist); } } PrecisionRectangle containerBounds = ((AlignmentTree)ept).getNewContainerBounds(); if(!containerBounds.equals(LayoutUtils.getAbsolutePosition(ept.getEditPart().getRoot()))) { //we reduce the container bounds used to avoid scrollbar containerBounds.setX(containerBounds.preciseX + LayoutUtils.scrollBarSize); containerBounds.setY(containerBounds.preciseY + LayoutUtils.scrollBarSize); containerBounds.setWidth(containerBounds.width - 2 * LayoutUtils.scrollBarSize); containerBounds.setHeight(containerBounds.height - 2 * LayoutUtils.scrollBarSize); } createConstrainedRequest(boundsRef, containerBounds, boundsLimit, (AlignmentTree)ept); } else if(ept.getEditPart() == refEP && ToolUtilities.isAncestorContainedIn(nodeChild, refEP)) { if(!((EditPartTree)ept.getParent()).isSelected()) { //nothing to do } else { /* * we need to create a command for the reference, only if * its direct parent is selected. * If the reference has ancestor in the selection and if this ancestor is not selected, itn's not necessary to move the * reference, because it's the ancestor which must move. */ PrecisionRectangle containerBounds = ((AlignmentTree)ept).getNewContainerBounds(); containerBounds.setX(containerBounds.preciseX + LayoutUtils.scrollBarSize); containerBounds.setY(containerBounds.preciseY + LayoutUtils.scrollBarSize); containerBounds.setWidth(containerBounds.width - 2 * LayoutUtils.scrollBarSize); containerBounds.setHeight(containerBounds.height - 2 * LayoutUtils.scrollBarSize); createConstrainedRequest(LayoutUtils.getAbsolutePosition(refEP), containerBounds, null, (AlignmentTree)ept); } } else if(ept.getEditPart() == refEP && (!ToolUtilities.isAncestorContainedIn(nodeChild, refEP))) { //nothing to do } } else {//the editpart is not selected! We need to maintain its location PrecisionRectangle containerBounds = ((AlignmentTree)ept).getNewContainerBounds(); containerBounds.setX(containerBounds.preciseX + LayoutUtils.scrollBarSize); containerBounds.setY(containerBounds.preciseY + LayoutUtils.scrollBarSize); containerBounds.setWidth(containerBounds.width - 2 * LayoutUtils.scrollBarSize); containerBounds.setHeight(containerBounds.height - 2 * LayoutUtils.scrollBarSize); createConstrainedRequest(LayoutUtils.getAbsolutePosition(ept.getEditPart()), containerBounds, null, (AlignmentTree)ept); } } } } /** * * <ul> * <li>Completes the {@link EditPartTree} with the correct new position for the object</li> * <li>Adds the created request to the {@link EditPartTree}</li> * </ul> * * @param ref * the reference used for the alignment * @param containerBounds * the size of the editpart container * @param dontCross * the shift must be done, without the figure bounds are drawn in this rectangle * @param tree * the tree for which we create the request */ protected void createConstrainedRequest(PrecisionRectangle ref, PrecisionRectangle containerBounds, PrecisionRectangle dontCross, AlignmentTree tree) { //variables used to write the request double xMinForObject = 0; double xMaxForObject = 0; double yMinForObject = 0; double yMaxForObject = 0; PrecisionRectangle editpartBounds = LayoutUtils.getAbsolutePosition(tree.getEditPart()); PrecisionRectangle newPosition = new PrecisionRectangle(editpartBounds); //1-we determine the bounds! if(dontCross == null && containerBounds.equals(LayoutUtils.getAbsolutePosition(tree.getEditPart().getRoot()))) { AlignmentRequest newRequest = new AlignmentRequest(RequestConstants.REQ_ALIGN); PrecisionRectangle newPrecisionRectangle = new PrecisionRectangle(ref); newRequest.setAlignment(this.alignment); newRequest.setAlignmentRectangle(newPrecisionRectangle); double pos = 0; switch(this.alignment) { case PositionConstants.LEFT: newPosition.setX(ref.preciseX()); break; case PositionConstants.CENTER: pos = ref.getTop().preciseX() - (editpartBounds.preciseWidth() / 2.0); newPosition.setX(pos); break; case PositionConstants.RIGHT: pos = ref.getRight().preciseX() - editpartBounds.preciseWidth(); newPosition.setX(pos); break; case PositionConstants.TOP: pos = ref.getTop().preciseY(); newPosition.setY(pos); break; case PositionConstants.MIDDLE: pos = ref.getLeft().preciseY() - (editpartBounds.preciseHeight / 2.0); newPosition.setY(pos); break; case PositionConstants.BOTTOM: pos = ref.getBottom().preciseY() - editpartBounds.preciseHeight(); newPosition.setY(pos); break; default: break; } tree.setNewPosition(newPosition); tree.setRequest(newRequest); return; } else if(dontCross == null && (!containerBounds.equals(LayoutUtils.getAbsolutePosition(tree.getEditPart().getRoot())))) { xMinForObject = containerBounds.preciseX; xMaxForObject = containerBounds.getRight().preciseX() - editpartBounds.preciseWidth(); yMinForObject = containerBounds.preciseY; yMaxForObject = containerBounds.getBottom().preciseY() - editpartBounds.preciseHeight(); } else if(dontCross != null) { xMinForObject = dontCross.getRight().preciseX() - editpartBounds.preciseWidth; xMaxForObject = dontCross.preciseX; yMinForObject = dontCross.getBottom().preciseY() - editpartBounds.preciseHeight; yMaxForObject = dontCross.preciseY; if(!containerBounds.equals(LayoutUtils.getAbsolutePosition(tree.getEditPart().getRoot()))) { //container's limits double xMinContainerLimit = containerBounds.preciseX; double xMaxContainerLimit = containerBounds.getRight().preciseX() - editpartBounds.preciseWidth(); double yMinContainerLimit = containerBounds.preciseY; double yMaxContainerLimit = containerBounds.getBottom().preciseY() - editpartBounds.preciseHeight(); xMinForObject = (xMinForObject > xMinContainerLimit) ? xMinForObject : xMinContainerLimit; xMaxForObject = (xMaxForObject > xMaxContainerLimit) ? xMaxContainerLimit : xMaxForObject; yMinForObject = (yMinForObject > yMinContainerLimit) ? yMinForObject : yMinContainerLimit; yMaxForObject = (yMaxForObject > yMaxContainerLimit) ? yMaxContainerLimit : yMaxForObject; } } /* rectangle used to do the alignment */ PrecisionRectangle myAlignRectangle = new PrecisionRectangle(editpartBounds); /* the editpart's position in its container, after the shift of the container */ PrecisionRectangle newTmpPosition = tree.getAbsolutePositionInTheNewContainerPosition(); /* the distance between the editpart in the new container position and its alignment reference */ double distance = 0; /* the point use to translate the editpart */ Point translationPoint = null; /* the new request */ AlignmentRequest newRequest = new AlignmentRequest(RequestConstants.REQ_ALIGN); newRequest.setAlignment(this.alignment); switch(alignment) { case PositionConstants.LEFT: if((ref.preciseX >= xMinForObject) && (ref.preciseX <= xMaxForObject)) { distance = ref.preciseX - newTmpPosition.preciseX; } else if(ref.preciseX < xMinForObject) { distance = xMinForObject - newTmpPosition.preciseX; } else if(ref.preciseX > xMaxForObject) { distance = xMaxForObject - newTmpPosition.preciseX; } myAlignRectangle.setX(LayoutUtils.getAbsolutePosition(tree.getEditPart()).preciseX + distance); translationPoint = new Point(distance, 0); break; case PositionConstants.CENTER:// un alignement central fait de cette façon : tous les packages aligné sur un élément extérieur ne marche pas du tout! double minCenter = xMinForObject + (editpartBounds.preciseWidth / 2.0); double maxCenter = xMaxForObject + (editpartBounds.preciseWidth / 2.0); if((ref.getTop().preciseX() >= minCenter) && (ref.getTop().preciseX() <= maxCenter)) { distance = (ref.preciseX + (ref.preciseWidth / 2.0) - (newTmpPosition.preciseX + (newTmpPosition.preciseWidth / 2.0))); } else if(ref.getTop().preciseX() < minCenter) { distance = minCenter - (newTmpPosition.preciseX + (newTmpPosition.preciseWidth / 2.0)); } else if(ref.getTop().preciseX() > maxCenter) { distance = maxCenter - (newTmpPosition.preciseX + ((newTmpPosition.preciseWidth) / 2.0)); } myAlignRectangle.setX(LayoutUtils.getAbsolutePosition(tree.getEditPart()).preciseX + distance); translationPoint = new Point(distance, 0); break; case PositionConstants.RIGHT: double minRight = xMinForObject + editpartBounds.preciseWidth; double maxRight = xMaxForObject + editpartBounds.preciseWidth; if((ref.getRight().preciseX() >= minRight) && (ref.getRight().preciseX() <= maxRight)) { distance = (ref.preciseX + ref.preciseWidth) - (newTmpPosition.preciseX + newTmpPosition.preciseWidth); } else if(ref.getRight().preciseX() < minRight) { distance = minRight - (newTmpPosition.preciseX + newTmpPosition.preciseWidth); } else if(ref.getRight().preciseX() > maxRight) { distance = maxRight - (newTmpPosition.preciseX + newTmpPosition.preciseWidth); } myAlignRectangle.setX(LayoutUtils.getAbsolutePosition(tree.getEditPart()).preciseX + distance); translationPoint = new Point(distance, 0); break; case PositionConstants.BOTTOM: double minBottom = yMinForObject + editpartBounds.preciseHeight; double maxBottom = yMaxForObject + editpartBounds.preciseHeight; if(((ref.getBottom().preciseY()) >= minBottom) && ((ref.getBottom().preciseY()) <= maxBottom)) { distance = (ref.preciseY + ref.preciseHeight) - (newTmpPosition.preciseY + newTmpPosition.preciseHeight); } else if((ref.getBottom().preciseY()) < minBottom) { distance = minBottom - (newTmpPosition.preciseY + newTmpPosition.preciseHeight); } else if((ref.getBottom().preciseY()) > maxBottom) { distance = maxBottom - (newTmpPosition.preciseY + newTmpPosition.preciseHeight); } translationPoint = new Point(0, distance); myAlignRectangle.setY(LayoutUtils.getAbsolutePosition(tree.getEditPart()).preciseY + distance); break; case PositionConstants.MIDDLE: double minMiddle = yMinForObject + (editpartBounds.preciseHeight / 2.0); double maxMiddle = yMaxForObject + (editpartBounds.preciseHeight / 2.0); if(((ref.preciseY + (ref.preciseHeight / 2.0)) >= minMiddle) && ((ref.preciseY + (ref.preciseHeight / 2.0)) <= maxMiddle)) { distance = (ref.preciseY + (ref.preciseHeight / 2.0) - (newTmpPosition.preciseY + (newTmpPosition.preciseHeight / 2.0)));; } else if((ref.preciseY + (ref.height / 2.0)) < minMiddle) { distance = minMiddle - (newTmpPosition.preciseY + (newTmpPosition.preciseHeight / 2.0)); } else if((ref.preciseY + (ref.height / 2.0)) > maxMiddle) { distance = maxMiddle - (newTmpPosition.preciseY + (newTmpPosition.preciseHeight / 2.0)); } translationPoint = new Point(0, distance); myAlignRectangle.setY(LayoutUtils.getAbsolutePosition(tree.getEditPart()).preciseY + distance); break; case PositionConstants.TOP: if((ref.preciseY >= yMinForObject) && (ref.preciseY <= yMaxForObject)) { distance = ref.preciseY - newTmpPosition.preciseY; } else if(ref.preciseY < yMinForObject) { distance = yMinForObject - newTmpPosition.preciseY; } else if(ref.preciseY > yMaxForObject) { distance = yMaxForObject - newTmpPosition.preciseY; } translationPoint = new Point(0, distance); myAlignRectangle.setY(LayoutUtils.getAbsolutePosition(tree.getEditPart()).preciseY + distance); break; default: break; } newRequest.setAlignmentRectangle(myAlignRectangle); newPosition = (PrecisionRectangle)tree.getAbsolutePositionInTheNewContainerPosition().translate(translationPoint); tree.setNewPosition(newPosition); tree.setRequest(newRequest); return; } /** * Returns the height of the label for the current editpart contained in {@code ept}, more the height of the children's label * * @param ept * The {@link EditPartTree} containing the {@link EditPart} used to calculate height * @return * The height of the label for the current editpart, more the height of the children's label * */ protected double getLabelHeightToRemove(EditPartTree ept) { double dist = 0; List children = ept.getEditPart().getChildren(); //we search the correct compartment for(int iter = 0; iter < children.size(); iter++) { if(children.get(iter) instanceof CompartmentEditPart) { CompartmentEditPart child = (CompartmentEditPart)children.get(iter); EditPolicy policy = child.getEditPolicy(EditPolicy.LAYOUT_ROLE); if(policy != null) { PrecisionRectangle cptSize = LayoutUtils.getAbsolutePosition(child); dist += cptSize.preciseY() - LayoutUtils.getAbsolutePosition(ept.getEditPart()).preciseY(); break; } } } Enumeration eptChildren = ept.children(); double max = 0; while(eptChildren.hasMoreElements()) { EditPartTree currentElement = (EditPartTree)eptChildren.nextElement(); if(currentElement.isSelected() && (!currentElement.isReference())) { double tmp = getLabelHeightToRemove(currentElement); max = (tmp > max) ? tmp : max; } } dist += max; return dist; } /** * Tests the selection (nodes and links) * * @param editparts * * @return * <ul> * <li> {@code true}</li> if the selection contains links and nodes * <li> {@code false}</li> if not * </ul> * */ protected boolean isMixedSelection(List<?> editparts) { boolean node = false; boolean link = false; for(Object editPart : editparts) { if(editPart instanceof AbstractConnectionEditPart) { link = true; } else { node = true; } } return !(((node == true) && (link == true))) ? false : true; } /** * Tests if all the selected elements are instance of {@linkplain AbstractConnectionEditPart} * * @param editparts * the editparts list to test * @return * <ul> * <li> {@code true}</li> if all the editparts represents a link * <li>{@code false}</li> if not * </ul> */ protected boolean isLinkSelection(List<?> editparts) { if(editparts.size() == 0) { return false; } for(Object object : editparts) { if(!(object instanceof AbstractConnectionEditPart)) { return false; } } return true; } }