EditorDropTarget4.java Source code

Java tutorial

Introduction

Here is the source code for EditorDropTarget4.java

Source

/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
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.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class EditorDropTarget4 implements DropTargetListener, PropertyChangeListener {
    public EditorDropTarget4(JEditorPane pane) {
        this.pane = pane;

        // Listen for changes in the enabled property
        pane.addPropertyChangeListener(this);

        // Save the JEditorPane's background color
        backgroundColor = pane.getBackground();

        // Create the DropTarget and register
        // it with the JEditorPane.
        dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE, this, pane.isEnabled(), null);
    }

    // Implementation of the DropTargetListener interface
    public void dragEnter(DropTargetDragEvent dtde) {
        DnDUtils.debugPrintln("dragEnter, drop action = " + DnDUtils.showActions(dtde.getDropAction()));

        // Get the type of object being transferred and determine
        // whether it is appropriate.
        checkTransferType(dtde);

        // Accept or reject the drag.
        boolean acceptedDrag = acceptOrRejectDrag(dtde);

        // Do drag-under feedback
        dragUnderFeedback(dtde, acceptedDrag);
    }

    public void dragExit(DropTargetEvent dte) {
        DnDUtils.debugPrintln("DropTarget dragExit");

        // Do drag-under feedback
        dragUnderFeedback(null, false);
    }

    public void dragOver(DropTargetDragEvent dtde) {
        DnDUtils.debugPrintln("DropTarget dragOver, drop action = " + DnDUtils.showActions(dtde.getDropAction()));

        // Accept or reject the drag
        boolean acceptedDrag = acceptOrRejectDrag(dtde);

        // Do drag-under feedback
        dragUnderFeedback(dtde, acceptedDrag);
    }

    public void dropActionChanged(DropTargetDragEvent dtde) {
        DnDUtils.debugPrintln(
                "DropTarget dropActionChanged, drop action = " + DnDUtils.showActions(dtde.getDropAction()));

        // Accept or reject the drag
        boolean acceptedDrag = acceptOrRejectDrag(dtde);

        // Do drag-under feedback
        dragUnderFeedback(dtde, acceptedDrag);
    }

    public void drop(DropTargetDropEvent dtde) {
        DnDUtils.debugPrintln("DropTarget drop, drop action = " + DnDUtils.showActions(dtde.getDropAction()));

        // Check the drop action
        if ((dtde.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {
            // Accept the drop and get the transfer data
            dtde.acceptDrop(dtde.getDropAction());
            Transferable transferable = dtde.getTransferable();

            try {
                boolean result = false;

                if (draggingFile) {
                    result = dropFile(transferable);
                } else {
                    result = dropContent(transferable, dtde);
                }

                dtde.dropComplete(result);
                DnDUtils.debugPrintln("Drop completed, success: " + result);
            } catch (Exception e) {
                DnDUtils.debugPrintln("Exception while handling drop " + e);
                dtde.rejectDrop();
            }
        } else {
            DnDUtils.debugPrintln("Drop target rejected drop");
            dtde.dropComplete(false);
        }
    }

    // PropertyChangeListener interface
    public void propertyChange(PropertyChangeEvent evt) {
        String propertyName = evt.getPropertyName();
        if (propertyName.equals("enabled")) {
            // Enable the drop target if the JEditorPane is enabled
            // and vice versa.
            dropTarget.setActive(pane.isEnabled());
        } else if (!changingBackground && propertyName.equals("background")) {
            backgroundColor = pane.getBackground();
        }
    }

    // Internal methods start here

    protected boolean acceptOrRejectDrag(DropTargetDragEvent dtde) {
        int dropAction = dtde.getDropAction();
        int sourceActions = dtde.getSourceActions();
        boolean acceptedDrag = false;

        DnDUtils.debugPrintln("\tSource actions are " + DnDUtils.showActions(sourceActions) + ", drop action is "
                + DnDUtils.showActions(dropAction));

        // Reject if the object being transferred
        // or the operations available are not acceptable.
        if (!acceptableType || (sourceActions & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
            DnDUtils.debugPrintln("Drop target rejecting drag");
            dtde.rejectDrag();
        } else if (!draggingFile && !pane.isEditable()) {
            // Can't drag text to a read-only JEditorPane
            DnDUtils.debugPrintln("Drop target rejecting drag");
            dtde.rejectDrag();
        } else if ((dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
            // Not offering copy or move - suggest a copy
            DnDUtils.debugPrintln("Drop target offering COPY");
            dtde.acceptDrag(DnDConstants.ACTION_COPY);
            acceptedDrag = true;
        } else {
            // Offering an acceptable operation: accept
            DnDUtils.debugPrintln("Drop target accepting drag");
            dtde.acceptDrag(dropAction);
            acceptedDrag = true;
        }

        return acceptedDrag;
    }

    protected void dragUnderFeedback(DropTargetDragEvent dtde, boolean acceptedDrag) {
        if (draggingFile) {
            // When dragging a file, change the background color
            Color newColor = (dtde != null && acceptedDrag ? feedbackColor : backgroundColor);
            if (newColor.equals(pane.getBackground()) == false) {
                changingBackground = true;
                pane.setBackground(newColor);
                changingBackground = false;
                pane.repaint();
            }
        } else {
            if (dtde != null && acceptedDrag) {
                // Dragging text - move the insertion cursor
                Point location = dtde.getLocation();
                pane.getCaret().setVisible(true);
                pane.setCaretPosition(pane.viewToModel(location));
            } else {
                pane.getCaret().setVisible(false);
            }
        }
    }

    protected void checkTransferType(DropTargetDragEvent dtde) {
        // Accept a list of files, or data content that
        // amounts to plain text or a Unicode text string
        acceptableType = false;
        draggingFile = false;
        if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            acceptableType = true;
            draggingFile = true;
        } else if (dtde.isDataFlavorSupported(DataFlavor.plainTextFlavor)
                || dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            acceptableType = true;
        }
        DnDUtils.debugPrintln("File type acceptable - " + acceptableType);
        DnDUtils.debugPrintln("Dragging a file - " + draggingFile);
    }

    // This method handles a drop for a list of files
    protected boolean dropFile(Transferable transferable)
            throws IOException, UnsupportedFlavorException, MalformedURLException {
        List fileList = (List) transferable.getTransferData(DataFlavor.javaFileListFlavor);
        File transferFile = (File) fileList.get(0);
        final URL transferURL = transferFile.toURL();
        DnDUtils.debugPrintln("File URL is " + transferURL);

        pane.setPage(transferURL);

        return true;
    }

    // This method handles a drop with data content
    protected boolean dropContent(Transferable transferable, DropTargetDropEvent dtde) {
        if (!pane.isEditable()) {
            // Can't drop content on a read-only text control
            return false;
        }

        try {
            // Check for a match with the current content type
            DataFlavor[] flavors = dtde.getCurrentDataFlavors();

            DataFlavor selectedFlavor = null;

            // Look for either plain text or a String.
            for (int i = 0; i < flavors.length; i++) {
                DataFlavor flavor = flavors[i];
                DnDUtils.debugPrintln("Drop MIME type " + flavor.getMimeType() + " is available");
                if (flavor.equals(DataFlavor.plainTextFlavor) || flavor.equals(DataFlavor.stringFlavor)) {
                    selectedFlavor = flavor;
                    break;
                }
            }

            if (selectedFlavor == null) {
                // No compatible flavor - should never happen
                return false;
            }

            DnDUtils.debugPrintln("Selected flavor is " + selectedFlavor.getHumanPresentableName());

            // Get the transferable and then obtain the data
            Object data = transferable.getTransferData(selectedFlavor);

            DnDUtils.debugPrintln("Transfer data type is " + data.getClass().getName());

            String insertData = null;
            if (data instanceof InputStream) {
                // Plain text flavor
                String charSet = selectedFlavor.getParameter("charset");
                InputStream is = (InputStream) data;
                byte[] bytes = new byte[is.available()];
                is.read(bytes);
                try {
                    insertData = new String(bytes, charSet);
                } catch (UnsupportedEncodingException e) {
                    // Use the platform default encoding
                    insertData = new String(bytes);
                }
            } else if (data instanceof String) {
                // String flavor
                insertData = (String) data;
            }

            if (insertData != null) {
                int selectionStart = pane.getCaretPosition();
                pane.replaceSelection(insertData);
                pane.select(selectionStart, selectionStart + insertData.length());
                return true;
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (Exception evt) {
        }

        final JFrame f = new JFrame("JEditor Pane Drop Target Example 4");

        // Create an editor with autoscrolling support
        final JEditorPane pane = new AutoScrollingEditorPane();

        // Add a drop target to the JEditorPane
        EditorDropTarget4 target = new EditorDropTarget4(pane);

        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent evt) {
                System.exit(0);
            }
        });

        JPanel panel = new JPanel();
        final JCheckBox editable = new JCheckBox("Editable");
        editable.setSelected(true);
        panel.add(editable);
        editable.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                pane.setEditable(editable.isSelected());
            }
        });

        final JCheckBox enabled = new JCheckBox("Enabled");
        enabled.setSelected(true);
        panel.add(enabled);
        enabled.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                pane.setEnabled(enabled.isSelected());
            }
        });

        f.getContentPane().add(new JScrollPane(pane), BorderLayout.CENTER);
        f.getContentPane().add(panel, BorderLayout.SOUTH);
        f.setSize(500, 400);
        f.setVisible(true);
    }

    protected JEditorPane pane;

    protected DropTarget dropTarget;

    protected boolean acceptableType; // Indicates whether data is acceptable

    protected boolean draggingFile; // True if dragging an entire file

    protected Color backgroundColor; // Original background color of JEditorPane

    protected boolean changingBackground;

    protected static final Color feedbackColor = Color.gray;
}

