package com.revolsys.swing.map.listener;
import java.awt.Component;
import java.awt.Container;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.io.BufferedReader;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.revolsys.swing.map.MapPanel;
import com.revolsys.swing.map.layer.Project;
import com.revolsys.swing.parallel.Invoke;
public class FileDropTargetListener implements DropTargetListener, HierarchyListener {
private static final Logger LOG = Logger.getLogger(FileDropTargetListener.class);
private static final String ZERO_CHAR_STRING = String.valueOf((char)0);
public FileDropTargetListener(final MapPanel map) {
addDropTarget(map);
}
public void addDropTarget(final Component component) {
if (component.getParent() != null) {
new DropTarget(component, this);
}
component.addHierarchyListener(this);
if (component.getParent() != null) {
new DropTarget(component, this);
}
if (component instanceof Container) {
final Container container = (Container)component;
final Component[] components = container.getComponents();
for (final Component child : components) {
addDropTarget(child);
}
}
}
@Override
public void dragEnter(final DropTargetDragEvent event) {
if (isDragOk(event)) {
event.acceptDrag(DnDConstants.ACTION_COPY);
} else {
event.rejectDrag();
}
}
@Override
public void dragExit(final DropTargetEvent event) {
}
@Override
public void dragOver(final DropTargetDragEvent event) {
}
@Override
@SuppressWarnings("unchecked")
public void drop(final DropTargetDropEvent event) {
try {
final Transferable tr = event.getTransferable();
final List<File> files = new ArrayList<>();
if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
event.acceptDrop(DnDConstants.ACTION_COPY);
files.addAll((List<File>)tr.getTransferData(DataFlavor.javaFileListFlavor));
} else {
final DataFlavor[] flavors = tr.getTransferDataFlavors();
boolean handled = false;
for (final DataFlavor flavor : flavors) {
if (flavor.isRepresentationClassReader()) {
event.acceptDrop(DnDConstants.ACTION_COPY);
final BufferedReader reader = new BufferedReader(flavor.getReaderForText(tr));
handled = true;
String fileName = null;
while ((fileName = reader.readLine()) != null) {
try {
// kde seems to append a 0 char to the end of the reader
if (!ZERO_CHAR_STRING.equals(fileName)) {
final URI uri = new URI(fileName);
if (uri.isAbsolute()) {
final File file = new File(uri);
files.add(file);
}
}
} catch (final URISyntaxException e) {
LOG.error("Drag and Drop file " + fileName + " not valid", e);
}
}
}
}
if (!handled) {
event.rejectDrop();
return;
}
}
final Project project = Project.get();
Invoke.background("Open Files", () -> project.openFiles(files));
event.getDropTargetContext().dropComplete(true);
} catch (final Throwable e) {
LOG.error("Unable to drop", e);
}
}
@Override
public void dropActionChanged(final DropTargetDragEvent event) {
if (isDragOk(event)) {
event.acceptDrag(DnDConstants.ACTION_COPY);
} else {
event.rejectDrag();
}
}
@Override
public void hierarchyChanged(final HierarchyEvent event) {
final Component component = event.getComponent();
final java.awt.Component parent = component.getParent();
if (parent == null) {
component.setDropTarget(null);
} else {
new DropTarget(component, this);
}
}
private boolean isDragOk(final DropTargetDragEvent event) {
final DataFlavor[] flavors = event.getCurrentDataFlavors();
for (final DataFlavor flavor : flavors) {
if (flavor.equals(DataFlavor.javaFileListFlavor) || flavor.isRepresentationClassReader()) {
return true;
}
}
return false;
}
}