336
|
Chapter 9, Drag-and-Drop
#66 Handle Dropped URLs
HACK
H A C K
#66
Handle Dropped URLs
Hack #66
Drag-and-drop is like a box of chocolates; you never know what you’re going
to get....
Bookmark menus are so 1995. Today, you should expect to be able to drag
URLs to other applications and have those applications open web pages,
store the address in a bookmark database, start an email in response to a
mailto: URL, etc. Java’s networking chops are well-established and aren’t
the problem here. The issue is actually getting the URL itself from the drop.
To accept drops of native objects, your GUI needs to designate some
Component as the onscreen drop target. Your code then implements the
DropTarget
interface, which means your implementation will get callbacks
when the user drags the mouse into your component, over it, out of it, etc.
Most of
DropTarget’s methods can be left as no-ops; for now, only the drop( )
method matters.
What’s interesting about native drag-and-drop (and copy-and-paste, for that
matter) is that there’s not necessarily one way to represent the data being
transferred. Instead, you do a sort of negotiation with the
Transferable
passed to you by the DropTargetDropEvent: it specifies, in order of robust-
ness, which
DataFlavors it can deliver, or you ask whether specific
DataFlavors are supported.
In the demo code in Example 9-3, I have a method called
dumpDataFlavors( ),
which shows the
DataFlavors offered to you by the drop. You can use
System.out.println( ) on a particular flavor to get its MIME type, which
describes the contents of the drop, and a representation class, which indi-
cates how those contents will be provided to you by
Transferable.
getTransferData( )
. For example, some browsers will give you a java.net.
URL
, whose DataFlavor looks like this:
java.awt.datatransfer.DataFlavor[mimetype=application/x-java-url;
representationclass=java.net.URL]
One thing that’s surprising is the number of DataFlavors offered by popular
web browsers. Table 9-1 is a short listing of some of the browsers I tested.
Table 9-1. Browsers and their supported DataFlavors
Browser Supported DataFlavors
Firefox 1.0 / Windows XP 78
MSIE 6.0 / Windows XP 53
Safari 1.3 / Mac OS X 53
Firefox 1.0 / Mac OS X 30
MSIE 5.2.3 / Mac OS X 53
Handle Dropped URLs #66
Chapter 9, Drag-and-Drop
|
337
HACK
Fortunately, a few DataFlavors appear on the lists for each browser, so your
drop can just handle these common cases.
The
URLDropTargetDemo
class in Example 9-3 presents a large Drop Here
label and a
JTextField
to show the dropped URL. I could have opened a
stream from that URL and rendered its contents in Swing’s
HTMLEditorKit
,
but the result looks so bad with real-world web pages that it wasn’t worth it.
Besides, your app might be doing something other than opening web pages,
such as storing bookmarks or starting emails.
Example 9-3. A drop target for URLs
public class URLDropTargetDemo extends JPanel
implements DropTargetListener {
DropTarget dropTarget;
JLabel dropHereLabel;
JTextField statusField;
static DataFlavor urlFlavor;
static {
try {
urlFlavor =
new DataFlavor ("application/x-java-url; class=java.net.URL");
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace( );
}
}
public URLDropTargetDemo( ) {
super(new BorderLayout( ));
dropHereLabel = new JLabel ("Drop here",
SwingConstants.CENTER);
dropHereLabel.setFont (getFont( ).deriveFont (Font.BOLD, 24.0f));
add (dropHereLabel, BorderLayout.CENTER);
// set up drop target stuff
dropTarget = new DropTarget (dropHereLabel, this);
statusField = new JTextField (30);
statusField.setEditable(false);
add (statusField, BorderLayout.SOUTH);
}
public static void main (String[] args) {
JFrame frame = new JFrame ("URL DropTarget Demo");
URLDropTargetDemo demoPanel = new URLDropTargetDemo( );
frame.getContentPane( ).add (demoPanel);
frame.pack( );
frame.setVisible(true);
}
338
|
Chapter 9, Drag-and-Drop
#66 Handle Dropped URLs
HACK
A static initializer sets up a flavor for getting real java.net.URLs (MIME type
application/x-java-url) from applications that provide them. The only
other
DataFlavor you’ll need is a string flavor that exists as a constant in the
DataFlavor class itself.
// drop target listener events
public void dragEnter (DropTargetDragEvent dtde) {}
public void dragExit (DropTargetEvent dte) {}
public void dragOver (DropTargetDragEvent dtde) {}
public void drop (DropTargetDropEvent dtde) {
System.out.println ("drop");
dtde.acceptDrop (DnDConstants.ACTION_COPY_OR_MOVE);
Transferable trans = dtde.getTransferable( );
dumpDataFlavors (trans);
boolean gotData = false;
try {
// try for application/x-java-url flavor
if (trans.isDataFlavorSupported (urlFlavor)) {
URL url = (URL) trans.getTransferData (urlFlavor);
statusField.setText (url.toString( ));
statusField.setCaretPosition (0);
gotData = true;
} else if (trans.isDataFlavorSupported (DataFlavor.stringFlavor)) {
// try for string flavor
String s =
(String) trans.getTransferData (DataFlavor.stringFlavor);
statusField.setText (s);
gotData = true;
}
} catch (Exception e) {
e.printStackTrace( );
} finally {
System.out.println ("gotData is " + gotData);
dtde.dropComplete (gotData);
}
}
public void dropActionChanged (DropTargetDragEvent dtde) {}
private void dumpDataFlavors (Transferable trans) {
System.out.println ("Flavors:");
DataFlavor[] flavors = trans.getTransferDataFlavors( );
for (int i=0; i<flavors.length; i++) {
System.out.println ("*** " + i + ": " + flavors[i]);
}
}
}
Example 9-3. A drop target for URLs (continued)

Get Swing Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.