package org.eclipse.uml2.diagram.common.actions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
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.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand;
import org.eclipse.gmf.runtime.diagram.ui.actions.DiagramAction;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
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.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPage;
public abstract class ChangeNotationAction extends DiagramAction {
private CreateViewRequest myCreateViewRequest;
public ChangeNotationAction(IWorkbenchPage workbenchPage, String actionId) {
super(workbenchPage);
setId(actionId);
}
@Override
public void init() {
super.init();
updateText();
updateImage();
}
@Override
public void refresh() {
super.refresh();
updateText();
updateImage();
}
protected abstract String getSemanticHint(GraphicalEditPart editPart);
protected void updateImage() {
}
protected void updateText() {
}
@Override
protected final Request createTargetRequest() {
return null;
}
@Override
protected final Command getCommand() {
final GraphicalEditPart editPart = getSelectedEditPart();
if (editPart == null) {
return UnexecutableCommand.INSTANCE;
}
Command deleteCommand = getDeleteViewCommand(editPart);
if (deleteCommand == null) {
return UnexecutableCommand.INSTANCE;
}
Command createViewCommand = getCreateViewCommand(editPart);
if (createViewCommand == null) {
return UnexecutableCommand.INSTANCE;
}
CompoundCommand command = new CompoundCommand(getCommandLabel());
command.add(deleteCommand);
command.add(createViewCommand);
return command.isEmpty() ? UnexecutableCommand.INSTANCE : (Command) new ICommandProxy(new Transactional(editPart, command));
}
private static class Transactional extends AbstractTransactionalCommand {
private final Command myGefCommand;
public Transactional(IGraphicalEditPart host, Command gefCommand) {
super(host.getEditingDomain(), gefCommand.getLabel() == null ? "" : gefCommand.getLabel(), getWorkspaceFiles(host.getNotationView()));
myGefCommand = gefCommand;
}
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
myGefCommand.execute();
return CommandResult.newOKCommandResult();
}
}
protected final Command getDeleteViewCommand(GraphicalEditPart editPart) {
View view = (View) editPart.getModel();
return new ICommandProxy(new DeleteCommand(view));
}
protected final Command getCreateViewCommand(GraphicalEditPart editPart) {
myCreateViewRequest = getCreateViewRequest(editPart);
if (myCreateViewRequest == null) {
return null;
}
return editPart.getParent().getCommand(myCreateViewRequest);
}
protected final CreateViewRequest getCreateViewRequest(GraphicalEditPart editPart) {
View view = (View) editPart.getModel();
EObject element = view.getElement();
String semanticHint = getSemanticHint(editPart);
ViewDescriptor viewDescriptor = new ViewDescriptor(new EObjectAdapter(element), Node.class, semanticHint, getPreferencesHint());
CreateViewRequest createViewRequest = new CreateViewRequest(viewDescriptor);
createViewRequest.setLocation(getLocation(editPart));
return createViewRequest;
}
@Override
protected final boolean isSelectionListener() {
return true;
}
protected final GraphicalEditPart getSelectedEditPart() {
for (Object ob : getSelectedObjects()) {
if (ob instanceof GraphicalEditPart) {
return (GraphicalEditPart) ob;
}
}
return null;
}
private Point getLocation(GraphicalEditPart editPart) {
Rectangle b = editPart.getFigure().getBounds().getCopy();
editPart.getFigure().translateToAbsolute(b);
return b.getLocation();
}
@Override
protected void doRun(IProgressMonitor progressMonitor) {
super.doRun(progressMonitor);
selectAddedObject();
myCreateViewRequest = null;
}
/**
* Almost copy of standard GMF implementation from org.eclipse.gmf.runtime.diagram.ui.actions.internal.CreateViewAction etc
*/
private void selectAddedObject() {
// we use myCreateViewRequest field instead of getRequest()
if (myCreateViewRequest == null) {
return;
}
Object result = myCreateViewRequest.getNewObject();
if (!(result instanceof Collection)) {
return;
}
final List<EditPart> editparts = new ArrayList<EditPart>(1);
IDiagramGraphicalViewer viewer = getDiagramGraphicalViewer();
if (viewer == null) {
return;
}
Map<?, ?> editpartRegistry = viewer.getEditPartRegistry();
for (Object viewAdaptable : (Collection<?>) result) {
if (viewAdaptable instanceof IAdaptable) {
Object editPart = editpartRegistry.get(((IAdaptable) viewAdaptable).getAdapter(View.class));
if (editPart instanceof EditPart)
editparts.add((EditPart) editPart);
}
}
if (!editparts.isEmpty()) {
viewer.setSelection(new StructuredSelection(editparts));
// automatically put the first shape into edit-mode
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
EditPart editPart = (EditPart) editparts.get(0);
editPart.performRequest(new Request(RequestConstants.REQ_DIRECT_EDIT));
}
});
}
}
}