| /** |
| * |
| * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| */ |
| package org.eclipse.osbp.vaadin.emf.actions; |
| |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.command.Command; |
| import org.eclipse.emf.common.command.CompoundCommand; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.edit.command.AddCommand; |
| import org.eclipse.emf.edit.command.MoveCommand; |
| import org.eclipse.emf.edit.command.RemoveCommand; |
| import org.eclipse.emf.edit.command.SetCommand; |
| import org.eclipse.osbp.vaadin.emf.api.IModelingContext; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.vaadin.event.DataBoundTransferable; |
| import com.vaadin.event.dd.DragAndDropEvent; |
| import com.vaadin.event.dd.DropHandler; |
| import com.vaadin.event.dd.acceptcriteria.AcceptAll; |
| import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; |
| import com.vaadin.shared.ui.dd.VerticalDropLocation; |
| import com.vaadin.ui.Tree; |
| import com.vaadin.ui.Tree.TreeTargetDetails; |
| |
| @SuppressWarnings("serial") |
| public class EmfTreeDndHandler implements DropHandler { |
| |
| private static final Logger LOGGER = LoggerFactory |
| .getLogger(EmfTreeDndHandler.class); |
| |
| private final IModelingContext modelingContext; |
| private final Tree tree; |
| |
| public EmfTreeDndHandler(IModelingContext modelingContext, Tree tree) { |
| super(); |
| this.modelingContext = modelingContext; |
| this.tree = tree; |
| } |
| |
| @Override |
| public AcceptCriterion getAcceptCriterion() { |
| return AcceptAll.get(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void drop(DragAndDropEvent event) { |
| DataBoundTransferable t = (DataBoundTransferable) event |
| .getTransferable(); |
| |
| // Make sure the drag source is the same tree |
| if (t.getSourceComponent() != tree) |
| return; |
| |
| TreeTargetDetails target = (TreeTargetDetails) event.getTargetDetails(); |
| |
| // Get ids of the dragged item and the target item |
| EObject sourceItemId = (EObject) t.getData("itemId"); |
| EObject targetItemId = (EObject) target.getItemIdOver(); |
| if (sourceItemId == null || targetItemId == null) { |
| return; |
| } |
| |
| // On which side of the target the item was dropped |
| VerticalDropLocation location = target.getDropLocation(); |
| |
| EStructuralFeature feature = sourceItemId.eContainingFeature(); |
| boolean isMany = feature.isMany(); |
| EObject targetParent = null; |
| EObject sourceParent = sourceItemId.eContainer(); |
| |
| int targetIndex = -1; |
| // Drop right on an item -> make it a child |
| if (location == VerticalDropLocation.MIDDLE) { |
| if (targetItemId.eContainer() == sourceItemId.eContainer()) { |
| targetParent = targetItemId.eContainer(); |
| if (isMany) { |
| List<EObject> collection = (List<EObject>) targetParent |
| .eGet(feature); |
| targetIndex = collection.indexOf(targetItemId) + 1; |
| } |
| } else { |
| targetParent = targetItemId; |
| targetIndex = -1; |
| } |
| } else if (location == VerticalDropLocation.TOP |
| || location == VerticalDropLocation.BOTTOM) { |
| if(targetItemId.eClass().getEAllStructuralFeatures().contains(feature)) { |
| // we drop it in the targetItemId |
| targetParent = targetItemId; |
| if (isMany && targetParent.eGet(feature) instanceof List) { |
| if (location == VerticalDropLocation.TOP) { |
| // targetIndex = index > 0 ? index - 1 : -1; |
| } else if (location == VerticalDropLocation.BOTTOM) { |
| targetIndex = -1; |
| } |
| } |
| }else{ |
| targetParent = targetItemId.eContainer(); |
| |
| if (isMany && targetParent.eGet(feature) instanceof List) { |
| List<EObject> collection = (List<EObject>) targetParent |
| .eGet(feature); |
| int index = collection.indexOf(targetItemId); |
| if (location == VerticalDropLocation.TOP) { |
| targetIndex = index > 0 ? index - 1 : -1; |
| } else if (location == VerticalDropLocation.BOTTOM) { |
| targetIndex = index; |
| } |
| } |
| } |
| } |
| |
| if (!targetParent.eClass().getEAllStructuralFeatures() |
| .contains(feature)) { |
| LOGGER.error("Feature " + feature.getName() |
| + " is not contained in droptarget " |
| + targetParent.eClass().getName()); |
| return; |
| } |
| |
| boolean isMove = targetParent == sourceParent; |
| if (isMany) { |
| if (isMove) { |
| // move if same parent |
| Command command = MoveCommand.create( |
| modelingContext.getEditingDomain(), targetParent, |
| feature, sourceItemId, targetIndex); |
| if (command.canExecute()) { |
| modelingContext.getCommandStack().execute(command); |
| } |
| } else { |
| // remove and add if new parent |
| Command remove = RemoveCommand.create( |
| modelingContext.getEditingDomain(), |
| Collections.singletonList(sourceItemId)); |
| Command add = AddCommand.create( |
| modelingContext.getEditingDomain(), targetParent, |
| feature, sourceItemId, targetIndex); |
| CompoundCommand command = new CompoundCommand(); |
| command.append(remove); |
| command.append(add); |
| if (command.canExecute()) { |
| modelingContext.getCommandStack().execute(command); |
| } |
| } |
| } else { |
| Command command = SetCommand.create( |
| modelingContext.getEditingDomain(), targetParent, feature, |
| sourceItemId); |
| if (command.canExecute()) { |
| modelingContext.getCommandStack().execute(command); |
| } |
| } |
| } |
| } |