| /*******************************************************************************
|
| * Copyright (c) 2010, 2019 Mia-Software and others.
|
| * All rights reserved. This program and the accompanying materials
|
| * are made available under the terms of the Eclipse Public License v2.0
|
| * which accompanies this distribution, and is available at
|
| * http://www.eclipse.org/legal/epl-v20.html
|
| *
|
| * Contributors:
|
| * Nicolas Bros (Mia-Software) - initial API and implementation
|
| *******************************************************************************/ |
| package org.eclipse.modisco.infra.browser.core;
|
|
|
| import java.util.ArrayList;
|
| import java.util.Collection;
|
| import java.util.Collections;
|
| import java.util.List;
|
| import java.util.ListIterator;
|
|
|
| import org.eclipse.emf.common.command.Command;
|
| import org.eclipse.emf.common.command.CompoundCommand;
|
| import org.eclipse.emf.common.command.IdentityCommand;
|
| import org.eclipse.emf.common.command.UnexecutableCommand;
|
| import org.eclipse.emf.ecore.EObject;
|
| import org.eclipse.emf.ecore.resource.Resource;
|
| import org.eclipse.emf.edit.command.AddCommand;
|
| import org.eclipse.emf.edit.command.CopyCommand;
|
| import org.eclipse.emf.edit.command.DragAndDropCommand;
|
| import org.eclipse.emf.edit.command.MoveCommand;
|
| import org.eclipse.emf.edit.command.RemoveCommand;
|
| import org.eclipse.emf.edit.domain.EditingDomain;
|
| import org.eclipse.modisco.infra.browser.uicore.internal.model.ITreeElement;
|
| import org.eclipse.modisco.infra.browser.uicore.internal.model.LinkItem;
|
| import org.eclipse.modisco.infra.browser.uicore.internal.model.ModelElementItem;
|
|
|
| /** Handles drag&drop on a {@link ModelElementItem} */
|
| public class DragAndDropOnModelElementCommand extends DragAndDropCommand {
|
|
|
| private final ModelElementItemEx modelElementItem;
|
|
|
| public DragAndDropOnModelElementCommand(final EditingDomain editingDomain,
|
| final ModelElementItemEx modelElementItem, final float location, final int operations,
|
| final int operation, final Collection<?> collection) {
|
| super(editingDomain, modelElementItem, location, operations, operation, collection);
|
| this.modelElementItem = modelElementItem;
|
| }
|
|
|
| public ModelElementItem getModelElementItem() {
|
| return this.modelElementItem;
|
| }
|
|
|
| public Command getDropCommand() {
|
| return this.dropCommand;
|
| }
|
|
|
| @Override
|
| protected Object getParent(final Object object) {
|
| if (object instanceof ITreeElement) {
|
| ITreeElement treeElement = (ITreeElement) object;
|
| return treeElement.getTreeParent();
|
| }
|
| return Collections.emptyList();
|
| }
|
|
|
| @Override
|
| protected Collection<?> getChildren(final Object object) {
|
| if (object instanceof ITreeElement) {
|
| ITreeElement treeElement = (ITreeElement) object;
|
| return treeElement.getChildren();
|
| }
|
| return Collections.emptyList();
|
| }
|
|
|
| @Override
|
| protected boolean prepareDropMoveInsert(final Object parent, final Collection<?> children,
|
| final int index) {
|
| LinkItem parentLinkItem;
|
| if (parent instanceof LinkItem) {
|
| parentLinkItem = (LinkItem) parent;
|
| } else {
|
| return false;
|
| }
|
|
|
| Collection<Object> emfChildren = new ArrayList<Object>();
|
| for (Object o : children) {
|
| if (o instanceof ModelElementItem) {
|
| ModelElementItem item = (ModelElementItem) o;
|
| emfChildren.add(item.getEObject());
|
| } else {
|
| emfChildren.add(o);
|
| }
|
| }
|
|
|
| // We don't want to move insert an object before or after
|
| // itself
|
| if (this.collection.contains(this.modelElementItem.getEObject())) {
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| } else if (emfChildren.containsAll(this.collection)) {
|
| // ↑ if the dragged objects share a parent
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
|
|
| // Create move commands for all the objects in the
|
| // collection.
|
| CompoundCommand compoundCommand = new CompoundCommand();
|
| List<Object> before = new ArrayList<Object>();
|
| List<Object> after = new ArrayList<Object>();
|
|
|
| int i = 0;
|
| for (Object object : emfChildren) {
|
| if (this.collection.contains(object)) {
|
| if (i < index) {
|
| before.add(object);
|
| } else if (i > index) {
|
| after.add(object);
|
| }
|
| }
|
| i++;
|
| }
|
|
|
| for (Object object : before) {
|
| compoundCommand.append(MoveCommand.create(this.domain, parentLinkItem.getParent(),
|
| parentLinkItem.getReference(), object, index - 1));
|
| }
|
|
|
| for (ListIterator<Object> objects = after.listIterator(after.size()); objects
|
| .hasPrevious();) {
|
| Object object = objects.previous();
|
| compoundCommand.append(MoveCommand.create(this.domain, parentLinkItem.getParent(),
|
| parentLinkItem.getReference(), object, index));
|
| }
|
|
|
| if (compoundCommand.getCommandList().isEmpty()) {
|
| this.dropCommand = IdentityCommand.INSTANCE;
|
| } else {
|
| this.dropCommand = compoundCommand;
|
| }
|
| } else {
|
| if (isCrossDomain()) {
|
| EObject eObject = this.modelElementItem.getEObject();
|
| Resource resource = eObject.eResource();
|
| if (resource != null && resource.getResourceSet() != null) {
|
| this.collection = DragAndDropUtils.translateCrossDomainObjects(this.collection,
|
| resource.getResourceSet());
|
| }
|
| }
|
| // Just remove the objects and add them.
|
| this.dropCommand = AddCommand.create(this.domain, parentLinkItem.getParent(),
|
| parentLinkItem.getReference(), this.collection, index);
|
| if (analyzeForNonContainment(this.dropCommand)) {
|
| // this.dropCommand.dispose();
|
| // this.dropCommand = UnexecutableCommand.INSTANCE;
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| } else {
|
| this.dragCommand = RemoveCommand.create(this.domain, this.collection);
|
| }
|
| }
|
|
|
| boolean result = this.dragCommand.canExecute() && this.dropCommand.canExecute();
|
| return result;
|
| }
|
|
|
| @Override
|
| protected boolean prepareDropCopyInsert(final Object parent, final Collection<?> children,
|
| final int index) {
|
| LinkItem parentLinkItem;
|
| if (parent instanceof LinkItem) {
|
| parentLinkItem = (LinkItem) parent;
|
| } else {
|
| return false;
|
| }
|
|
|
| boolean result;
|
| // We don't want to copy insert an object before or after
|
| // itself
|
| if (this.collection.contains(this.modelElementItem.getEObject())) {
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| result = false;
|
| } else {
|
| // Copy the collection
|
| this.dragCommand = CopyCommand.create(this.domain, this.collection);
|
|
|
| if (this.optimize) {
|
| result = optimizedCanExecute();
|
| if (result) {
|
| this.optimizedDropCommandOwner = this.modelElementItem.getEObject();
|
| }
|
| } else {
|
| if (this.dragCommand.canExecute() && this.dragCommand.canUndo()) {
|
| this.dragCommand.execute();
|
| this.isDragCommandExecuted = true;
|
|
|
| // And add the copy.
|
| this.dropCommand = AddCommand.create(this.domain, parentLinkItem.getParent(),
|
| parentLinkItem.getReference(), this.dragCommand.getResult(), index);
|
| if (analyzeForNonContainment(this.dropCommand)) {
|
| this.dropCommand.dispose();
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
|
|
| this.dragCommand.undo();
|
| this.dragCommand.dispose();
|
| this.isDragCommandExecuted = false;
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| }
|
| result = this.dropCommand.canExecute();
|
| } else {
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| result = false;
|
| }
|
| }
|
| }
|
| return result;
|
| }
|
|
|
| @Override
|
| protected boolean prepareDropLinkInsert(final Object parent, final Collection<?> children,
|
| final int index) {
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| return false;
|
| }
|
|
|
| @Override
|
| protected boolean prepareDropMoveOn() {
|
| if (isCrossDomain()) {
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| } else {
|
| this.dropCommand = AddCommand.create(this.domain, this.modelElementItem.getEObject(),
|
| null, this.collection);
|
| if (analyzeForNonContainment(this.dropCommand)) {
|
| this.dropCommand.dispose();
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| } else {
|
| this.dragCommand = RemoveCommand.create(this.domain, this.collection);
|
| }
|
| }
|
|
|
| boolean result = this.dragCommand.canExecute() && this.dropCommand.canExecute();
|
| return result;
|
| }
|
|
|
| @Override
|
| protected boolean prepareDropCopyOn() {
|
| boolean result;
|
|
|
| this.dragCommand = CopyCommand.create(this.domain, this.collection);
|
|
|
| if (this.dragCommand.canExecute() && this.dragCommand.canUndo()) {
|
| this.dragCommand.execute();
|
| this.isDragCommandExecuted = true;
|
| this.dropCommand = AddCommand.create(this.domain, this.modelElementItem.getEObject(),
|
| null, this.dragCommand.getResult());
|
| if (analyzeForNonContainment(this.dropCommand)) {
|
| this.dropCommand.dispose();
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
|
|
| this.dragCommand.undo();
|
| this.dragCommand.dispose();
|
| this.isDragCommandExecuted = false;
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| }
|
| } else {
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| }
|
|
|
| result = this.dragCommand.canExecute() && this.dropCommand.canExecute();
|
|
|
| return result;
|
| }
|
|
|
| @Override
|
| protected boolean prepareDropLinkOn() {
|
| this.dragCommand = IdentityCommand.INSTANCE;
|
| this.dropCommand = UnexecutableCommand.INSTANCE;
|
| return false;
|
| }
|
| }
|