| /******************************************************************************* |
| * Copyright (c) 2008, 2015 Andrew Gvozdev. |
| * 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: |
| * Andrew Gvozdev (Quoin Inc.) - Initial implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.cdt.make.internal.ui.dnd; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.cdt.make.core.IMakeTarget; |
| import org.eclipse.cdt.make.internal.ui.MakeUIPlugin; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.jface.util.LocalSelectionTransfer; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.Transfer; |
| |
| /** |
| * {@code LocalTransferDropTargetListener} supports dropping of dragged selection to |
| * Make Target View. {@link LocalSelectionTransfer} is used as a transfer agent. |
| * |
| * @see AbstractContainerAreaDropAdapter |
| * @see org.eclipse.swt.dnd.DropTargetListener |
| */ |
| public class LocalTransferDropTargetListener extends AbstractContainerAreaDropAdapter { |
| |
| Viewer fViewer; |
| |
| /** |
| * Constructor setting a viewer such as TreeViewer. |
| * |
| * @param viewer - to provide shell for UI interaction. |
| */ |
| public LocalTransferDropTargetListener(Viewer viewer) { |
| fViewer = viewer; |
| } |
| |
| |
| /** |
| * @return the {@link Transfer} type that this listener can accept a |
| * drop operation for. |
| */ |
| @Override |
| public Transfer getTransfer() { |
| return LocalSelectionTransfer.getTransfer(); |
| } |
| |
| /** |
| * Get selection from {@link LocalSelectionTransfer}. |
| * |
| * @return selection as {@link IStructuredSelection}. |
| */ |
| private IStructuredSelection getSelection() { |
| ISelection selection = LocalSelectionTransfer.getTransfer().getSelection(); |
| if (selection instanceof IStructuredSelection) { |
| return (IStructuredSelection) selection; |
| } |
| return null; |
| } |
| |
| /** |
| * Initial drag operation. Adjusted to be the least of user initiated |
| * operation and best supported operation for a given selection. The |
| * operation will be indicated by mouse cursor. |
| * |
| * @param operation - incoming operation. |
| * @return changed operation. |
| */ |
| @Override |
| public int dragEnterOperation(int operation) { |
| int bestOperation = determineBestOperation(getSelection(), null); |
| if (bestOperation > operation) { |
| bestOperation = operation; |
| } |
| return bestOperation; |
| } |
| |
| /** |
| * Operation on dragging over target . Adjusted to be the least of user |
| * initiated operation and best supported operation for a given selection |
| * considering drop container. The operation will be indicated by mouse |
| * cursor. Note that drop on itself is not allowed here. |
| * |
| * @param operation - incoming operation. |
| * @param dropContainer - container where drop is going to be. |
| * @return changed operation. |
| */ |
| @Override |
| public int dragOverOperation(int operation, IContainer dropContainer, Object dropTarget) { |
| int bestOperation = DND.DROP_NONE; |
| IStructuredSelection selection = getSelection(); |
| if (dropContainer != null && selection != null && !selection.toList().contains(dropTarget)) { |
| bestOperation = determineBestOperation(selection, dropContainer); |
| if (bestOperation > operation) { |
| bestOperation = operation; |
| } |
| } |
| return bestOperation; |
| } |
| |
| /** |
| * Implementation of the actual drop of {@code dropObject} to {@code dropContainer}. |
| * |
| * @param dropObject - object to drop. |
| * @param dropContainer - container where to drop the object. |
| * @param operation - drop operation. |
| */ |
| @Override |
| public void dropToContainer(Object dropObject, IContainer dropContainer, int operation) { |
| if (dropObject instanceof IStructuredSelection && dropContainer != null) { |
| IMakeTarget[] makeTargets = prepareMakeTargetsFromSelection((IStructuredSelection)dropObject, dropContainer); |
| MakeTargetDndUtil.copyTargets(makeTargets, dropContainer, operation, fViewer.getControl().getShell()); |
| } |
| } |
| |
| /** |
| * Check if this item is a file or convertible to file. |
| * |
| * @param element - an item to examine. |
| * @return true if convertible to file. |
| */ |
| private static boolean isConvertibleToFile(Object element) { |
| if (element instanceof IAdaptable) { |
| IAdaptable a = (IAdaptable)element; |
| if (a.getAdapter(IFile.class)!=null) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Calculate which operations are available for dropping the selection to |
| * the target. {@code IMakeTarget} can be moved but files can only be |
| * copied. The selection should contain only {@code IMakeTarget} or items |
| * convertible to files. |
| * |
| * @param selection - data being dragged. |
| * @param dropContainer - container where drop is targeted. |
| * |
| * @return the most advanced operation available. The return must be one of |
| * {@link org.eclipse.swt.dnd.DND} operations. |
| * |
| * @see DND#DROP_NONE |
| * @see DND#DROP_COPY |
| * @see DND#DROP_MOVE |
| * @see DND#DROP_LINK |
| */ |
| private int determineBestOperation(IStructuredSelection selection, IContainer dropContainer) { |
| int bestOperation = DND.DROP_NONE; |
| if (selection != null) { |
| List<?> items = selection.toList(); |
| for (Object item : items) { |
| if (item instanceof IMakeTarget) { |
| // Looking for a target which is not being moving to itself |
| IContainer container = ((IMakeTarget)item).getContainer(); |
| // dropContainer==null means disregard the container |
| if (dropContainer==null || !dropContainer.equals(container)) { |
| if (bestOperation < DND.DROP_MOVE) { |
| bestOperation = DND.DROP_MOVE; |
| } |
| } else if (dropContainer.equals(container)) { |
| // Allow to copy/duplicate targets into the same folder |
| if (bestOperation < DND.DROP_COPY) { |
| bestOperation = DND.DROP_COPY; |
| } |
| } |
| } else if (isConvertibleToFile(item)) { |
| // Files can be copied |
| if (bestOperation < DND.DROP_COPY) { |
| bestOperation = DND.DROP_COPY; |
| } |
| } else { |
| // if any item is not drop-able selection is not drop-able |
| bestOperation = DND.DROP_NONE; |
| break; |
| } |
| } |
| } |
| return bestOperation; |
| } |
| |
| /** |
| * Provide the list of make targets made out of selected elements. This method assumes |
| * {@code IMakeTarget} or items adaptable to files in the selection. |
| * |
| * @param selection - selected items. |
| * @param dropContainer - container where make targets will belong to. |
| * @return an array of {@code IMakeTarget}s. |
| */ |
| private static IMakeTarget[] prepareMakeTargetsFromSelection(IStructuredSelection selection, IContainer dropContainer) { |
| List<?> elements = selection.toList(); |
| List<IMakeTarget> makeTargetsList= new ArrayList<IMakeTarget>(elements.size()); |
| for (Object element : elements) { |
| if (element instanceof IMakeTarget) { |
| makeTargetsList.add((IMakeTarget)element); |
| continue; |
| } else if (isConvertibleToFile(element)) { |
| IAdaptable a = (IAdaptable)element; |
| IFile file = a.getAdapter(IFile.class); |
| String fileName = file.getName(); |
| String fileLocation = file.getLocation().toString(); |
| |
| if (fileName!=null) { |
| try { |
| String buildCommand = MakeTargetDndUtil.getProjectBuildCommand(dropContainer.getProject()); |
| IMakeTarget makeTarget = MakeTargetDndUtil.createMakeTarget(fileName, fileLocation, |
| buildCommand, dropContainer); |
| makeTargetsList.add(makeTarget); |
| } catch (CoreException e) { |
| // log any problem then ignore it |
| MakeUIPlugin.log(e); |
| } |
| } |
| } |
| } |
| if (makeTargetsList.size()>0) { |
| return makeTargetsList.toArray(new IMakeTarget[makeTargetsList.size()]); |
| } |
| return null; |
| } |
| |
| } |