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.emf.transaction.TransactionalEditingDomain;
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 CustomRegionMoveCommand extends AbstractTransactionalCommand {
IAdaptable adaptableForTargetRegion;
IAdaptable adaptableForRegionToMove;
String dropLocation = Zone.RIGHT;
PreferencesHint prefHints;
CreateViewRequest.ViewDescriptor viewDescriptor;
public CustomRegionMoveCommand(IAdaptable adaptableForTargetRegion, IAdaptable adaptableForRegionToMove, PreferencesHint prefHints, TransactionalEditingDomain domain, String label, String dropLocation) {
super(domain, label, null);
this.adaptableForTargetRegion = adaptableForTargetRegion;
this.adaptableForRegionToMove = adaptableForRegionToMove;
this.prefHints = prefHints;
viewDescriptor = new ViewDescriptor(adaptableForRegionToMove, prefHints);
// make sure the return object is available even before
// executing/undoing/redoing
setResult(CommandResult.newOKCommandResult(viewDescriptor));
this.dropLocation = dropLocation;
}
/*
* Essentially performs a resize of the region to be removed so that
* neighbouring regions are updated accordingly, then resets the zone of
* neighbouring regions and finally remove the region
*/
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException {
// adapt the view of the existing region
View targetRegion = (View)adaptableForTargetRegion.getAdapter(View.class);
// adapt the view of the dropped region
View regionToMove = (View)adaptableForRegionToMove.getAdapter(View.class);
// manage the fake removal of regionToMove
View compartment = (View)regionToMove.eContainer();
if(compartment.getChildren().size() != 1) {
int regionWidth = Zone.getWidth(regionToMove);
int regionHeight = Zone.getHeight(regionToMove);
String s = Zone.getZone(regionToMove);
List<View> neighbours = null;
if(Zone.isRight(s)) {
neighbours = Zone.getRegionLeftBorderOutsideNeighbours(regionToMove);
Iterator<View> it = neighbours.iterator();
while(it.hasNext()) {
View view = it.next();
// for each of these we add regionWidth to their width
int width = Zone.getWidth(view);
width += regionWidth;
Zone.setWidth(view, width);
}
} else if(Zone.isLeft(s)) {
neighbours = Zone.getRegionRightBorderOutsideNeighbours(regionToMove);
Iterator<View> it = neighbours.iterator();
while(it.hasNext()) {
View view = it.next();
// for each of these we add regionWidth to their width and
// translate their x of
// -regionWidth
int width = Zone.getWidth(view);
width += regionWidth;
Zone.setWidth(view, width);
int x = Zone.getX(view);
x -= regionWidth;
Zone.setX(view, x);
}
} else if(Zone.isTop(s)) {
neighbours = Zone.getRegionBottomBorderOutsideNeighbours(regionToMove);
Iterator<View> it = neighbours.iterator();
while(it.hasNext()) {
View view = it.next();
// for each of these we add regionHeight to their height and
// -regionHeight to their
// y
int height = Zone.getHeight(view);
height += regionHeight;
Zone.setHeight(view, height);
int y = Zone.getY(view);
y -= regionHeight;
Zone.setY(view, y);
}
} else if(Zone.isBottom(s)) {
neighbours = Zone.getRegionTopBorderOutsideNeighbours(regionToMove);
Iterator<View> it = neighbours.iterator();
while(it.hasNext()) {
View view = it.next();
// for each of these we add regionHeight to their height
int height = Zone.getHeight(view);
height += regionHeight;
Zone.setHeight(view, height);
}
}
// set the zone accordingly
// get its counterpart
Zone.resetRegionCounterpartZone(regionToMove);
}
// now perform the move
// get targetRegion bounds (i.e. the space which needs to be divided)
int height = Zone.getHeight(targetRegion);
int width = Zone.getWidth(targetRegion);
int x = Zone.getX(targetRegion);
int y = Zone.getY(targetRegion);
// the test itself and change of bounds
if(Zone.isRight(dropLocation)) {
// the new region zone should reflect that of other branch
Zone.copyZone(targetRegion, regionToMove);
// now set new region as RIGHT
Zone.setRight(regionToMove);
// and existing region to LEFT
Zone.setLeft(targetRegion);
// shrink width of existing region
width *= 0.5;
Zone.setWidth(targetRegion, width);
// new region will have same height and width
Zone.setWidth(regionToMove, width);
Zone.setHeight(regionToMove, height);
// set new region to location (x+width,y) (existing region is not
// moved)
Zone.setX(regionToMove, x + width);
Zone.setY(regionToMove, y);
} else if(Zone.isLeft(dropLocation)) {
// the new region zone should reflect that of existing region
Zone.copyZone(targetRegion, regionToMove);
// now set new region as LEFT
Zone.setLeft(regionToMove);
// and existing region to RIGHT
Zone.setRight(targetRegion);
// shrink width of existing region
width *= 0.5;
Zone.setWidth(targetRegion, width);
// new region will have same height and width
Zone.setWidth(regionToMove, width);
Zone.setHeight(regionToMove, height);
// set existing region to location (x+width,y) and new region at
// (x,y)
Zone.setX(targetRegion, x + width);
Zone.setX(regionToMove, x);
Zone.setY(regionToMove, y);
} else if(Zone.isBottom(dropLocation)) {
// the new region zone should reflect that of existing region
Zone.copyZone(targetRegion, regionToMove);
// now set new region as BOTTOM
Zone.setBottom(regionToMove);
// and existing region to TOP
Zone.setTop(targetRegion);
// shrink height of existing region
height *= 0.5;
Zone.setHeight(targetRegion, height);
// new region will have same height and width
Zone.setWidth(regionToMove, width);
Zone.setHeight(regionToMove, height);
// set new region to location (x,y+height) (existing region is not
// moved)
Zone.setX(regionToMove, x);
Zone.setY(regionToMove, y + height);
} else if(Zone.isTop(dropLocation)) {
// the new region zone should reflect that of existing region
Zone.copyZone(targetRegion, regionToMove);
// now set new region as TOP
Zone.setTop(regionToMove);
// and existing region to BOTTOM
Zone.setBottom(targetRegion);
// shrink height of existing region
height *= 0.5;
Zone.setHeight(targetRegion, height);
// new region will have same height and width
Zone.setWidth(regionToMove, width);
Zone.setHeight(regionToMove, height);
// set existing region to location (x,y+height) and new region at
// (x,y)
Zone.setY(targetRegion, y + height);
Zone.setX(regionToMove, x);
Zone.setY(regionToMove, y);
}
viewDescriptor.setView(regionToMove);
return CommandResult.newOKCommandResult();
}
}