corpus-services  1.0
FileDrop.java
Go to the documentation of this file.
1 package de.uni_hamburg.corpora.swing;
2 
3 
4 import java.awt.datatransfer.DataFlavor;
5 import java.io.BufferedReader;
6 import java.io.File;
7 import java.io.IOException;
8 import java.io.PrintStream;
9 import java.io.Reader;
10 
50 public class FileDrop
51 {
52  private transient javax.swing.border.Border normalBorder;
53  private transient java.awt.dnd.DropTargetListener dropListener;
54 
55 
57  private static Boolean supportsDnD;
58 
59  // Default border color
60  private static java.awt.Color defaultBorderColor = new java.awt.Color( 0f, 0f, 1f, 0.25f );
61 
72  public FileDrop(
73  final java.awt.Component c,
74  final Listener listener )
75  { this( null, // Logging stream
76  c, // Drop target
77  javax.swing.BorderFactory.createMatteBorder( 2, 2, 2, 2, defaultBorderColor ), // Drag border
78  true, // Recursive
79  listener );
80  } // end constructor
81 
82 
83 
84 
95  public FileDrop(
96  final java.awt.Component c,
97  final boolean recursive,
98  final Listener listener )
99  { this( null, // Logging stream
100  c, // Drop target
101  javax.swing.BorderFactory.createMatteBorder( 2, 2, 2, 2, defaultBorderColor ), // Drag border
102  recursive, // Recursive
103  listener );
104  } // end constructor
105 
106 
120  public FileDrop(
121  final java.io.PrintStream out,
122  final java.awt.Component c,
123  final Listener listener )
124  { this( out, // Logging stream
125  c, // Drop target
126  javax.swing.BorderFactory.createMatteBorder( 2, 2, 2, 2, defaultBorderColor ),
127  false, // Recursive
128  listener );
129  } // end constructor
130 
131 
132 
150  public FileDrop(
151  final java.io.PrintStream out,
152  final java.awt.Component c,
153  final boolean recursive,
154  final Listener listener)
155  { this( out, // Logging stream
156  c, // Drop target
157  javax.swing.BorderFactory.createMatteBorder( 2, 2, 2, 2, defaultBorderColor ), // Drag border
158  recursive, // Recursive
159  listener );
160  } // end constructor
161 
162 
163 
164 
173  public FileDrop(
174  final java.awt.Component c,
175  final javax.swing.border.Border dragBorder,
176  final Listener listener)
177  { this(
178  null, // Logging stream
179  c, // Drop target
180  dragBorder, // Drag border
181  false, // Recursive
182  listener );
183  } // end constructor
184 
185 
186 
187 
199  public FileDrop(
200  final java.awt.Component c,
201  final javax.swing.border.Border dragBorder,
202  final boolean recursive,
203  final Listener listener)
204  { this(
205  null,
206  c,
207  dragBorder,
208  recursive,
209  listener );
210  } // end constructor
211 
212 
213 
227  public FileDrop(
228  final java.io.PrintStream out,
229  final java.awt.Component c,
230  final javax.swing.border.Border dragBorder,
231  final Listener listener)
232  { this(
233  out, // Logging stream
234  c, // Drop target
235  dragBorder, // Drag border
236  false, // Recursive
237  listener );
238  } // end constructor
239 
240 
241 
242 
243 
258  public FileDrop(
259  final java.io.PrintStream out,
260  final java.awt.Component c,
261  final javax.swing.border.Border dragBorder,
262  final boolean recursive,
263  final Listener listener)
264  {
265 
266  if( supportsDnD() )
267  { // Make a drop listener
268  dropListener = new java.awt.dnd.DropTargetListener()
269  { public void dragEnter( java.awt.dnd.DropTargetDragEvent evt )
270  { log( out, "FileDrop: dragEnter event." );
271 
272  // Is this an acceptable drag event?
273  if( isDragOk( out, evt ) )
274  {
275  // If it's a Swing component, set its border
276  if( c instanceof javax.swing.JComponent )
277  { javax.swing.JComponent jc = (javax.swing.JComponent) c;
278  normalBorder = jc.getBorder();
279  log( out, "FileDrop: normal border saved." );
280  jc.setBorder( dragBorder );
281  log( out, "FileDrop: drag border set." );
282  } // end if: JComponent
283 
284  // Acknowledge that it's okay to enter
285  //evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
286  evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY );
287  log( out, "FileDrop: event accepted." );
288  } // end if: drag ok
289  else
290  { // Reject the drag event
291  evt.rejectDrag();
292  log( out, "FileDrop: event rejected." );
293  } // end else: drag not ok
294  } // end dragEnter
295 
296  public void dragOver( java.awt.dnd.DropTargetDragEvent evt )
297  { // This is called continually as long as the mouse is
298  // over the drag target.
299  } // end dragOver
300 
301  public void drop( java.awt.dnd.DropTargetDropEvent evt )
302  { log( out, "FileDrop: drop event." );
303  try
304  { // Get whatever was dropped
305  java.awt.datatransfer.Transferable tr = evt.getTransferable();
306 
307  // Is it a file list?
308  if (tr.isDataFlavorSupported (java.awt.datatransfer.DataFlavor.javaFileListFlavor))
309  {
310  // Say we'll take it.
311  //evt.acceptDrop ( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
312  evt.acceptDrop ( java.awt.dnd.DnDConstants.ACTION_COPY );
313  log( out, "FileDrop: file list accepted." );
314 
315  // Get a useful list
316  java.util.List fileList = (java.util.List)
317  tr.getTransferData(java.awt.datatransfer.DataFlavor.javaFileListFlavor);
318  java.util.Iterator iterator = fileList.iterator();
319 
320  // Convert list to array
321  java.io.File[] filesTemp = new java.io.File[ fileList.size() ];
322  fileList.toArray( filesTemp );
323  final java.io.File[] files = filesTemp;
324 
325  // Alert listener to drop.
326  if( listener != null )
327  listener.filesDropped( files );
328 
329  // Mark that drop is completed.
330  evt.getDropTargetContext().dropComplete(true);
331  log( out, "FileDrop: drop complete." );
332  } // end if: file list
333  else // this section will check for a reader flavor.
334  {
335  // Thanks, Nathan!
336  // BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
337  DataFlavor[] flavors = tr.getTransferDataFlavors();
338  boolean handled = false;
339  for (int zz = 0; zz < flavors.length; zz++) {
340  if (flavors[zz].isRepresentationClassReader()) {
341  // Say we'll take it.
342  //evt.acceptDrop ( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
343  evt.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY);
344  log(out, "FileDrop: reader accepted.");
345 
346  Reader reader = flavors[zz].getReaderForText(tr);
347 
348  BufferedReader br = new BufferedReader(reader);
349 
350  if(listener != null)
351  listener.filesDropped(createFileArray(br, out));
352 
353  // Mark that drop is completed.
354  evt.getDropTargetContext().dropComplete(true);
355  log(out, "FileDrop: drop complete.");
356  handled = true;
357  break;
358  }
359  }
360  if(!handled){
361  log( out, "FileDrop: not a file list or reader - abort." );
362  evt.rejectDrop();
363  }
364  // END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
365  } // end else: not a file list
366  } // end try
367  catch ( java.io.IOException io)
368  { log( out, "FileDrop: IOException - abort:" );
369  io.printStackTrace( out );
370  evt.rejectDrop();
371  } // end catch IOException
372  catch (java.awt.datatransfer.UnsupportedFlavorException ufe)
373  { log( out, "FileDrop: UnsupportedFlavorException - abort:" );
374  ufe.printStackTrace( out );
375  evt.rejectDrop();
376  } // end catch: UnsupportedFlavorException
377  finally
378  {
379  // If it's a Swing component, reset its border
380  if( c instanceof javax.swing.JComponent )
381  { javax.swing.JComponent jc = (javax.swing.JComponent) c;
382  jc.setBorder( normalBorder );
383  log( out, "FileDrop: normal border restored." );
384  } // end if: JComponent
385  } // end finally
386  } // end drop
387 
388  public void dragExit( java.awt.dnd.DropTargetEvent evt )
389  { log( out, "FileDrop: dragExit event." );
390  // If it's a Swing component, reset its border
391  if( c instanceof javax.swing.JComponent )
392  { javax.swing.JComponent jc = (javax.swing.JComponent) c;
393  jc.setBorder( normalBorder );
394  log( out, "FileDrop: normal border restored." );
395  } // end if: JComponent
396  } // end dragExit
397 
398  public void dropActionChanged( java.awt.dnd.DropTargetDragEvent evt )
399  { log( out, "FileDrop: dropActionChanged event." );
400  // Is this an acceptable drag event?
401  if( isDragOk( out, evt ) )
402  { //evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
403  evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY );
404  log( out, "FileDrop: event accepted." );
405  } // end if: drag ok
406  else
407  { evt.rejectDrag();
408  log( out, "FileDrop: event rejected." );
409  } // end else: drag not ok
410  } // end dropActionChanged
411  }; // end DropTargetListener
412 
413  // Make the component (and possibly children) drop targets
414  makeDropTarget( out, c, recursive );
415  } // end if: supports dnd
416  else
417  { log( out, "FileDrop: Drag and drop is not supported with this JVM" );
418  } // end else: does not support DnD
419  } // end constructor
420 
421 
422  private static boolean supportsDnD()
423  { // Static Boolean
424  if( supportsDnD == null )
425  {
426  boolean support = false;
427  try
428  { Class arbitraryDndClass = Class.forName( "java.awt.dnd.DnDConstants" );
429  support = true;
430  } // end try
431  catch( Exception e )
432  { support = false;
433  } // end catch
434  supportsDnD = new Boolean( support );
435  } // end if: first time through
436  return supportsDnD.booleanValue();
437  } // end supportsDnD
438 
439 
440  // BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
441  private static String ZERO_CHAR_STRING = "" + (char)0;
442  private static File[] createFileArray(BufferedReader bReader, PrintStream out)
443  {
444  try {
445  java.util.List list = new java.util.ArrayList();
446  java.lang.String line = null;
447  while ((line = bReader.readLine()) != null) {
448  try {
449  // kde seems to append a 0 char to the end of the reader
450  if(ZERO_CHAR_STRING.equals(line)) continue;
451 
452  java.io.File file = new java.io.File(new java.net.URI(line));
453  list.add(file);
454  } catch (Exception ex) {
455  log(out, "Error with " + line + ": " + ex.getMessage());
456  }
457  }
458 
459  return (java.io.File[]) list.toArray(new File[list.size()]);
460  } catch (IOException ex) {
461  log(out, "FileDrop: IOException");
462  }
463  return new File[0];
464  }
465  // END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
466 
467 
468  private void makeDropTarget( final java.io.PrintStream out, final java.awt.Component c, boolean recursive )
469  {
470  // Make drop target
471  final java.awt.dnd.DropTarget dt = new java.awt.dnd.DropTarget();
472  try
473  { dt.addDropTargetListener( dropListener );
474  } // end try
475  catch( java.util.TooManyListenersException e )
476  { e.printStackTrace();
477  log(out, "FileDrop: Drop will not work due to previous error. Do you have another listener attached?" );
478  } // end catch
479 
480  // Listen for hierarchy changes and remove the drop target when the parent gets cleared out.
481  c.addHierarchyListener( new java.awt.event.HierarchyListener()
482  { public void hierarchyChanged( java.awt.event.HierarchyEvent evt )
483  { log( out, "FileDrop: Hierarchy changed." );
484  java.awt.Component parent = c.getParent();
485  if( parent == null )
486  { c.setDropTarget( null );
487  log( out, "FileDrop: Drop target cleared from component." );
488  } // end if: null parent
489  else
490  { new java.awt.dnd.DropTarget(c, dropListener);
491  log( out, "FileDrop: Drop target added to component." );
492  } // end else: parent not null
493  } // end hierarchyChanged
494  }); // end hierarchy listener
495  if( c.getParent() != null )
496  new java.awt.dnd.DropTarget(c, dropListener);
497 
498  if( recursive && (c instanceof java.awt.Container ) )
499  {
500  // Get the container
501  java.awt.Container cont = (java.awt.Container) c;
502 
503  // Get it's components
504  java.awt.Component[] comps = cont.getComponents();
505 
506  // Set it's components as listeners also
507  for( int i = 0; i < comps.length; i++ )
508  makeDropTarget( out, comps[i], recursive );
509  } // end if: recursively set components as listener
510  } // end dropListener
511 
512 
513 
515  private boolean isDragOk( final java.io.PrintStream out, final java.awt.dnd.DropTargetDragEvent evt )
516  { boolean ok = false;
517 
518  // Get data flavors being dragged
519  java.awt.datatransfer.DataFlavor[] flavors = evt.getCurrentDataFlavors();
520 
521  // See if any of the flavors are a file list
522  int i = 0;
523  while( !ok && i < flavors.length )
524  {
525  // BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
526  // Is the flavor a file list?
527  final DataFlavor curFlavor = flavors[i];
528  if( curFlavor.equals( java.awt.datatransfer.DataFlavor.javaFileListFlavor ) ||
529  curFlavor.isRepresentationClassReader()){
530  ok = true;
531  }
532  // END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
533  i++;
534  } // end while: through flavors
535 
536  // If logging is enabled, show data flavors
537  if( out != null )
538  { if( flavors.length == 0 )
539  log( out, "FileDrop: no data flavors." );
540  for( i = 0; i < flavors.length; i++ )
541  log( out, flavors[i].toString() );
542  } // end if: logging enabled
543 
544  return ok;
545  } // end isDragOk
546 
547 
549  private static void log( java.io.PrintStream out, String message )
550  { // Log message if requested
551  if( out != null )
552  out.println( message );
553  } // end log
554 
555 
556 
557 
568  public static boolean remove( java.awt.Component c)
569  { return remove( null, c, true );
570  } // end remove
571 
572 
573 
584  public static boolean remove( java.io.PrintStream out, java.awt.Component c, boolean recursive )
585  { // Make sure we support dnd.
586  if( supportsDnD() )
587  { log( out, "FileDrop: Removing drag-and-drop hooks." );
588  c.setDropTarget( null );
589  if( recursive && ( c instanceof java.awt.Container ) )
590  { java.awt.Component[] comps = ((java.awt.Container)c).getComponents();
591  for( int i = 0; i < comps.length; i++ )
592  remove( out, comps[i], recursive );
593  return true;
594  } // end if: recursive
595  else return false;
596  } // end if: supports DnD
597  else return false;
598  } // end remove
599 
600 
601 
602 
603 /* ******** I N N E R I N T E R F A C E L I S T E N E R ******** */
604 
605 
621  public static interface Listener {
622 
629  public abstract void filesDropped( java.io.File[] files );
630 
631 
632  } // end inner-interface Listener
633 
634 
635 /* ******** I N N E R C L A S S ******** */
636 
637 
650  public static class Event extends java.util.EventObject {
651 
652  private java.io.File[] files;
653 
663  public Event( java.io.File[] files, Object source ) {
664  super( source );
665  this.files = files;
666  } // end constructor
667 
675  public java.io.File[] getFiles() {
676  return files;
677  } // end getFiles
678 
679  } // end inner class Event
680 
681 
682 
683 /* ******** I N N E R C L A S S ******** */
684 
685 
728  public static class TransferableObject implements java.awt.datatransfer.Transferable
729  {
736  public final static String MIME_TYPE = "application/x-net.iharder.dnd.TransferableObject";
737 
738 
748  public final static java.awt.datatransfer.DataFlavor DATA_FLAVOR =
749  new java.awt.datatransfer.DataFlavor( FileDrop.TransferableObject.class, MIME_TYPE );
750 
751 
752  private Fetcher fetcher;
753  private Object data;
754 
755  private java.awt.datatransfer.DataFlavor customFlavor;
756 
757 
758 
769  public TransferableObject( Object data )
770  { this.data = data;
771  this.customFlavor = new java.awt.datatransfer.DataFlavor( data.getClass(), MIME_TYPE );
772  } // end constructor
773 
774 
775 
786  public TransferableObject( Fetcher fetcher )
787  { this.fetcher = fetcher;
788  } // end constructor
789 
790 
791 
805  public TransferableObject( Class dataClass, Fetcher fetcher )
806  { this.fetcher = fetcher;
807  this.customFlavor = new java.awt.datatransfer.DataFlavor( dataClass, MIME_TYPE );
808  } // end constructor
809 
818  public java.awt.datatransfer.DataFlavor getCustomDataFlavor()
819  { return customFlavor;
820  } // end getCustomDataFlavor
821 
822 
823  /* ******** T R A N S F E R A B L E M E T H O D S ******** */
824 
825 
836  public java.awt.datatransfer.DataFlavor[] getTransferDataFlavors()
837  {
838  if( customFlavor != null )
839  return new java.awt.datatransfer.DataFlavor[]
840  { customFlavor,
841  DATA_FLAVOR,
842  java.awt.datatransfer.DataFlavor.stringFlavor
843  }; // end flavors array
844  else
845  return new java.awt.datatransfer.DataFlavor[]
846  { DATA_FLAVOR,
847  java.awt.datatransfer.DataFlavor.stringFlavor
848  }; // end flavors array
849  } // end getTransferDataFlavors
850 
851 
852 
864  public Object getTransferData( java.awt.datatransfer.DataFlavor flavor )
865  throws java.awt.datatransfer.UnsupportedFlavorException, java.io.IOException
866  {
867  // Native object
868  if( flavor.equals( DATA_FLAVOR ) )
869  return fetcher == null ? data : fetcher.getObject();
870 
871  // String
872  if( flavor.equals( java.awt.datatransfer.DataFlavor.stringFlavor ) )
873  return fetcher == null ? data.toString() : fetcher.getObject().toString();
874 
875  // We can't do anything else
876  throw new java.awt.datatransfer.UnsupportedFlavorException(flavor);
877  } // end getTransferData
878 
879 
880 
881 
890  public boolean isDataFlavorSupported( java.awt.datatransfer.DataFlavor flavor )
891  {
892  // Native object
893  if( flavor.equals( DATA_FLAVOR ) )
894  return true;
895 
896  // String
897  if( flavor.equals( java.awt.datatransfer.DataFlavor.stringFlavor ) )
898  return true;
899 
900  // We can't do anything else
901  return false;
902  } // end isDataFlavorSupported
903 
904 
905  /* ******** I N N E R I N T E R F A C E F E T C H E R ******** */
906 
920  public static interface Fetcher
921  {
929  public abstract Object getObject();
930  } // end inner interface Fetcher
931 
932 
933 
934  } // end class TransferableObject
935 
936 
937 
938 
939 
940 } // end class FileDrop
abstract void filesDropped(java.io.File[] files)
boolean isDataFlavorSupported(java.awt.datatransfer.DataFlavor flavor)
Definition: FileDrop.java:890
TransferableObject(Class dataClass, Fetcher fetcher)
Definition: FileDrop.java:805
java.awt.datatransfer.DataFlavor getCustomDataFlavor()
Definition: FileDrop.java:818
java.awt.datatransfer.DataFlavor[] getTransferDataFlavors()
Definition: FileDrop.java:836
FileDrop(final java.awt.Component c, final javax.swing.border.Border dragBorder, final boolean recursive, final Listener listener)
Definition: FileDrop.java:199
FileDrop(final java.awt.Component c, final boolean recursive, final Listener listener)
Definition: FileDrop.java:95
FileDrop(final java.io.PrintStream out, final java.awt.Component c, final javax.swing.border.Border dragBorder, final Listener listener)
Definition: FileDrop.java:227
FileDrop(final java.awt.Component c, final Listener listener)
Definition: FileDrop.java:72
FileDrop(final java.io.PrintStream out, final java.awt.Component c, final javax.swing.border.Border dragBorder, final boolean recursive, final Listener listener)
Definition: FileDrop.java:258
FileDrop(final java.awt.Component c, final javax.swing.border.Border dragBorder, final Listener listener)
Definition: FileDrop.java:173
FileDrop(final java.io.PrintStream out, final java.awt.Component c, final Listener listener)
Definition: FileDrop.java:120
Object getTransferData(java.awt.datatransfer.DataFlavor flavor)
Definition: FileDrop.java:864
Event(java.io.File[] files, Object source)
Definition: FileDrop.java:663
FileDrop(final java.io.PrintStream out, final java.awt.Component c, final boolean recursive, final Listener listener)
Definition: FileDrop.java:150