Package ch.randelshofer.gui.datatransfer

Source Code of ch.randelshofer.gui.datatransfer.FileTextFieldTransferHandler

/*
* @(#)FileTextFieldTransferHandler.java  1.0  September 8, 2007
*
* Copyright (c) 2007 Werner Randelshofer
* Hausmatt 10, CH-6405 Immensee, Switzerland
* All rights reserved.
*
* The copyright of this software is owned by Werner Randelshofer.
* You may not use, copy or modify this software, except in 
* accordance with the license agreement you entered into with 
* Werner Randelshofer. For details see accompanying license terms.
*/

package ch.randelshofer.gui.datatransfer;

import java.awt.datatransfer.*;
import java.awt.im.InputContext;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;

/**
* The FileTextFieldTransferHandler can be used to add drag and drop
* support for JTextFields, which contain the path to a file.
*
* @author Werner Randelshofer
* @version 1.0 September 8, 2007 Created.
*/
public class FileTextFieldTransferHandler extends TransferHandler {
    private boolean shouldRemove;
    private JTextComponent exportComp;
    private int p0;
    private int p1;
   
   
    /** Creates a new instance. */
    public FileTextFieldTransferHandler() {
    }
   
    public boolean importData(JComponent comp, Transferable t) {
        JTextComponent c = (JTextComponent)comp;
       
        // if we are importing to the same component that we exported from
        // then don't actually do anything if the drop location is inside
        // the drag location and set shouldRemove to false so that exportDone
        // knows not to remove any data
        if (c == exportComp && c.getCaretPosition() >= p0 && c.getCaretPosition() <= p1) {
            shouldRemove = false;
            return true;
        }
       
        boolean imported = false;
        if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            InputContext ic = c.getInputContext();
            if (ic != null) {
                ic.endComposition();
            }
           
            try {
                java.util.List list = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
                c.setText(((File) list.get(0)).getPath());
                imported = true;
            } catch (UnsupportedFlavorException ex) {
                //   ex.printStackTrace();
            } catch (IOException ex) {
                //   ex.printStackTrace();
            }
        }
       
