/**
* This file Copyright (c) 2005-2010 Aptana, Inc. This program is
* dual-licensed under both the Aptana Public License and the GNU General
* Public license. You may elect to use one or the other of these licenses.
*
* This program is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. Redistribution, except as permitted by whichever of
* the GPL or APL you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or modify this
* program under the terms of the GNU General Public License,
* Version 3, as published by the Free Software Foundation. You should
* have received a copy of the GNU General Public License, Version 3 along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Aptana provides a special exception to allow redistribution of this file
* with certain other free and open source software ("FOSS") code and certain additional terms
* pursuant to Section 7 of the GPL. You may view the exception and these
* terms on the web at http://www.aptana.com/legal/gpl/.
*
* 2. For the Aptana Public License (APL), this program and the
* accompanying materials are made available under the terms of the APL
* v1.0 which accompanies this distribution, and is available at
* http://www.aptana.com/legal/apl/.
*
* You may view the GPL, Aptana's exception and additional terms, and the
* APL in the file titled license.html at the root of the corresponding
* plugin containing this source file.
*
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ide.ui.io.navigator.resources;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.filesystem.IFileSystem;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.ui.navigator.CommonDropAdapter;
import org.eclipse.ui.navigator.resources.ResourceDropAdapterAssistant;
import com.aptana.ide.core.io.LocalRoot;
import com.aptana.ide.ui.io.FileSystemUtils;
import com.aptana.ide.ui.io.IOUIPlugin;
import com.aptana.ide.ui.io.actions.CopyFilesOperation;
import com.aptana.ide.ui.io.actions.MoveFilesOperation;
import com.aptana.ide.ui.io.internal.Utils;
/**
* @author Michael Xia (mxia@aptana.com)
*/
public class FileDropAdapterAssistant extends ResourceDropAdapterAssistant {
@Override
public IStatus handleDrop(CommonDropAdapter aDropAdapter, DropTargetEvent aDropTargetEvent,
Object aTarget) {
if (aDropAdapter.getCurrentTarget() == null || aDropTargetEvent.data == null) {
return Status.CANCEL_STATUS;
}
IStatus status = null;
IAdaptable[] sources = null;
TransferData currentTransfer = aDropAdapter.getCurrentTransfer();
if (LocalSelectionTransfer.getTransfer().isSupportedType(currentTransfer)) {
sources = getSelectedSourceFiles();
aDropTargetEvent.detail = DND.DROP_NONE;
}
if (FileTransfer.getInstance().isSupportedType(currentTransfer)) {
status = performDrop(aDropAdapter, (String[]) aDropTargetEvent.data);
} else if (sources != null && sources.length > 0) {
if (aDropAdapter.getCurrentOperation() == DND.DROP_COPY
|| !isFromSameFilesystem(aDropAdapter.getCurrentTarget(), sources)) {
status = performCopy(aDropAdapter, sources);
} else {
status = performMove(aDropAdapter, sources);
}
}
openError(status);
return status;
}
@Override
public IStatus validateDrop(Object target, int operation, TransferData transferType) {
IStatus status = super.validateDrop(target, operation, transferType);
if (status == Status.OK_STATUS) {
return status;
}
if (!(target instanceof IAdaptable)) {
return createStatus(Messages.FileDropAdapterAssistant_ERR_NotAdaptable);
}
IAdaptable destination = (IAdaptable) target;
IFileStore fileStore = Utils.getFileStore(destination);
if (fileStore == null) {
return createStatus(Messages.FileDropAdapterAssistant_ERR_NotIFileStore);
}
if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) {
IAdaptable[] files = getSelectedSourceFiles();
if (files.length == 0) {
return createStatus(Messages.FileDropAdapterAssistant_ERR_InvalidDropSelection);
}
for (Object file : files) {
if (file instanceof LocalRoot) {
return createStatus(Messages.FileDropAdapterAssistant_ERR_DropLocalRoot);
}
}
String message = CopyFilesOperation.validateDestination(destination, files);
if (message != null) {
return createStatus(message);
}
} else if (FileTransfer.getInstance().isSupportedType(transferType)) {
String[] sourceNames = (String[]) FileTransfer.getInstance().nativeToJava(transferType);
if (sourceNames == null) {
sourceNames = new String[0];
}
String message = CopyFilesOperation.validateDestination(destination, sourceNames);
if (message != null) {
return createStatus(message);
}
}
return Status.OK_STATUS;
}
private IStatus performCopy(final CommonDropAdapter dropAdapter, IAdaptable[] sources) {
MultiStatus problems = new MultiStatus(IOUIPlugin.PLUGIN_ID, 1,
Messages.FileDropAdapterAssistant_ERR_Copying, null);
IStatus validate = validateDrop(dropAdapter.getCurrentTarget(), dropAdapter
.getCurrentOperation(), dropAdapter.getCurrentTransfer());
if (!validate.isOK()) {
problems.merge(validate);
}
final IFileStore destination = getFolderStore((IAdaptable) dropAdapter.getCurrentTarget());
CopyFilesOperation operation = new CopyFilesOperation(getShell());
operation.copyFiles(sources, destination, new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
refresh(dropAdapter.getCurrentTarget());
}
});
return problems;
}
private IStatus performDrop(final CommonDropAdapter dropAdapter, String[] data) {
MultiStatus problems = new MultiStatus(IOUIPlugin.PLUGIN_ID, 0,
Messages.FileDropAdapterAssistant_ERR_Importing, null);
IStatus validate = validateDrop(dropAdapter.getCurrentTarget(), dropAdapter
.getCurrentOperation(), dropAdapter.getCurrentTransfer());
if (!validate.isOK()) {
problems.merge(validate);
}
final IFileStore destination = getFolderStore((IAdaptable) dropAdapter.getCurrentTarget());
CopyFilesOperation operation = new CopyFilesOperation(getShell());
operation.copyFiles(data, destination, new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
refresh(dropAdapter.getCurrentTarget());
}
});
return problems;
}
private IStatus performMove(final CommonDropAdapter dropAdapter, IAdaptable[] sources) {
MultiStatus problems = new MultiStatus(IOUIPlugin.PLUGIN_ID, 1,
Messages.FileDropAdapterAssistant_ERR_Moving, null);
IStatus validate = validateDrop(dropAdapter.getCurrentTarget(), dropAdapter
.getCurrentOperation(), dropAdapter.getCurrentTransfer());
if (!validate.isOK()) {
problems.merge(validate);
}
final IFileStore destination = getFolderStore((IAdaptable) dropAdapter.getCurrentTarget());
MoveFilesOperation operation = new MoveFilesOperation(getShell());
operation.copyFiles(sources, destination, new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
refresh(dropAdapter.getCurrentTarget());
}
});
return problems;
}
private void openError(IStatus status) {
if (status == null) {
return;
}
String title = Messages.FileDropAdapterAssistant_ERR_DragAndDrop_Title;
int codes = IStatus.ERROR | IStatus.WARNING;
if (status.isMultiStatus()) {
IStatus[] children = status.getChildren();
if (children.length == 1) {
ErrorDialog.openError(getShell(), status.getMessage(), null, children[0], codes);
} else {
ErrorDialog.openError(getShell(), title, null, status, codes);
}
} else {
ErrorDialog.openError(getShell(), title, null, status, codes);
}
}
private void refresh(Object element) {
if (element instanceof IResource) {
try {
((IResource) element).refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
}
} else {
IOUIPlugin.refreshNavigatorView(element);
}
}
private static IAdaptable[] getSelectedSourceFiles() {
ISelection selection = LocalSelectionTransfer.getTransfer().getSelection();
if (selection instanceof IStructuredSelection) {
return getSelectedSourceFiles((IStructuredSelection) selection);
}
return new IAdaptable[0];
}
@SuppressWarnings("unchecked")
private static IAdaptable[] getSelectedSourceFiles(IStructuredSelection selection) {
List<IAdaptable> selectedFiles = new ArrayList<IAdaptable>();
Iterator iter = selection.iterator();
Object object;
IFileStore fileStore;
while (iter.hasNext()) {
object = iter.next();
if (object instanceof IAdaptable) {
IAdaptable adaptable = (IAdaptable) object;
fileStore = Utils.getFileStore(adaptable);
if (fileStore != null) {
// valid selection
selectedFiles.add(adaptable);
}
}
}
return selectedFiles.toArray(new IAdaptable[selectedFiles.size()]);
}
private static IFileStore getFolderStore(IAdaptable destination) {
IFileStore store = Utils.getFileStore(destination);
IFileInfo info = Utils.getFileInfo(destination);
if (store != null && info != null && !info.isDirectory()) {
store = store.getParent();
}
return store;
}
/**
* @param destination
* the destination target
* @param sources
* the array of selected source files
* @return true if the sources are from the same file system as the
* destination, false otherwise
*/
private static boolean isFromSameFilesystem(Object destination, Object[] sources) {
IFileStore fileStore = Utils.getFileStore(destination);
if (fileStore == null) {
return false;
}
IFileSystem filesystem = fileStore.getFileSystem();
IFileStore sourceFileStore;
for (Object source : sources) {
sourceFileStore = Utils.getFileStore(source);
if (sourceFileStore == null) {
return false;
}
if (sourceFileStore.getFileSystem() != filesystem) {
return false;
}
}
return true;
}
private static Status createStatus(String message) {
return new Status(IStatus.INFO, IOUIPlugin.PLUGIN_ID, 0, message, null);
}
}