package org.expeditee.gio; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; import org.expeditee.core.Point; import org.expeditee.gui.DisplayController; import org.expeditee.gui.FreeItems; import org.expeditee.importer.FileImporter; import org.expeditee.importer.FilePathImporter; import org.expeditee.importer.ImageImporter; import org.expeditee.importer.TextImporter; import org.expeditee.importer.pdfImporter; import org.expeditee.items.Item; import org.expeditee.items.Text; /** TODO: Comment. cts16 */ public abstract class DragAndDropManager { /** The list of custom file importers registered with the DnD manager. */ private List _customFileImporters = new LinkedList(); /** The list of standard file importers registered with the DnD manager. */ private List _standardFileImporters = new LinkedList(); /** Standard constructor. */ protected DragAndDropManager() { // Set up the standard file importers _standardFileImporters.add(new ImageImporter()); _standardFileImporters.add(new pdfImporter()); _standardFileImporters.add(new TextImporter()); _standardFileImporters.add(new FilePathImporter()); // Filepath importer as last resort } /** * Adds a custom importer. If an importer competes with another importer for * handling the same file types, the importer that was added first will have * first serve. * * @param importer * The importer to add. Must not be null * * @throws NullPointerException * if importer is null. */ public void addCustomFileImporter(FileImporter importer) { if (importer == null) throw new NullPointerException("importer"); if (!_customFileImporters.contains(importer)) { _customFileImporters.add(importer); } } /** * Removes a custom importer. * * @param importer * The importer to remove. * * @throws NullPointerException * if importer is null. */ public void removeCustomFileImporter(FileImporter importer) { if (importer == null) throw new NullPointerException("importer"); _customFileImporters.remove(importer); } /** * Imports a string into expeditee's current frame * * @param text * The text content. * @param expediteeDropPoint * The location in the current expeditee frame of where to drop * the text item. * @param attachToFreeItems TODO */ public static Text importString(String text, Point expediteeDropPoint, boolean attachToFreeItems) { assert (DisplayController.getCurrentFrame() != null); assert (text != null && text.length() > 0); Text importedTextItem = new Text(DisplayController.getCurrentFrame().getNextItemID(), text); importedTextItem.setPosition(expediteeDropPoint); if (attachToFreeItems) { FreeItems.getInstance().add(importedTextItem); } else { DisplayController.getCurrentFrame().addItem(importedTextItem); } DisplayController.requestRefresh(true); return importedTextItem; } /** Imports a list of files into Expeditee's current frame. * @param attachToFreeItems TODO*/ public void importFileList(List files, Point expediteeDropPoint, boolean attachToFreeItems) throws IOException { Point currentPoint = new Point(expediteeDropPoint); // import files one by one for (File fileToImport : files) { Item lastItem = importFile(fileToImport, currentPoint, attachToFreeItems); if (lastItem == null) { currentPoint.setY(currentPoint.getY() + 30); } else { currentPoint.setY(currentPoint.getY() + lastItem.getBoundsHeight()); } // of the item that was created // TODO: Better placement strategy // if (currentPoint.y > (Browser._theBrowser.getHeight() - 20)) // currentPoint.y = Browser._theBrowser.getHeight() - 20; } } /** * Imports a file into Expeditee. Any custom importers registered get first attempt, * followed by the standard importers. * * @param f * The file to import. * @param expediteeDropPoint * @param attachToFreeItems If true, instead of adding to generated item at {@code expediteeDropPoint}, add to free items. * * @throws IOException */ public Item importFile(File f, Point expediteeDropPoint, boolean attachToFreeItems) throws IOException { assert (f != null); // Check for custom importers first. They get preference to standard // importing routines... Item lastCreatedItem; if (null == (lastCreatedItem = performFileImport(_customFileImporters, f, expediteeDropPoint, attachToFreeItems))) { // Standard file importing lastCreatedItem = performFileImport(_standardFileImporters, f, expediteeDropPoint, attachToFreeItems); } return lastCreatedItem; } /** * Imports a single file into Expeditee's current frame. Importers are given the opportunity to * interpret the file in order of their addition to the list. * @param attachToFreeItems If true, instead of adding to generated item at {@code expediteeDropPoint}, add to free items. */ private Item performFileImport(List importers, File f, Point expediteeDropPoint, boolean attachToFreeItems) throws IOException { for (FileImporter fi : importers) { Item lastCreated = fi.importFile(f, expediteeDropPoint, attachToFreeItems); if (lastCreated != null) return lastCreated; } return null; } /** * Converts a string formatted as a list of URIs into a list of Files. * * Code adopted from SUN - java BUG ID 4899516 workaround for KDE/GNOME * Desktops * * @param uriListString * Formatted according to RFC 2483 * * @return The list of FILES in the uriListString. Never null. */ protected List textURIListToFileList(String uriListString) { List fileList = new LinkedList(); for (StringTokenizer st = new StringTokenizer(uriListString, "\r\n"); st.hasMoreTokens();) { String s = st.nextToken(); if (s.startsWith("#")) { // the line is a comment (as per the RFC 2483) continue; } try { URI uri = new URI(s); File file = new File(uri); fileList.add(file); } catch (URISyntaxException e) { // malformed URI } catch (IllegalArgumentException e) { // the URI is not a valid 'file:' URI } } return fileList; } }