content: package tim.prune.fileutils;
  
  import java.awt.datatransfer.DataFlavor;
  import java.io.File;
  import java.net.URI;
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.swing.TransferHandler;
  
  import tim.prune.App;
  
  /**
   * Class to listen for drag/drop events and react to dropping files on to the application
   */
  public class FileDropHandler extends TransferHandler
  {
  	/** App object for passing results back to */
  	private final App _app;
  
  	/** Fixed flavour in case the java file list flavour isn't available */
  	private static DataFlavor _uriListFlavour = null;
  
  	/** Static block to initialise the list flavour */
  	static
  	{
  		try {
  			_uriListFlavour = new DataFlavor("text/uri-list;class=java.lang.String");
  		} catch (ClassNotFoundException nfe) {}
  	}
  
  
  	/**
  	 * Constructor
  	 * @param inApp App object to pass results of drop back to
  	 */
  	public FileDropHandler(App inApp) {
  		_app = inApp;
  	}
  
  	/**
  	 * Check if the object being dragged can be accepted
  	 * @param inSupport object to check
  	 */
  	public boolean canImport(TransferSupport inSupport)
  	{
  		boolean retval = inSupport.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
  			|| inSupport.isDataFlavorSupported(_uriListFlavour);
  		// Modify icon to show a copy, not a move (+ icon on cursor)
  		if (retval) {
  			inSupport.setDropAction(COPY);
  		}
  		return retval;
  	}
  
  	/**
  	 * Accept the incoming data and pass it on to the App
  	 * @param inSupport contents of drop
  	 */
  	public boolean importData(TransferSupport inSupport)
  	{
  		if (!canImport(inSupport)) {return false;} // not allowed
  
  		boolean success = false;
  		ArrayList<File> dataFiles = new ArrayList<>();
  
  		// Try a java file list flavour first
  		try
  		{
  			@SuppressWarnings("unchecked")
  			List<File> fileList = (List<File>) inSupport.getTransferable().getTransferData(
  				DataFlavor.javaFileListFlavor);
  			success = true;
  
  			for (File f : fileList)
  			{
  				if (f != null && f.exists())
  				{
  					if (f.isDirectory()) {
  						addDirectoryToList(f, dataFiles);
  					}
  					else if (f.isFile()) {
  						dataFiles.add(f);
  					}
  				}
  			}
  		} catch (Exception e) {}  // exception caught, probably missing a javafilelist flavour - just continue
  
  		// If that didn't work, try a list of strings instead
  		if (!success)
  		{
  			try
  			{
  				String pathList = inSupport.getTransferable().getTransferData(_uriListFlavour).toString();
  
  				for (String s : pathList.split("[\n\r]+"))
  				{
  					if (s != null && !s.equals(""))
  					{
  						File f = new File(new URI(s));
  						if (f.exists())
  						{
  							if (f.isDirectory()) {
  								addDirectoryToList(f, dataFiles);
  							}
  							else if (f.isFile()) {
  								dataFiles.add(f);
  							}
  						}
  					}
  				}
  			} catch (Exception e) {
  				System.err.println("exception: " + e.getClass().getName() + " - " + e.getMessage());
  				return false;
  			}
  		}
  
  		// Pass files back to app
  		if (!dataFiles.isEmpty()) {
  			_app.loadDataFiles(dataFiles);
  		}
  		return true;
  	}
  
  
  	/**
  	 * Recursively-called method to add files from the given directory (and its subdirectories)
  	 * to the given list of files
  	 * @param inDir directory to add
  	 * @param inList file list to append to
  	 */
  	private void addDirectoryToList(File inDir, List<File> inList)
  	{
  		if (inDir != null && inDir.exists() && inDir.canRead() && inDir.isDirectory() && inList != null)
  		{
  			for (File file : FileList.filesIn(inDir))
  			{
  				if (file != null && file.exists() && file.canRead())
  				{
  					if (file.isFile())
  					{
  						// Add the found file to the list (if it's not in there already)
  						if (!inList.contains(file)) {
  							inList.add(file);
  						}
  					}
  					else if (file.isDirectory())
  					{
  						// Recursively add the files from subdirectories
  						addDirectoryToList(file, inList);
  					}
  				}
  			}
  		}
  	}
  }
  