Java tutorial
/* 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)); } } } }