1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.commons.gui.dnd;
21
22 import java.awt.datatransfer.DataFlavor;
23 import java.awt.datatransfer.Transferable;
24 import java.awt.datatransfer.UnsupportedFlavorException;
25 import java.io.File;
26 import java.io.IOException;
27 import java.net.MalformedURLException;
28 import java.net.URL;
29 import java.net.URLDecoder;
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.StringTokenizer;
33 import javax.swing.JComponent;
34 import javax.swing.TransferHandler;
35
36 /***
37 * Abstract handler class easing drag and drop support of file objects.
38 * <p>
39 * Also handles Linux Desktop file drag and drops which don't seem to translate
40 * to the {@link java.awt.datatransfer.DataFlavor#javaFileListFlavor}.
41 * <p>
42 * Subclasses should override {@link #createTransferable(JComponent)}
43 * and {@link #importFiles(JComponent, List)}.
44 *
45 * @author Felix Berger
46 */
47 public abstract class AbstractFileTransferHandler extends TransferHandler
48 {
49
50 /***
51 * URI flavor used for file drag and drops on the Linux desktop.
52 */
53 public static DataFlavor linuxURIFlavor;
54
55 static {
56 linuxURIFlavor = createLinuxURIFlavor();
57 }
58
59 private static DataFlavor createLinuxURIFlavor()
60 {
61 try {
62 return new DataFlavor("text/uri-list;class=java.lang.String");
63 }
64 catch (ClassNotFoundException cnfe) {
65 return null;
66 }
67 }
68
69 /***
70 * Returns true if one of the supported flavors is either
71 * {@link DataFlavor#javaFileListFlavor} or {@link #linuxURIFlavor}.
72 */
73 @Override
74 public boolean canImport(JComponent comp, DataFlavor[] transferFlavors)
75 {
76 for (DataFlavor flavor : transferFlavors) {
77 if (flavor.equals(DataFlavor.javaFileListFlavor)
78 || flavor.equals(AbstractFileTransferHandler.linuxURIFlavor)) {
79 return true;
80 }
81 }
82 return false;
83 }
84
85 /***
86 * Returns {@link TransferHandler#COPY}.
87 */
88 @Override
89 public int getSourceActions(JComponent c)
90 {
91 return TransferHandler.COPY;
92 }
93
94 /***
95 * Returns <code>null</code>.
96 * <p>
97 * Subclasses can return a {@link FileTransferable}.
98 */
99 @Override
100 protected Transferable createTransferable(JComponent c)
101 {
102 return null;
103 }
104
105 /***
106 * Returns <code>false</code>, thus disallowing dropping of files on
107 * the component <code>comp</code>.
108 * <p>
109 * Subclasses should import the list of <code>files</code> and return true
110 * on success.
111 */
112 public boolean importFiles(JComponent comp, List<File> files)
113 {
114 return false;
115 }
116
117 /***
118 * Overriden to extract the file lists from the different types of
119 * transferables.
120 */
121 @Override
122 public boolean importData(JComponent comp, Transferable t)
123 {
124 List<File> files = null;
125 try {
126 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
127 files = (List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);
128 }
129 else if (t.isDataFlavorSupported(AbstractFileTransferHandler.linuxURIFlavor)) {
130 String s = (String)t.getTransferData(AbstractFileTransferHandler.linuxURIFlavor);
131 StringTokenizer st = new StringTokenizer(s, System.getProperty("line.separator"));
132 files = new ArrayList<File>();
133 while (st.hasMoreTokens()) {
134 String file = st.nextToken();
135 try {
136 URL url = new URL(file);
137 files.add(new File(URLDecoder.decode(url.getPath())));
138 }
139 catch (MalformedURLException mue) {
140 }
141 }
142 }
143 }
144 catch (UnsupportedFlavorException e) {
145 return false;
146 }
147 catch (IOException e) {
148 return false;
149 }
150 return (files != null && !files.isEmpty()) ? importFiles(comp, files) : false;
151 }
152
153 }