/**
TrakEM2 plugin for ImageJ(C).
Copyright (C) 2005-2009 Albert Cardona and Rodney Douglas.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation (http://www.gnu.org/licenses/gpl.txt )
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
You may contact Albert Cardona at acardona at ini.phys.ethz.ch
Institute of Neuroinformatics, University of Zurich / ETH, Switzerland.
**/
package ini.trakem2.utils;
import ij.IJ;
import ij.ImagePlus;
import ij.VirtualStack; // only after 1.38q
import ij.gui.GenericDialog;
import ini.trakem2.display.Display;
import ini.trakem2.display.Layer;
import ini.trakem2.io.ImageFileFilter;
import java.awt.Point;
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.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.swing.SwingUtilities;
public class DNDInsertImage implements DropTargetListener {
private Display display;
private DropTarget dt;
public DNDInsertImage(Display display) {
this.display = display;
this.dt = new DropTarget(display.getCanvas(), this);
}
public void destroy() {
// is there any way to really destroy it?
SwingUtilities.invokeLater(new Runnable() { public void run() {
dt.setActive(false);
display.getCanvas().setDropTarget(null);
dt.setComponent(null);
}});
}
public void dragEnter(DropTargetDragEvent e) {
e.acceptDrag(DnDConstants.ACTION_COPY);
}
public void dragExit(DropTargetEvent e) {}
public void dragOver(DropTargetDragEvent e) {}
public void dropActionChanged(DropTargetDragEvent e) {}
public void drop(final DropTargetDropEvent dtde) {
if (!display.getProject().isInputEnabled()) return;
try {
dtde.acceptDrop(DnDConstants.ACTION_COPY);
Point point = dtde.getLocation();
point.x = display.getCanvas().offScreenX(point.x);
point.y = display.getCanvas().offScreenY(point.y);
Transferable t = dtde.getTransferable();
DataFlavor[] flavors = t.getTransferDataFlavors();
int success = 0;
if (IJ.isMacOSX()) {
// Try file list first:
Object data = t.getTransferData(DataFlavor.javaFileListFlavor);
if (null != data) {
Iterator<?> iterator = ((List<?>)data).iterator();
while(iterator.hasNext()) {
File f = (File)iterator.next();
String path = f.getCanonicalPath().replace('\\', '/');
if (importImageFile(f, path, point)) success++;
}
}
}
if (0 == success) {
// Try now the String representation
for (int i=0; i<flavors.length; i++) {
if (!flavors[i].getRepresentationClass().equals(String.class)) continue;
Object ob = t.getTransferData(flavors[i]);
if (!(ob instanceof String)) continue;
String s = ob.toString().trim();
BufferedReader br = new BufferedReader(new StringReader(s));
String tmp;
while (null != (tmp = br.readLine())) {
tmp = java.net.URLDecoder.decode(tmp, "UTF-8");
if (tmp.startsWith("file://")) {
tmp = tmp.substring(7);
}
File f = new File(tmp);
if (importImageFile(f, tmp, point)) success++;
}
break;
}
}
if (0 == success && t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// from ij.plugin.DragAndDrop class by Wayne Rasband
Object data = t.getTransferData(DataFlavor.javaFileListFlavor);
Iterator<?> iterator = ((List<?>)data).iterator();
while(iterator.hasNext()) {
File f = (File)iterator.next();
String path = f.getCanonicalPath().replace('\\', '/');
importImageFile(f, path, point);
}
}
dtde.dropComplete(true);
} catch (Exception e) {
dtde.dropComplete(false);
}
}
private boolean importImageFile(File f, String path, Point point) throws Exception {
if (f.exists()) {
final Layer layer = display.getLayer();
Bureaucrat burro = null;
if (f.isDirectory()) {
// ask:
GenericDialog gd = new GenericDialog("Import directory");
String[] choice = new String[]{"Stack", "Grid", "Sequence as grid"};
gd.addChoice("Directory as: ", choice, choice[0]);
gd.showDialog();
if (gd.wasCanceled()) {
return true; // the user cancel it, so all is ok.
}
display.getLayerSet().addLayerContentStep(layer);
switch (gd.getNextChoiceIndex()) {
case 0: // as stack
// if importing image sequence as a stack:
String[] names = f.list(new ImageFileFilter()); // don't filter by name "^[^\\.].*[\\.][a-zA-Z1-9_]{3,4}$"
Utils.log2("stack size: " + names.length);
for (int i=0; i<names.length; i++) {
Utils.log2(names[i]);
}
Arrays.sort(names);
VirtualStack stack = new VirtualStack(10, 10, null, f.getAbsolutePath().replace('\\', '/')); // I don't care about the dimensions
for (int k=0; k<names.length; k++) {
IJ.redirectErrorMessages();
if (names[k].toLowerCase().endsWith(".xml")) continue; // ignore trakem2 files
stack.addSlice(names[k]);
}
if (stack.getSize() > 0) {
burro = display.getProject().getLoader().importStack(layer, point.x, point.y, new ImagePlus("stack", stack), true, path, false);
}
break;
case 1: // as grid
burro = display.getProject().getLoader().importGrid(layer, path);
break;
case 2: // sequence as grid
burro = display.getProject().getLoader().importSequenceAsGrid(layer, path);
break;
}
} else {
layer.getParent().addLayerContentStep(layer);
// single image file (single image or a stack)
burro = display.getProject().getLoader().importImage(layer, point.x, point.y, path, false);
}
if (null != burro) {
burro.addPostTask(new Runnable() { public void run() {
// The current state
layer.getParent().addLayerContentStep(layer);
}});
}
return true;
} else {
Utils.log("File not found: " + path);
return false;
}
}
}