package org.eclipse.papyrus.uml.diagram.statemachine.custom.commands; import java.util.Iterator; 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.Node; import org.eclipse.gmf.runtime.notation.NotationFactory; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.uml.diagram.statemachine.custom.helpers.Zone; public class CustomStateResizeCommand extends AbstractTransactionalCommand { CreateViewRequest.ViewDescriptor viewDescriptor; IAdaptable adaptable; PreferencesHint prefHints; /** * The request to perform. */ private ChangeBoundsRequest request = null; /** * The bounds rectangle. */ private Rectangle bounds = null; private boolean internalResize = false; public CustomStateResizeCommand(IAdaptable adaptable, PreferencesHint prefHints, TransactionalEditingDomain domain, String label, ChangeBoundsRequest request, Rectangle bounds, boolean internalResize) { super(domain, label, null); this.adaptable = adaptable; this.prefHints = prefHints; this.request = request; this.bounds = bounds; this.internalResize = internalResize; 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 state = (View)adaptable.getAdapter(View.class); View stateLabel = (View)state.getChildren().get(0); View stateCompartment = (View)state.getChildren().get(1); // a bunch of initializations int direction = request.getResizeDirection(); int dx = request.getSizeDelta().width; int dy = request.getSizeDelta().height; Iterator<Node> it = state.getChildren().iterator(); while(it.hasNext()) { Node currentNode = it.next(); if(currentNode.getLayoutConstraint() == null) { currentNode.setLayoutConstraint(NotationFactory.eINSTANCE.createBounds()); } } if(internalResize) { Zone.setHeight(stateLabel, Zone.getHeight(stateLabel) + dy); // dy = 0; } // first resize the state node with the constraint provided Zone.setBounds(state, bounds); // resize label and compartment Zone.setWidth(stateLabel, bounds.width); Zone.setWidth(stateCompartment, bounds.width); Zone.setHeight(stateCompartment, bounds.height - Zone.getHeight(stateLabel)); Zone.setY(stateCompartment, Zone.getHeight(stateLabel)); if(internalResize && (dx == 0)) return CommandResult.newOKCommandResult(); // one region displayed case if(stateCompartment.getChildren().size() == 1) { // we need to resize the region View defaultRegion = (View)stateCompartment.getChildren().get(0); Zone.setWidth(defaultRegion, Zone.getWidth(stateCompartment)); Zone.setHeight(defaultRegion, Zone.getHeight(stateCompartment)); return CommandResult.newOKCommandResult(); } // multiple region case // test the direction of resize // the processing depends on the direction // basically embedded nodes to be either scaled and/or translated along // one or two axis // depending on their relative positions to the borders of the state // machine it = stateCompartment.getChildren().iterator(); while(it.hasNext()) { View view = (View)it.next(); String zone = Zone.getZone(view); switch(direction) { case PositionConstants.WEST: // we test whether the current node is close to the outer LEFT // border // this is the case if it has no LEFT neighbors at all if(!Zone.hasLeftNeighbours(zone)) { // these nodes need to be scaled // we add dx to their width int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); } else { // in other cases the node needs to be translated // for each of these we translate their x of dx int x = Zone.getX(view); x += dx; Zone.setX(view, x); } break; case PositionConstants.EAST: // we test whether the current node is close to the outer RIGHT // border // this is the case if it has no RIGHT neighbours at all if(!Zone.hasRightNeighbours(zone)) { // these nodes need to be scaled // we add dx to their width int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); } break; case PositionConstants.NORTH: // we test whether the current node is close to the outer TOP // border // this is the case if it has no TOP neighbours at all if(!Zone.hasTopNeighbours(zone)) { // these nodes need to be scaled // we add dy to their height int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } else { // in other cases the node needs to be translated // for each of these we translate their y of dy int y = Zone.getY(view); y += dy; Zone.setY(view, y); } break; case PositionConstants.SOUTH: // we test whether the current node is close to the outer BOTTOM // border // this is the case if it has no BOTTOM neighbours at all if(!Zone.hasBottomNeighbours(zone)) { // these nodes need to be scaled // we add dy to their height int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } break; case PositionConstants.NORTH_WEST: // we test whether the current node is close to the outer TOP // and LEFT borders // this is the case if it has no LEFT neighbours nor TOP // neighbours at all if(!Zone.hasLeftNeighbours(zone) && !Zone.hasTopNeighbours(zone)) { // for each of these we add dx to their width and dy to // their height int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } // the second case is when it has no LEFT neighbours but TOP // ones, i.e. close to // LEFT border only else if(!Zone.hasLeftNeighbours(zone) && Zone.hasTopNeighbours(zone)) { // for each of these we add dx to their width and translate // their y of dy int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); int y = Zone.getY(view); y += dy; Zone.setY(view, y); } // in the reverse case, i.e. close to TOP border only else if(Zone.hasLeftNeighbours(zone) && !Zone.hasTopNeighbours(zone)) { // for each of these we add dy to their height and translate // their x of dx int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); int x = Zone.getX(view); x += dx; Zone.setX(view, x); } else { // in other cases the node needs to be translated both ways // for each of these we translate their x of dx and their y // of dy int x = Zone.getX(view); x += dx; Zone.setX(view, x); int y = Zone.getY(view); y += dy; Zone.setY(view, y); } break; case PositionConstants.NORTH_EAST: // we test whether the current node is close to the outer TOP // and RIGHT borders // this is the case if it has no RIGHT neighbours nor TOP // neigbours at all if(!Zone.hasRightNeighbours(zone) && !Zone.hasTopNeighbours(zone)) { // for each of these we add dx to their width and dy to // their height int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } // the second case is when it has no RIGHT neighbours but TOP // ones, i.e. close // to RIGHT border only else if(!Zone.hasRightNeighbours(zone) && Zone.hasTopNeighbours(zone)) { // for each of these we add dx to their width and translate // their y of dy int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); int y = Zone.getY(view); y += dy; Zone.setY(view, y); } // in the reverse case, i.e. close to TOP border only else if(Zone.hasRightNeighbours(zone) && !Zone.hasTopNeighbours(zone)) { // for each of these we add dy to their height int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } else { // in other cases the node needs to be translated along Y // for each of these we translate their y of dy int y = Zone.getY(view); y += dy; Zone.setY(view, y); } break; case PositionConstants.SOUTH_WEST: // we test whether the current node is close to the outer BOTTOM // and LEFT // borders // this is the case if it has no LEFT neighbours nor BOTTOM // neigbours at all if(!Zone.hasLeftNeighbours(zone) && !Zone.hasBottomNeighbours(zone)) { // for each of these we add dx to their width and dy to // their height int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } // the second case is when it has no LEFT neighbours but BOTTOM // ones, i.e. close // to LEFT border only else if(!Zone.hasLeftNeighbours(zone) && Zone.hasBottomNeighbours(zone)) { // for each of these we add dx to their width int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); } // in the reverse case, i.e. close to BOTTOM border only else if(Zone.hasLeftNeighbours(zone) && !Zone.hasBottomNeighbours(zone)) { // for each of these we add dy to their height and translate // their x of dx int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); int x = Zone.getX(view); x += dx; Zone.setX(view, x); } else { // in other cases the node needs to be translated in X // for each of these we translate their x of dx int x = Zone.getX(view); x += dx; Zone.setX(view, x); } break; case PositionConstants.SOUTH_EAST: // we test whether the current node is close to the outer BOTTOM // and RIGHT // borders // this is the case if it has no RIGHT neighbours nor BOTTOM // neigbours at all if(!Zone.hasRightNeighbours(zone) && !Zone.hasBottomNeighbours(zone)) { // for each of these we add dx to their width and dy to // their height int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } // the second case is when it has no RIGHT neighbours but BOTTOM // ones, i.e. // close to RIGHT border only else if(!Zone.hasRightNeighbours(zone) && Zone.hasBottomNeighbours(zone)) { // for each of these we add dx to their width int width = Zone.getWidth(view); width += dx; Zone.setWidth(view, width); } // in the reverse case, i.e. close to BOTTOM border only else if(Zone.hasRightNeighbours(zone) && !Zone.hasBottomNeighbours(zone)) { // for each of these we add dy to their height int height = Zone.getHeight(view); height += dy; Zone.setHeight(view, height); } break; }// switch }// while return CommandResult.newOKCommandResult(); } }