        if (! imported) {
            DataFlavor importFlavor = getImportFlavor(t.getTransferDataFlavors(), c);
            if (importFlavor != null) {
                InputContext ic = c.getInputContext();
                if (ic != null) {
                    ic.endComposition();
                }
                try {
                    String text = (String) t.getTransferData(DataFlavor.stringFlavor);
                    Reader r = importFlavor.getReaderForText(t);
                    boolean useRead = false;
                    handleReaderImport(r, c, useRead);
                    imported = true;
                } catch (UnsupportedFlavorException ex) {
                    //   ex.printStackTrace();
                } catch (BadLocationException ex) {
                    //   ex.printStackTrace();
                } catch (IOException ex) {
                    //   ex.printStackTrace();
                }
            }
        }
        return imported;
    }
   
    protected Transferable createTransferable(JComponent comp) {
       
        CompositeTransferable t;
       
        JTextComponent c = (JTextComponent)comp;
        shouldRemove = true;
        p0 = c.getSelectionStart();
        p1 = c.getSelectionEnd();
        if (p0 != p1) {
            t = new CompositeTransferable();
           
            String text = c.getSelectedText();
           
            //LinkedList fileList = new LinkedList();
            //fileList.add(new File(text));
            //t.add(new JVMLocalObjectTransferable(DataFlavor.javaFileListFlavor, fileList));
            t.add(new StringTransferable(text));
            t.add(new PlainTextTransferable(text));
        } else {
            t = null;
        }
       
       
        return t;
    }
   
    public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
        JTextComponent c = (JTextComponent)comp;
        if (!(c.isEditable() && c.isEnabled())) {
            return false;
        }
       
        for (DataFlavor flavor : transferFlavors) {
            if (flavor.isFlavorJavaFileListType() ||
                    flavor.isFlavorTextType()) {
                return true;
            }
        }
       
        return false;
    }
   
    /**
     * Try to find a flavor that can be used to import a Transferable.
     * The set of usable flavors are tried in the following order:
     * <ol>
     *     <li>First, an attempt to find a text/plain flavor is made.
     *     <li>Second, an attempt to find a flavor representing a String reference
     *         in the same VM is made.
     *     <li>Lastly, DataFlavor.stringFlavor is searched for.
     * </ol>
     */
    protected DataFlavor getImportFlavor(DataFlavor[] flavors, JTextComponent c) {
        DataFlavor plainFlavor = null;
        DataFlavor refFlavor = null;
        DataFlavor stringFlavor = null;
       
        for (int i = 0; i < flavors.length; i++) {
            String mime = flavors[i].getMimeType();
            if (mime.startsWith("text/plain")) {
                return flavors[i];
            } else if (refFlavor == null && mime.startsWith("application/x-java-jvm-local-objectref")
            && flavors[i].getRepresentationClass() == java.lang.String.class) {
                refFlavor = flavors[i];
            } else if (stringFlavor == null && flavors[i].equals(DataFlavor.stringFlavor)) {
                stringFlavor = flavors[i];
            }
        }
        if (refFlavor != null) {
            return refFlavor;
        } else if (stringFlavor != null) {
            return stringFlavor;
        }
        return null;
    }
    /**
     * Import the given stream data into the text component.
     */
    protected void handleReaderImport(Reader in, JTextComponent c, boolean useRead)
    throws BadLocationException, IOException {
        if (useRead) {
            int startPosition = c.getSelectionStart();
            int endPosition = c.getSelectionEnd();
            int length = endPosition - startPosition;
            EditorKit kit = c.getUI().getEditorKit(c);
            Document doc = c.getDocument();
            if (length > 0) {
                doc.remove(startPosition, length);
            }
            kit.read(in, doc, startPosition);
        } else {
            char[] buff = new char[1024];
            int nch;
            boolean lastWasCR = false;
            int last;
            StringBuffer sbuff = null;
           
            // Read in a block at a time, mapping \r\n to \n, as well as single
            // \r to \n.
            while ((nch = in.read(buff, 0, buff.length)) != -1) {
                if (sbuff == null) {
                    sbuff = new StringBuffer(nch);
                }
                last = 0;
                for(int counter = 0; counter < nch; counter++) {
                    switch(buff[counter]) {
                        case '\r':
                            if (lastWasCR) {
                                if (counter == 0) {
                                    sbuff.append('\n');
                                } else {
                                    buff[counter - 1] = '\n';
                                }
                            } else {
                                lastWasCR = true;
                            }
                            break;
                        case '\n':
                            if (lastWasCR) {
                                if (counter > (last + 1)) {
                                    sbuff.append(buff, last, counter - last - 1);
                                }
                                // else nothing to do, can skip \r, next write will
                                // write \n
                                lastWasCR = false;
                                last = counter;
                            }
                            break;
                        default:
                            if (lastWasCR) {
                                if (counter == 0) {
                                    sbuff.append('\n');
                                } else {
                                    buff[counter - 1] = '\n';
                                }
                                lastWasCR = false;
                            }
                            break;
                    }
                }
                if (last < nch) {
                    if (lastWasCR) {
                        if (last < (nch - 1)) {
                            sbuff.append(buff, last, nch - last - 1);
                        }
                    } else {
                        sbuff.append(buff, last, nch - last);
                    }
                }
            }
            if (lastWasCR) {
                sbuff.append('\n');
            }
            System.out.println("FileTextTransferHandler "+c.getSelectionStart()+".."+c.getSelectionEnd());
            c.replaceSelection(sbuff != null ? sbuff.toString() : "");
        }
    }
   
    // --- TransferHandler methods ------------------------------------
   
    /**
     * This is the type of transfer actions supported by the source.  Some models are
     * not mutable, so a transfer operation of COPY only should
     * be advertised in that case.
     *
     * @param c  The component holding the data to be transfered.  This
     *  argument is provided to enable sharing of TransferHandlers by
     *  multiple components.
     * @return  This is implemented to return NONE if the component is a JPasswordField
     *  since exporting data via user gestures is not allowed.  If the text component is
     *  editable, COPY_OR_MOVE is returned, otherwise just COPY is allowed.
     */
    public int getSourceActions(JComponent comp) {
        JTextComponent c = (JTextComponent) comp;
       
        if (c instanceof JPasswordField &&
                c.getClientProperty("JPasswordField.cutCopyAllowed") !=
                Boolean.TRUE) {
            return NONE;
        }
       
        return c.isEditable() ? COPY_OR_MOVE : COPY;
    }
   
   
    /**
     * This method is called after data has been exported.  This method should remove
     * the data that was transfered if the action was MOVE.
     *
     * @param source The component that was the source of the data.
     * @param data   The data that was transferred or possibly null
     *               if the action is <code>NONE</code>.
     * @param action The actual action that was performed.
     */
    protected void exportDone(JComponent comp, Transferable data, int action) {
        JTextComponent c = (JTextComponent)comp;
       
        // only remove the text if shouldRemove has not been set to
        // false by importData and only if the action is a move
        if (shouldRemove && action == MOVE) {
            try {
                Document doc = c.getDocument();
                doc.remove(p0, p1 - p0);
            } catch (BadLocationException e) {
            }
        }
        exportComp = null;
    }
   
}
TOP

Related Classes of ch.randelshofer.gui.datatransfer.FileTextFieldTransferHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.