source: trunk/src/org/expeditee/importer/FrameDNDTransferHandler.java@ 919

Last change on this file since 919 was 919, checked in by jts21, 10 years ago

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

File size: 9.8 KB
Line 
1/**
2 * FrameDNDTransferHandler.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.importer;
20
21import java.awt.Point;
22import java.awt.datatransfer.DataFlavor;
23import java.awt.datatransfer.UnsupportedFlavorException;
24import java.io.File;
25import java.io.IOException;
26import java.net.URI;
27import java.net.URISyntaxException;
28import java.util.LinkedList;
29import java.util.List;
30import java.util.StringTokenizer;
31
32import javax.swing.TransferHandler;
33
34import org.expeditee.gui.DisplayIO;
35import org.expeditee.gui.FrameGraphics;
36import org.expeditee.gui.MessageBay;
37import org.expeditee.items.Item;
38import org.expeditee.items.Text;
39
40/**
41 *
42 * Expeditee's transfer handler (swing's drag and drop scheme) for importing
43 * data into frames.
44 *
45 * @author Brook Novak
46 *
47 */
48public class FrameDNDTransferHandler extends TransferHandler {
49
50 private static final long serialVersionUID = 1L;
51
52 private List<FileImporter> _customFileImporters = new LinkedList<FileImporter>();
53
54 private List<FileImporter> _standardFileImporters = new LinkedList<FileImporter>();
55
56 // GNOME and KDE desktops have a specialized way of DNDing files
57 private DataFlavor _URIListDataflavorString;
58
59 private DataFlavor _URIListDataflavorCharArray;
60
61 private static FrameDNDTransferHandler _instance = new FrameDNDTransferHandler();
62
63 public static FrameDNDTransferHandler getInstance() {
64 return _instance;
65 }
66
67 private FrameDNDTransferHandler() {
68
69 // Add standard file importers - order from most ideal to last resort
70 // (if competing)
71
72 // TODO: Image
73 _standardFileImporters.add(new ImageImporter());
74 _standardFileImporters.add(new pdfImporter());
75 _standardFileImporters.add(new TextImporter());
76 _standardFileImporters.add(new FilePathImporter()); // Filepath importer
77 // as last resort
78
79 try {
80 _URIListDataflavorString = new DataFlavor(
81 "text/uri-list;class=java.lang.String");
82 _URIListDataflavorCharArray = new DataFlavor(
83 "text/uri-list;class=\"[C\"");
84 } catch (ClassNotFoundException e) { // This would never happen,
85 // java.lang.String is always
86 // present
87 e.printStackTrace();
88 _URIListDataflavorString = null;
89 }
90 assert (_URIListDataflavorString != null);
91 assert (_URIListDataflavorCharArray != null);
92
93 }
94
95 /**
96 * Adds a custom importer. If an importer competes with another importer for
97 * handling the same file types, the importer that was added first will have
98 * first serve.
99 *
100 * @param importer
101 * The importer to add. Must not be null
102 *
103 * @throws NullPointerException
104 * if importer is null.
105 */
106 public void addCustomFileImporter(FileImporter importer) {
107 if (importer == null)
108 throw new NullPointerException("importer");
109 if (!_customFileImporters.contains(importer))
110 _customFileImporters.add(importer);
111
112 }
113
114 /**
115 * Removes a custom importer.
116 *
117 * @param importer
118 * The importer to remove.
119 *
120 * @throws NullPointerException
121 * if importer is null.
122 */
123 public void removeCustomFileImporter(FileImporter importer) {
124 if (importer == null)
125 throw new NullPointerException("importer");
126 _customFileImporters.remove(importer);
127 }
128
129 @Override
130 public boolean canImport(TransferSupport support) {
131
132 if (!support.isDrop()) {
133 return false;
134 }
135
136 // we only import Strings
137 if (support.isDataFlavorSupported(DataFlavor.stringFlavor)
138 || support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
139 || support.isDataFlavorSupported(_URIListDataflavorString)
140 || support.isDataFlavorSupported(_URIListDataflavorCharArray)) {
141
142 // check if the source actions (a bitwise-OR of supported actions)
143 // contains the COPY action
144 boolean copySupported = (COPY & support.getSourceDropActions()) == COPY;
145 if (copySupported) {
146 support.setDropAction(COPY);
147 return true;
148 }
149 }
150
151 // Reject transfer
152 return false;
153 }
154
155 @Override
156 public boolean importData(TransferSupport support) {
157
158 if (!canImport(support) || DisplayIO.getCurrentFrame() == null)
159 return false;
160
161 // Get the drop location of where to lot the import
162 DropLocation location = support.getDropLocation();
163
164 // Covert it into expeditee space
165 Point expediteeDropPoint = location.getDropPoint();
166
167 try {
168
169 // The list of data flavors are ordered by most rich to least ..
170 // keep trying until first
171 // data flavor recognized.
172 for (DataFlavor df : support.getTransferable()
173 .getTransferDataFlavors()) {
174
175 System.out.println(df);
176
177 if (df == DataFlavor.stringFlavor) { // import as text item
178
179 String str = (String) support.getTransferable()
180 .getTransferData(DataFlavor.stringFlavor);
181
182 if (str != null && str.length() > 0) {
183 importString(str, expediteeDropPoint);
184 return true;
185 }
186
187 // Usually Windows and MAC enviroments
188 } else if (df == DataFlavor.javaFileListFlavor
189 || df.getSubType().equals("x-java-file-list")) { // Windows
190 // has
191 // other
192 // random
193 // types...
194
195 List<? extends File> files = (List<? extends File>) support
196 .getTransferable().getTransferData(
197 DataFlavor.javaFileListFlavor);
198
199 importFileList(files, expediteeDropPoint);
200
201 return true;
202
203 // Usually GNOME and KDE enviroments
204 } else if (df.equals(_URIListDataflavorString)) {
205
206 String data = (String) support.getTransferable()
207 .getTransferData(_URIListDataflavorString);
208
209 List<File> files = textURIListToFileList(data);
210
211 importFileList(files, expediteeDropPoint);
212
213 return true;
214
215 } else if (df.equals(_URIListDataflavorCharArray)) {
216
217 char[] data = (char[]) support.getTransferable()
218 .getTransferData(_URIListDataflavorCharArray);
219
220 String uriString = new String(data);
221
222 List<File> files = textURIListToFileList(uriString);
223
224 importFileList(files, expediteeDropPoint);
225
226 return true;
227 }
228 }
229
230 } catch (UnsupportedFlavorException e) {
231 MessageBay
232 .displayMessage("Drag and drop for that type of data is not supported");
233 } catch (IOException e) {
234 e.printStackTrace();
235 MessageBay.displayMessage("Failed to import data in Expeditee");
236 }
237
238 return false;
239 }
240
241 /**
242 * Imports a string into expeditee's current frame
243 *
244 * @param text
245 * The text content.
246 *
247 * @param expediteeDropPoint
248 * The location in the current ecpeditee frame of where to drop
249 * the text item.
250 */
251 public static Text importString(String text, Point expediteeDropPoint) {
252
253 assert (DisplayIO.getCurrentFrame() != null);
254 assert (text != null && text.length() > 0);
255
256 Text importedTextItem = new Text(DisplayIO.getCurrentFrame()
257 .getNextItemID(), text);
258 importedTextItem.setPosition(expediteeDropPoint);
259
260 DisplayIO.getCurrentFrame().addItem(importedTextItem);
261 FrameGraphics.requestRefresh(true);
262
263 return importedTextItem;
264 }
265
266 public void importFileList(List<? extends File> files,
267 Point expediteeDropPoint) throws IOException {
268
269 Point currentPoint = expediteeDropPoint.getLocation();
270
271 for (File fileToImport : files) { // import files one by one
272
273 Item lastItem = importFile(fileToImport, currentPoint);
274
275 if (lastItem == null) {
276 currentPoint.y += 30;
277 } else {
278 currentPoint.y += lastItem.getBoundsHeight();
279 }
280 // of the item that was created
281
282 // TODO: Better placement strategy
283 // if (currentPoint.y > (Browser._theBrowser.getHeight() - 20))
284 // currentPoint.y = Browser._theBrowser.getHeight() - 20;
285 }
286 }
287
288 /**
289 * Imports a file into expeditee.
290 *
291 * @param f
292 * The file to import.
293 *
294 * @param expediteeDropPoint
295 *
296 * @throws IOException
297 */
298 public Item importFile(File f, Point expediteeDropPoint) throws IOException {
299 assert (f != null);
300
301 // Check for custom importers first. They get preference to standard
302 // importing routines...
303 Item lastCreatedItem;
304 if (null == (lastCreatedItem = performFileImport(_customFileImporters,
305 f, expediteeDropPoint))) {
306
307 // Standard file importing
308 lastCreatedItem = performFileImport(_standardFileImporters, f,
309 expediteeDropPoint);
310
311 }
312 return lastCreatedItem;
313 }
314
315 private Item performFileImport(List<FileImporter> importers, File f,
316 Point expediteeDropPoint) throws IOException {
317
318 for (FileImporter fi : importers) {
319 Item lastCreated = fi.importFile(f, expediteeDropPoint);
320 if (lastCreated != null)
321 return lastCreated;
322 }
323
324 return null;
325 }
326
327 /**
328 * Code adopted from SUN - java BUG ID 4899516 workaround for KDE/GNOME
329 * Desktops
330 *
331 * @param uriListString
332 * Formatted according to RFC 2483
333 *
334 * @return The list of FILES in the uriListString. Never null.
335 */
336 private List<File> textURIListToFileList(String uriListString) {
337
338 List<File> fileList = new LinkedList<File>();
339
340 for (StringTokenizer st = new StringTokenizer(uriListString, "\r\n"); st
341 .hasMoreTokens();) {
342
343 String s = st.nextToken();
344
345 if (s.startsWith("#")) {
346 // the line is a comment (as per the RFC 2483)
347 continue;
348 }
349
350 try {
351
352 URI uri = new URI(s);
353 File file = new File(uri);
354 fileList.add(file);
355
356 } catch (URISyntaxException e) {
357 // malformed URI
358 } catch (IllegalArgumentException e) {
359 // the URI is not a valid 'file:' URI
360 }
361 }
362
363 return fileList;
364 }
365}
Note: See TracBrowser for help on using the repository browser.