class DnDUtils {
    public static String showActions(int action) {
        String actions = "";
        if ((action & (DnDConstants.ACTION_LINK | DnDConstants.ACTION_COPY_OR_MOVE)) == 0) {
            return "None";
        }

        if ((action & DnDConstants.ACTION_COPY) != 0) {
            actions += "Copy ";
        }

        if ((action & DnDConstants.ACTION_MOVE) != 0) {
            actions += "Move ";
        }

        if ((action & DnDConstants.ACTION_LINK) != 0) {
            actions += "Link";
        }

        return actions;
    }

    public static boolean isDebugEnabled() {
        return debugEnabled;
    }

    public static void debugPrintln(String s) {
        if (debugEnabled) {
            System.out.println(s);
        }
    }

    private static boolean debugEnabled = (System.getProperty("DnDExamples.debug") != null);
}

class AutoScrollingEditorPane extends JEditorPane implements Autoscroll {
    public static final Insets defaultScrollInsets = new Insets(8, 8, 8, 8);

    protected Insets scrollInsets = defaultScrollInsets;

    public AutoScrollingEditorPane() {
    }

    public void setScrollInsets(Insets insets) {
        this.scrollInsets = insets;
    }

    public Insets getScrollInsets() {
        return scrollInsets;
    }

    // Implementation of Autoscroll interface
    public Insets getAutoscrollInsets() {
        Rectangle r = getVisibleRect();
        Dimension size = getSize();
        Insets i = new Insets(r.y + scrollInsets.top, r.x + scrollInsets.left,
                size.height - r.y - r.height + scrollInsets.bottom,
                size.width - r.x - r.width + scrollInsets.right);
        return i;
    }

    public void autoscroll(Point location) {
        JScrollPane scroller = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
        if (scroller != null) {
            JScrollBar hBar = scroller.getHorizontalScrollBar();
            JScrollBar vBar = scroller.getVerticalScrollBar();
            Rectangle r = getVisibleRect();
            if (location.x <= r.x + scrollInsets.left) {
                // Need to scroll left
                hBar.setValue(hBar.getValue() - hBar.getUnitIncrement(-1));
            }
            if (location.y <= r.y + scrollInsets.top) {
                // Need to scroll up
                vBar.setValue(vBar.getValue() - vBar.getUnitIncrement(-1));
            }
            if (location.x >= r.x + r.width - scrollInsets.right) {
                // Need to scroll right
                hBar.setValue(hBar.getValue() + hBar.getUnitIncrement(1));
            }
            if (location.y >= r.y + r.height - scrollInsets.bottom) {
                // Need to scroll down
                vBar.setValue(vBar.getValue() + vBar.getUnitIncrement(1));
            }
        }
    }
}