package org.eclipse.papyrus.uml.diagram.statemachine.custom.commands;
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.common.core.command.ICommand;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.core.services.ViewService;
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.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter;
import org.eclipse.papyrus.uml.diagram.statemachine.custom.helpers.Zone;
import org.eclipse.papyrus.uml.diagram.statemachine.providers.ElementInitializers;
import org.eclipse.papyrus.uml.diagram.statemachine.providers.UMLElementTypes;
import org.eclipse.uml2.uml.Region;
import org.eclipse.uml2.uml.State;
import org.eclipse.uml2.uml.StateMachine;
import org.eclipse.uml2.uml.UMLFactory;
public class CustomRegionCreateElementCommand extends AbstractTransactionalCommand {
IAdaptable adaptable;
IAdaptable adaptableForDropped = null;
PreferencesHint prefHints;
CreateViewRequest.ViewDescriptor viewDescriptor;
CreateElementRequest createElementRequest;
String dropLocation = Zone.RIGHT;
public CustomRegionCreateElementCommand(IAdaptable adaptable, IAdaptable adaptableForDropped, PreferencesHint prefHints, TransactionalEditingDomain domain, String label, String dropLocation) {
super(domain, label, null);
this.adaptable = adaptable;
this.adaptableForDropped = adaptableForDropped;
this.prefHints = prefHints;
viewDescriptor = new ViewDescriptor(adaptable, prefHints);
// make sure the return object is available even before
// executing/undoing/redoing
setResult(CommandResult.newOKCommandResult(viewDescriptor));
this.dropLocation = dropLocation;
}
protected void doConfigure(Region newElement, IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
IElementType elementType = createElementRequest.getElementType();
ConfigureRequest configureRequest = new ConfigureRequest(getEditingDomain(), newElement, elementType);
configureRequest.setClientContext(createElementRequest.getClientContext());
configureRequest.addParameters(createElementRequest.getParameters());
ICommand configureCommand = elementType.getEditCommand(configureRequest);
if(configureCommand != null && configureCommand.canExecute()) {
configureCommand.execute(monitor, info);
}
}
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
// adapt the view at execution time
View existingRegion = (View)adaptable.getAdapter(View.class);
// get existingRegion bounds (i.e. the space which needs to be divided)
int height = Zone.getHeight(existingRegion);
int width = Zone.getWidth(existingRegion);
int x = Zone.getX(existingRegion);
int y = Zone.getY(existingRegion);
// get the stateMachine/state via the stateMachineView/stateView
View compartment = (View)existingRegion.eContainer();
View ownerView = (View)compartment.eContainer();
if(adaptableForDropped == null) {
Region umlRegion = UMLFactory.eINSTANCE.createRegion();
createElementRequest = new CreateElementRequest(getEditingDomain(), ownerView, UMLElementTypes.Region_3000);
// create a new UML region
if(ownerView.getElement() instanceof StateMachine) {
StateMachine umlStateMachine = (StateMachine)ownerView.getElement();
umlStateMachine.getRegions().add(umlRegion);
} else if(ownerView.getElement() instanceof State) {
State umlState = (State)ownerView.getElement();
umlState.getRegions().add(umlRegion);
}
ElementInitializers.getInstance().init_Region_3000(umlRegion);
doConfigure(umlRegion, monitor, info);
adaptableForDropped = new SemanticAdapter(umlRegion, null);
}
// create a view for the new region on the stateMachineCompartment
String semanticHint = ((IHintedType)UMLElementTypes.Region_3000).getSemanticHint();
View newRegion = (View)ViewService.getInstance().createNode(adaptableForDropped, compartment, semanticHint, -1, prefHints);
// add region specific annotation
Zone.createRegionDefaultAnnotation(newRegion);
// adjust bounds and zone
// the test itself and change of bounds
if(Zone.isRight(dropLocation)) {
// the new region zone should reflect that of other branch
Zone.copyZone(existingRegion, newRegion);
// now set new region as RIGHT
Zone.setRight(newRegion);
// and existing region to LEFT
Zone.setLeft(existingRegion);
// shrink width of existing region
width *= 0.5;
Zone.setWidth(existingRegion, width);
// new region will have same height and width
Zone.setWidth(newRegion, width);
Zone.setHeight(newRegion, height);
// set new region to location (x+width,y) (existing region is not
// moved)
Zone.setX(newRegion, x + width);
Zone.setY(newRegion, y);
} else if(Zone.isLeft(dropLocation)) {
// the new region zone should reflect that of existing region
Zone.copyZone(existingRegion, newRegion);
// now set new region as LEFT
Zone.setLeft(newRegion);
// and existing region to RIGHT
Zone.setRight(existingRegion);
// shrink width of existing region
width *= 0.5;
Zone.setWidth(existingRegion, width);
// new region will have same height and width
Zone.setWidth(newRegion, width);
Zone.setHeight(newRegion, height);
// set existing region to location (x+width,y) and new region at
// (x,y)
Zone.setX(existingRegion, x + width);
Zone.setX(newRegion, x);
Zone.setY(newRegion, y);
} else if(Zone.isBottom(dropLocation)) {
// the new region zone should reflect that of existing region
Zone.copyZone(existingRegion, newRegion);
// now set new region as BOTTOM
Zone.setBottom(newRegion);
// and existing region to TOP
Zone.setTop(existingRegion);
// shrink height of existing region
height *= 0.5;
Zone.setHeight(existingRegion, height);
// new region will have same height and width
Zone.setWidth(newRegion, width);
Zone.setHeight(newRegion, height);
// set new region to location (x,y+height) (existing region is not
// moved)
Zone.setX(newRegion, x);
Zone.setY(newRegion, y + height);
} else if(Zone.isTop(dropLocation)) {
// the new region zone should reflect that of existing region
Zone.copyZone(existingRegion, newRegion);
// now set new region as TOP
Zone.setTop(newRegion);
// and existing region to BOTTOM
Zone.setBottom(existingRegion);
// shrink height of existing region
height *= 0.5;
Zone.setHeight(existingRegion, height);
// new region will have same height and width
Zone.setWidth(newRegion, width);
Zone.setHeight(newRegion, height);
// set existing region to location (x,y+height) and new region at
// (x,y)
Zone.setY(existingRegion, y + height);
Zone.setX(newRegion, x);
Zone.setY(newRegion, y);
}
viewDescriptor.setView(newRegion);
return CommandResult.newOKCommandResult(viewDescriptor);
}
}