package org.eclipse.papyrus.uml.diagram.sequence.util; import java.util.ArrayList; import java.util.Arrays; 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.geometry.Rectangle; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.editparts.AbstractGraphicalEditPart; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.ui.commands.PopupMenuCommand; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.menus.PopupMenu; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.EditHelperContext; import org.eclipse.gmf.runtime.emf.type.core.IClientContext; import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.AbstractEditCommandRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; import org.eclipse.gmf.runtime.notation.Bounds; import org.eclipse.gmf.runtime.notation.Shape; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.CombinedFragmentEditPart; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.InteractionInteractionCompartmentEditPart; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.InteractionOperandEditPart; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.uml2.uml.CombinedFragment; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.Interaction; import org.eclipse.uml2.uml.InteractionFragment; import org.eclipse.uml2.uml.InteractionOperand; public class CombinedFragmentDeleteHelper { public static class EditRequest extends AbstractEditCommandRequest { /** element to edit */ private Element elementToEdit; public EditRequest(TransactionalEditingDomain editingDomain, Element elementToEdit) { super(editingDomain); this.elementToEdit = elementToEdit; } public Object getEditHelperContext() { IClientContext context = getClientContext(); if(context == null) { return getElementToEdit(); } else { return new EditHelperContext(getElementToEdit(), context); } } public Element getElementToEdit() { return elementToEdit; } } public static class MoveOperandFragmentsCommand extends EditElementCommand { private InteractionFragment parent; private EList<InteractionFragment> fragmentsToMove; private InteractionOperand sourceOperand; private CombinedFragment combinedFragment; private CombinedFragmentEditPart host; public MoveOperandFragmentsCommand(CombinedFragmentEditPart host, CombinedFragment cf, InteractionOperand op, EditRequest editRequest) { super(null, editRequest.getElementToEdit(), editRequest); InteractionOperand enclosingOp = cf.getEnclosingOperand(); if(enclosingOp != null) { Element owner = enclosingOp.getOwner(); if(owner instanceof CombinedFragment) { this.parent = enclosingOp; } } else { Element owner = cf.getOwner(); if(owner instanceof Interaction) { this.parent = (InteractionFragment)owner; } } this.host = host; this.sourceOperand = op; this.combinedFragment = cf; fragmentsToMove = op.getFragments(); } public boolean canExecute() { return (sourceOperand != null && combinedFragment != null); } @Override protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { if(parent != null && !fragmentsToMove.isEmpty()) { List<CombinedFragmentEditPart> parts = collectCombinedFragmentParts(); if(parent instanceof InteractionOperand) { ((InteractionOperand)parent).getFragments().addAll(fragmentsToMove); moveToOperandPart((InteractionOperandEditPart)host.getParent(), parts); } else if(parent instanceof Interaction) { ((Interaction)parent).getFragments().addAll(fragmentsToMove); moveToInteractionPart((InteractionInteractionCompartmentEditPart)host.getParent(), parts); } } sourceOperand.getFragments().clear(); return CommandResult.newOKCommandResult(); } private void moveToOperandPart(GraphicalEditPart op, List<CombinedFragmentEditPart> keepParts) { if(!keepParts.isEmpty()) { Rectangle parentBounds = getAbsoluteBounds((AbstractGraphicalEditPart)op.getParent()); for(CombinedFragmentEditPart cef : keepParts) { View view = cef.getNotationView(); op.getNotationView().getPersistedChildren().add(view); Bounds bounds = (Bounds)((Shape)cef.getNotationView()).getLayoutConstraint(); Rectangle absolute = getAbsoluteBounds(cef); bounds.setX(absolute.x() - parentBounds.x()); bounds.setY(absolute.y() - parentBounds.y()); } } } private void moveToInteractionPart(GraphicalEditPart op, List<CombinedFragmentEditPart> keepParts) { if(!keepParts.isEmpty()) { Rectangle b = getAbsoluteBounds(op); for(CombinedFragmentEditPart cef : keepParts) { View view = cef.getNotationView(); op.getNotationView().getPersistedChildren().add(view); Bounds bounds = (Bounds)((Shape)cef.getNotationView()).getLayoutConstraint(); Rectangle absolute = getAbsoluteBounds(cef); absolute.performTranslate(-b.x, -b.y); bounds.setX(absolute.x() - 5); bounds.setY(absolute.y() - 6); } } } private List<CombinedFragmentEditPart> collectCombinedFragmentParts() { List<CombinedFragmentEditPart> parts = new ArrayList<CombinedFragmentEditPart>(); for(InteractionFragment f : fragmentsToMove) { if(f instanceof CombinedFragment) { EditPart p = findEditPartByModel(host, f); if(p instanceof CombinedFragmentEditPart) parts.add((CombinedFragmentEditPart)p); } } return parts; } } static public class SelectLabelProvider extends org.eclipse.jface.viewers.LabelProvider { public String getText(Object object) { return object.toString(); } public Image getImage(Object object) { return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ETOOL_DELETE); } } public static class SelectAndDeleteCommand extends PopupMenuCommand { private String choice; private CompositeTransactionalCommand deletaAllCommand; private CompositeTransactionalCommand keepCommand; private String[] labels; public SelectAndDeleteCommand(CompositeTransactionalCommand deletaAllCommand, CompositeTransactionalCommand keepCommand, String[] labels) { super("prompt for delete", Display.getCurrent().getActiveShell()); PopupMenu popupMenu = new PopupMenu(Arrays.asList(labels), new SelectLabelProvider()); setPopupMenu(popupMenu); this.labels = labels; this.deletaAllCommand = deletaAllCommand; this.keepCommand = keepCommand; } protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, org.eclipse.core.runtime.IAdaptable info) throws ExecutionException { CommandResult cmdResult = super.doExecuteWithResult(progressMonitor, info); if(!cmdResult.getStatus().isOK()) { return cmdResult; } this.choice = cmdResult.getReturnValue().toString(); if(choice.contains(labels[0])) { deletaAllCommand.execute(progressMonitor, info); return deletaAllCommand.getCommandResult(); } else { keepCommand.execute(progressMonitor, info); return keepCommand.getCommandResult(); } } protected CommandResult doUndoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { if(choice.contains(labels[0])) { deletaAllCommand.undo(progressMonitor, info); return deletaAllCommand.getCommandResult(); } else { keepCommand.undo(progressMonitor, info); return keepCommand.getCommandResult(); } } protected CommandResult doRedoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { if(choice.contains(labels[0])) { deletaAllCommand.redo(progressMonitor, info); return deletaAllCommand.getCommandResult(); } else { keepCommand.redo(progressMonitor, info); return keepCommand.getCommandResult(); } } } static class DeleteCombinedFragmentCommand extends AbstractTransactionalCommand { private IElementEditService provider; private DestroyElementRequest req; public DeleteCombinedFragmentCommand(TransactionalEditingDomain domain, IElementEditService provider, DestroyElementRequest req) { super(domain, null, null); this.provider = provider; this.req = req; } @Override protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { ICommand deleteCommand = provider.getEditCommand(req); try { deleteCommand.execute(monitor, info); } catch (ExecutionException e) { e.printStackTrace(); } return CommandResult.newOKCommandResult(); } } public static ICommand createDestroyElementCommand(CombinedFragment cf, TransactionalEditingDomain transactionalEditingDomain, IElementEditService provider, DestroyElementRequest req, ICommand deleteCommand, CombinedFragmentEditPart host) { CompositeTransactionalCommand deleteAll = new CompositeTransactionalCommand(transactionalEditingDomain, null); deleteAll.add(deleteCommand); CompositeTransactionalCommand deleteCfOnly = new CompositeTransactionalCommand(transactionalEditingDomain, null); { // remove children from operands and append to parent combined fragment for(InteractionOperand op : cf.getOperands()) { deleteCfOnly.add(new MoveOperandFragmentsCommand(host, cf, op, new EditRequest(transactionalEditingDomain, cf))); } deleteCfOnly.add(new DeleteCombinedFragmentCommand(transactionalEditingDomain, provider, req)); } return new SelectAndDeleteCommand(deleteAll, deleteCfOnly, new String[]{ "Delete all", "Keep contents" }); } public static ICommand createDeleteViewCommand(CombinedFragment cf, TransactionalEditingDomain transactionalEditingDomain, CombinedFragmentEditPart host) { CompositeTransactionalCommand deleteAll = new CompositeTransactionalCommand(transactionalEditingDomain, null); { // Get the elements associated with the CF List<Element> elements = SequenceUtil.getCombinedFragmentAssociatedElement(cf); // Create the delete view commands SequenceDeleteHelper.deleteView(deleteAll, elements, transactionalEditingDomain); } CompositeTransactionalCommand deleteCfOnly = new CompositeTransactionalCommand(transactionalEditingDomain, null); { // remove children from operands and append to parent combined fragment for(InteractionOperand op : cf.getOperands()) { deleteCfOnly.add(new MoveOperandFragmentsCommand(host, cf, op, new EditRequest(transactionalEditingDomain, cf))); } // delete operands from combined fragment for(Element element : cf.getOperands()) { SequenceDeleteHelper.deleteView(deleteCfOnly, element, transactionalEditingDomain); } } return new SelectAndDeleteCommand(deleteAll, deleteCfOnly, new String[]{ "Hide all", "Keep contents" }); } static Rectangle getAbsoluteBounds(AbstractGraphicalEditPart part) { Rectangle b = part.getFigure().getBounds().getCopy(); part.getFigure().translateToAbsolute(b); return b; } public static EditPart findEditPartByModel(EditPart part, EObject m) { List children = part.getChildren(); if(children != null && children.size() > 0) { for(Object o : children) { EditPart p = (EditPart)o; Object model = p.getModel(); if(model != null && model instanceof View && m.equals(((View)model).getElement())) return p; EditPart res = findEditPartByModel(p, m); if(res != null) return res; } } return null; } }