package org.eclipse.papyrus.uml.diagram.statemachine.custom.commands; import java.util.Iterator; import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.uml.diagram.statemachine.custom.helpers.Zone; public class CustomRegionResizeCommand extends AbstractTransactionalCommand { CreateViewRequest.ViewDescriptor viewDescriptor; IAdaptable adaptable; PreferencesHint prefHints; /** * The request to perform. */ private ChangeBoundsRequest request = null; /** * The bounds rectangle. */ private Rectangle bounds = null; public CustomRegionResizeCommand(IAdaptable adaptable, PreferencesHint prefHints, TransactionalEditingDomain domain, String label, ChangeBoundsRequest request, Rectangle bounds) { super(domain, label, null); this.adaptable = adaptable; this.prefHints = prefHints; this.request = request; this.bounds = bounds; viewDescriptor = new ViewDescriptor(adaptable, prefHints); // make sure the return object is available even before // executing/undoing/redoing setResult(CommandResult.newOKCommandResult(viewDescriptor)); } @Override protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { View region = (View)adaptable.getAdapter(View.class); // a bunch of initializations int direction = request.getResizeDirection(); int dx = request.getSizeDelta().width; int dy = request.getSizeDelta().height; // depending on the direction of resize there are different // scaling/translation to be // performed // on the nodes sitting on either side of the border which is to be // moved // the various cases follow the same structure // first: retrieve a list of node on a given side of the border // second: perform various setting of bounds switch(direction) { case PositionConstants.WEST: // a resize that moves a LEFT border // retrieve the nodes on the LEFT side of LEFT border List<View> todo = Zone.getRegionLeftBorderOutsideNeighbours(region); Iterator<View> it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add (-dx) to their width int width = Zone.getWidth(view); width -= dx; Zone.setWidth(view, width); } // retrieve the nodes on the RIGHT side of LEFT border todo = Zone.getRegionLeftBorderInsideNeighbours(region); it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add dx to their width and translate // their x of (-dx) int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); int x = Zone.getX(view); x -= dx; Zone.setX(view, x); } break; case PositionConstants.EAST: // a resize that moves a RIGHT border // retrieve the nodes on the LEFT side of RIGHT border todo = Zone.getRegionRightBorderInsideNeighbours(region); it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add dx to their width int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); } // retrieve the nodes on the RIGHT side of RIGHT border todo = Zone.getRegionRightBorderOutsideNeighbours(region); it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add (-dx) to their width and translate // their x of dx int width = Zone.getWidth(view); width -= dx; Zone.setWidth(view, width); int x = Zone.getX(view); x += dx; Zone.setX(view, x); } break; case PositionConstants.NORTH: // a resize that moves a TOP border // retrieve the nodes on the BOTTOM side of TOP border todo = Zone.getRegionTopBorderInsideNeighbours(region); it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add dy to their height and (-dy) to // their y int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); int y = Zone.getY(view); y -= dy; Zone.setY(view, y); } // retrieve the nodes on the TOP side of TOP border todo = Zone.getRegionTopBorderOutsideNeighbours(region); it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add (-dy) to their height int height = Zone.getHeight(view); height -= dy; Zone.setHeight(view, height); } break; case PositionConstants.SOUTH: // a resize that moves a BOTTOM border // retrieve the nodes on the TOP side of BOTTOM border todo = Zone.getRegionBottomBorderInsideNeighbours(region); it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add dy to their height int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } // retrieve the nodes on the BOTTOM side of BOTTOM border todo = Zone.getRegionBottomBorderOutsideNeighbours(region); it = todo.iterator(); while(it.hasNext()) { View view = it.next(); // for each of these we add (-dy) to their height and dy to // their y int height = Zone.getHeight(view); height -= dy; Zone.setHeight(view, height); int y = Zone.getY(view); y += dy; Zone.setY(view, y); } break; }// switch return CommandResult.newOKCommandResult(); } public void reverseRequest() { request.getMoveDelta().negate(); } }