package org.limewire.ui.swing.dnd;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
import org.apache.commons.logging.Log;
import org.limewire.core.api.library.LocalFileItem;
import org.limewire.core.api.library.LocalFileList;
import org.limewire.logging.LogFactory;
import org.limewire.ui.swing.util.DNDUtils;
import org.limewire.ui.swing.warnings.LibraryWarningController;
/**
* An abstract class for transferring {@link LocalFileItem} through a
* {@link TransferHandler}.
*/
public abstract class LocalFileListTransferHandler extends TransferHandler {
private static final Log LOG = LogFactory.getLog(LocalFileListTransferHandler.class);
private final WeakHashMap<Transferable, Map<LocalFileList, Boolean>> canImportCache = new WeakHashMap<Transferable, Map<LocalFileList, Boolean>>();
private final LibraryWarningController librarySupport;
public LocalFileListTransferHandler(LibraryWarningController librarySupport) {
this.librarySupport = librarySupport;
}
@Override
protected Transferable createTransferable(JComponent c) {
List<File> files = getSelectedFiles();
if (!files.isEmpty()) {
return new LocalFileListTransferable(getLocalFileList(), files.toArray(new File[files.size()]));
} else {
return null;
}
}
/** Returns all files that want to be transferred. */
protected abstract List<File> getSelectedFiles();
/** Returns the LocalFileList that items should be transfered to or from. */
protected abstract LocalFileList getLocalFileList();
@Override
public int getSourceActions(JComponent c) {
return COPY;
}
@Override
public boolean canImport(TransferHandler.TransferSupport info) {
Transferable t = info.getTransferable();
LocalFileList localFileList = getLocalFileList();
Map<LocalFileList, Boolean> canImportMap = canImportCache.get(t);
if (canImportMap == null) {
canImportMap = new HashMap<LocalFileList, Boolean>();
canImportCache.put(t, canImportMap);
}
Boolean canImport = canImportMap.get(localFileList);
if (canImport == null) {
canImport = canImportInternal(info);
canImportMap.put(localFileList, canImport);
}
return canImport;
}
private boolean canImportInternal(TransferHandler.TransferSupport info) {
if (getLocalFileList() == null || !DNDUtils.containsFileFlavors(info)) {
return false;
}
//don't allow dragging and dropping ot the same list.
Transferable t = info.getTransferable();
if(t.isDataFlavorSupported(LocalFileListTransferable.LOCAL_FILE_LIST_DATA_FLAVOR)) {
try {
LocalFileList localFileList = (LocalFileList) t.getTransferData(LocalFileListTransferable.LOCAL_FILE_LIST_DATA_FLAVOR);
if(localFileList == getLocalFileList()) {
return false;
}
} catch (IOException e) {
LOG.debug("Error get Trasferable contents.", e);
} catch (UnsupportedFlavorException e) {
LOG.debug("Error get Trasferable contents.", e);
}
}
List<File> files = Collections.emptyList();
if (DNDUtils.containsFileFlavors(info)) {
try {
files = Arrays.asList(DNDUtils.getFiles(t));
} catch (Throwable e) {
LOG.debug("Error get Trasferable contents.", e);
return true;
}
}
LocalFileList localFileList = getLocalFileList();
for (File file : files) {
if (localFileList.isFileAddable(file)) {
return true;
}
}
return false;
}
@Override
public boolean importData(TransferHandler.TransferSupport info) {
if (!info.isDrop()) {
return false;
}
Transferable t = info.getTransferable();
canImportCache.remove(t);
List<File> files = Collections.emptyList();
if (DNDUtils.containsFileFlavors(info)) {
try {
files = Arrays.asList(DNDUtils.getFiles(t));
} catch (Throwable failed) {
return false;
}
}
handleFiles(files);
return true;
}
private void handleFiles(final List<File> files) {
LocalFileList localFileList = getLocalFileList();
librarySupport.addFiles(localFileList, files);
}
}