aead340498a079835c00f472c9277bbd239f760e
[debian/jabref.git] / src / java / net / sf / jabref / gui / FileListEditor.java
1 package net.sf.jabref.gui;
2
3 import net.sf.jabref.*;
4 import net.sf.jabref.groups.EntryTableTransferHandler;
5 import net.sf.jabref.undo.NamedCompound;
6 import net.sf.jabref.undo.UndoableFieldChange;
7 import net.sf.jabref.external.*;
8
9 import javax.swing.*;
10 import java.awt.*;
11 import java.awt.dnd.DnDConstants;
12 import java.awt.datatransfer.Transferable;
13 import java.awt.datatransfer.DataFlavor;
14 import java.awt.datatransfer.UnsupportedFlavorException;
15 import java.awt.event.*;
16 import java.util.*;
17 import java.util.List;
18 import java.io.File;
19 import java.io.IOException;
20 import java.net.URL;
21
22 import com.jgoodies.forms.builder.DefaultFormBuilder;
23 import com.jgoodies.forms.layout.FormLayout;
24
25 /**
26  * Created by Morten O. Alver 2007.02.22
27  */
28 public class FileListEditor extends JTable implements FieldEditor,
29         DownloadExternalFile.DownloadCallback {
30
31     FieldNameLabel label;
32     FileListEntryEditor editor = null;
33     private JabRefFrame frame;
34     private MetaData metaData;
35     private String fieldName;
36     private EntryEditor entryEditor;
37     private JPanel panel;
38     private FileListTableModel tableModel;
39     private JScrollPane sPane;
40     private JButton add, remove, up, down, auto, download;
41     private JPopupMenu menu = new JPopupMenu();
42     private JMenuItem item = new JMenuItem(Globals.lang("Open"));
43
44
45
46     public FileListEditor(JabRefFrame frame, MetaData metaData, String fieldName, String content,
47                           EntryEditor entryEditor) {
48         this.frame = frame;
49         this.metaData = metaData;
50         this.fieldName = fieldName;
51         this.entryEditor = entryEditor;
52         label = new FieldNameLabel(" " + Util.nCase(fieldName) + " ");
53         tableModel = new FileListTableModel();
54         setText(content);
55         setModel(tableModel);
56         sPane = new JScrollPane(this);
57         setTableHeader(null);
58         addMouseListener(new TableClickListener());
59
60         add = new JButton(GUIGlobals.getImage("add"));
61         add.setToolTipText(Globals.lang("New file link (INSERT)"));
62         remove = new JButton(GUIGlobals.getImage("remove"));
63         remove.setToolTipText(Globals.lang("Remove file link (DELETE)"));
64         up = new JButton(GUIGlobals.getImage("up"));
65
66         down = new JButton(GUIGlobals.getImage("down"));
67         auto = new JButton(Globals.lang("Auto"));
68         download = new JButton(Globals.lang("Download"));
69         add.setMargin(new Insets(0,0,0,0));
70         remove.setMargin(new Insets(0,0,0,0));
71         up.setMargin(new Insets(0,0,0,0));
72         down.setMargin(new Insets(0,0,0,0));
73         add.addActionListener(new ActionListener() {
74             public void actionPerformed(ActionEvent e) {
75                 addEntry();
76             }
77         });
78         remove.addActionListener(new ActionListener() {
79             public void actionPerformed(ActionEvent e) {
80                 removeEntries();
81             }
82         });
83         up.addActionListener(new ActionListener() {
84             public void actionPerformed(ActionEvent e) {
85                 moveEntry(-1);
86             }
87         });
88         down.addActionListener(new ActionListener() {
89             public void actionPerformed(ActionEvent e) {
90                 moveEntry(1);
91             }
92         });
93         auto.addActionListener(new ActionListener() {
94             public void actionPerformed(ActionEvent e) {
95                 autoSetLinks();
96             }
97         });
98         download.addActionListener(new ActionListener() {
99             public void actionPerformed(ActionEvent e) {
100                 downloadFile();
101             }
102         });
103         DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout
104                 ("fill:pref,1dlu,fill:pref,1dlu,fill:pref", "fill:pref,fill:pref"));
105         builder.append(up);
106         builder.append(add);
107         builder.append(auto);
108         builder.append(down);
109         builder.append(remove);
110         builder.append(download);        
111         panel = new JPanel();
112         panel.setLayout(new BorderLayout());
113         panel.add(sPane, BorderLayout.CENTER);
114         panel.add(builder.getPanel(), BorderLayout.EAST);
115
116         TransferHandler th = new FileListEditorTransferHandler();
117         setTransferHandler(th);
118         panel.setTransferHandler(th);
119
120         // Add an input/action pair for deleting entries:
121         getInputMap().put(KeyStroke.getKeyStroke("DELETE"), "delete");
122         getActionMap().put("delete", new AbstractAction() {
123             public void actionPerformed(ActionEvent actionEvent) {
124                 int row = getSelectedRow();
125                 removeEntries();
126                 row = Math.min(row, getRowCount()-1);
127                 if (row >= 0)
128                     setRowSelectionInterval(row, row);
129             }
130         });
131
132         // Add an input/action pair for inserting an entry:
133         getInputMap().put(KeyStroke.getKeyStroke("INSERT"), "insert");
134         getActionMap().put("insert", new AbstractAction() {
135
136             public void actionPerformed(ActionEvent actionEvent) {
137                 addEntry();
138             }
139         });
140
141         menu.add(item);
142         item.addActionListener(new ActionListener() {
143             public void actionPerformed(ActionEvent actionEvent) {
144                 openSelectedFile();
145             }
146         });
147     }
148
149     private void openSelectedFile() {
150         int row = getSelectedRow();
151         if (row >= 0) {
152             FileListEntry entry = tableModel.getEntry(row);
153             try {
154                 Util.openExternalFileAnyFormat(metaData, entry.getLink(), entry.getType());
155             } catch (IOException e) {
156                 e.printStackTrace();
157             }
158         }
159     }
160
161
162     public String getFieldName() {
163         return fieldName;
164     }
165
166     /*
167       * Returns the component to be added to a container. Might be a JScrollPane
168     * or the component itself.
169     */
170     public JComponent getPane() {
171         return panel;
172     }
173
174     /*
175      * Returns the text component itself.
176     */
177     public JComponent getTextComponent() {
178         return this;
179     }
180
181     public JLabel getLabel() {
182         return label;
183     }
184
185     public void setLabelColor(Color c) {
186         label.setForeground(c);
187     }
188
189     public String getText() {
190         return tableModel.getStringRepresentation();
191     }
192
193     public void setText(String newText) {
194         tableModel.setContent(newText);
195     }
196
197
198     public void append(String text) {
199
200     }
201
202     public void updateFont() {
203
204     }
205
206     public void paste(String textToInsert) {
207
208     }
209
210     public String getSelectedText() {
211         return null;
212     }
213
214     private void addEntry(String initialLink) {
215         int row = getSelectedRow();
216         if (row == -1)
217             row = 0;
218         FileListEntry entry = new FileListEntry("", initialLink, null);
219         if (editListEntry(entry))
220             tableModel.addEntry(row, entry);
221         entryEditor.updateField(this);
222     }
223
224     private void addEntry() {
225         addEntry("");
226     }
227
228     /**
229      * Add the listed files, prompting the user with the entry editor in each case.
230      * @param files A list of File objects.
231      */
232     private void addAll(List files) {
233         for (Iterator i = files.iterator(); i.hasNext();) {
234             File file = (File)i.next();
235             String fileName = file.getAbsolutePath();
236             FileListEntry entry = new FileListEntry("", fileName, null);
237             if (editListEntry(entry))
238                     tableModel.addEntry(tableModel.getRowCount(), entry);
239         }
240         entryEditor.updateField(this);
241     }
242
243     private void removeEntries() {
244         int[] rows = getSelectedRows();
245         if (rows != null)
246             for (int i = rows.length-1; i>=0; i--) {
247                 tableModel.removeEntry(rows[i]);
248             }
249         entryEditor.updateField(this);
250     }
251
252     private void moveEntry(int i) {
253         int[] sel = getSelectedRows();
254         if ((sel.length != 1) || (tableModel.getRowCount() < 2))
255             return;
256         int toIdx = sel[0]+i;
257         if (toIdx >= tableModel.getRowCount())
258             toIdx -= tableModel.getRowCount();
259         if (toIdx < 0)
260             toIdx += tableModel.getRowCount();
261         FileListEntry entry = tableModel.getEntry(sel[0]);
262         tableModel.removeEntry(sel[0]);
263         tableModel.addEntry(toIdx, entry);
264         entryEditor.updateField(this);
265         setRowSelectionInterval(toIdx, toIdx);
266     }
267
268     private boolean editListEntry(FileListEntry entry) {
269         if (editor == null) {
270             editor = new FileListEntryEditor(frame, entry, false, metaData);
271         }
272         else
273             editor.setEntry(entry);
274         editor.setVisible(true);
275         if (editor.okPressed())
276             tableModel.fireTableDataChanged();
277         entryEditor.updateField(this);
278         return editor.okPressed();
279     }
280
281     private void autoSetLinks() {
282         auto.setEnabled(false);
283         BibtexEntry entry = entryEditor.getEntry();
284         int tableSize = tableModel.getRowCount();
285         JDialog diag = new JDialog(frame, true);
286         autoSetLinks(entry, tableModel, metaData, new ActionListener() {
287             public void actionPerformed(ActionEvent e) {
288                 auto.setEnabled(true);
289                 if (e.getID() > 0) {
290                     entryEditor.updateField(FileListEditor.this);
291                     frame.output(Globals.lang("Finished autosetting external links."));
292                 }
293                 else frame.output(Globals.lang("Finished autosetting external links.")
294                     +" "+Globals.lang("No files found."));
295             }
296         }, diag);
297
298     }
299
300     /**
301      * Automatically add links for this set of entries, based on the globally stored list of
302      * external file types. The entries are modified, and corresponding UndoEdit elements
303      * added to the NamedCompound given as argument. Furthermore, all entries which are modified
304      * are added to the Set of entries given as an argument.
305      *
306      * The entries' bibtex keys must have been set - entries lacking key are ignored.
307      * The operation is done in a new thread, which is returned for the caller to wait for
308      * if needed.
309      *
310      * @param entries A collection of BibtexEntry objects to find links for.
311      * @param ce A NamedCompound to add UndoEdit elements to.
312      * @param changedEntries A Set of BibtexEntry objects to which all modified entries is added.
313      * @return the thread performing the autosetting
314      */
315     public static Thread autoSetLinks(final Collection<BibtexEntry> entries, final NamedCompound ce,
316                                       final Set<BibtexEntry> changedEntries,
317                                       final ArrayList<File> dirs) {
318
319         final ExternalFileType[] types = Globals.prefs.getExternalFileTypeSelection();
320         final JLabel label = new JLabel(Globals.lang("Searching for files"));
321         Runnable r = new Runnable() {
322
323             public void run() {
324                 boolean foundAny = false;
325                 ExternalFileType[] types = Globals.prefs.getExternalFileTypeSelection();
326                 Collection<String> extensions = new ArrayList<String>();
327                 for (int i = 0; i < types.length; i++) {
328                     final ExternalFileType type = types[i];
329                     extensions.add(type.getExtension());
330                 }
331                 // Run the search operation:
332                 Map<BibtexEntry, java.util.List<File>> result =
333                         Util.findAssociatedFiles(entries, extensions, dirs);
334
335                 // Iterate over the entries:
336                 for (Iterator<BibtexEntry> i=result.keySet().iterator(); i.hasNext();) {
337                     BibtexEntry anEntry = i.next();
338                     FileListTableModel tableModel = new FileListTableModel();
339                     Object oldVal = anEntry.getField(GUIGlobals.FILE_FIELD);
340                     if (oldVal != null)
341                         tableModel.setContent((String)oldVal);
342                     List<File> files = result.get(anEntry);
343                     for (File f : files) {
344                         f = relativizePath(f, dirs);
345                         boolean alreadyHas = false;
346                         //System.out.println("File: "+f.getPath());
347                         for (int j = 0; j < tableModel.getRowCount(); j++) {
348                             FileListEntry existingEntry = tableModel.getEntry(j);
349                             //System.out.println("Comp: "+existingEntry.getLink());
350                             if (new File(existingEntry.getLink()).equals(f)) {
351                                 alreadyHas = true;
352                                 break;
353                             }
354                         }
355                         if (!alreadyHas) {
356                             int index = f.getPath().lastIndexOf('.');
357                             if ((index >= 0) && (index < f.getPath().length()-1)) {
358                                 ExternalFileType type = Globals.prefs.getExternalFileTypeByExt
359                                     (f.getPath().substring(index+1));
360                                 FileListEntry flEntry = new FileListEntry(f.getName(), f.getPath(), type);
361                                 tableModel.addEntry(tableModel.getRowCount(), flEntry);
362                             } else {
363                                 FileListEntry flEntry = new FileListEntry(f.getName(), f.getPath(),
364                                         new UnknownExternalFileType(""));
365                                 tableModel.addEntry(tableModel.getRowCount(), flEntry);
366                             }
367                             String newVal = tableModel.getStringRepresentation();
368                             if (newVal.length() == 0)
369                                 newVal = null;
370                             UndoableFieldChange change = new UndoableFieldChange(anEntry,
371                                     GUIGlobals.FILE_FIELD, oldVal, newVal);
372                             ce.addEdit(change);
373                             anEntry.setField(GUIGlobals.FILE_FIELD, newVal);
374                             changedEntries.add(anEntry);
375                         }
376                     }
377                 }
378             }
379         };
380         Thread t = new Thread(r);
381         t.start();
382         return t;
383     }
384
385
386     /**
387      * Automatically add links for this entry to the table model given as an argument, based on
388      * the globally stored list of external file types. The entry itself is not modified. The entry's
389      * bibtex key must have been set.
390      * The operation is done in a new thread, which is returned for the caller to wait for
391      * if needed.
392      *
393      * @param entry The BibtexEntry to find links for.
394      * @param tableModel The table model to insert links into. Already existing links are not duplicated or removed.
395      * @param metaData The MetaData providing the relevant file directory, if any.
396      * @param callback An ActionListener that is notified (on the event dispatch thread) when the search is
397      *  finished. The ActionEvent has id=0 if no new links were added, and id=1 if one or more links were added.
398      *  This parameter can be null, which means that no callback will be notified.
399      * @param diag An instantiated modal JDialog which will be used to display the progress of the autosetting.
400      *      This parameter can be null, which means that no progress update will be shown.
401      * @return the thread performing the autosetting
402      */
403     public static Thread autoSetLinks(final BibtexEntry entry, final FileListTableModel tableModel,
404                                       final MetaData metaData, final ActionListener callback,
405                                       final JDialog diag) {
406
407         final Collection<BibtexEntry> entries = new ArrayList<BibtexEntry>();
408         entries.add(entry);
409         final ExternalFileType[] types = Globals.prefs.getExternalFileTypeSelection();
410         final JProgressBar prog = new JProgressBar(JProgressBar.HORIZONTAL, types.length-1);
411         prog.setIndeterminate(true);
412         prog.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
413         final JLabel label = new JLabel(Globals.lang("Searching for files"));
414         if (diag != null) {
415             diag.setTitle(Globals.lang("Autosetting links"));
416             diag.getContentPane().add(prog, BorderLayout.CENTER);
417             diag.getContentPane().add(label, BorderLayout.SOUTH);
418
419             diag.pack();
420             diag.setLocationRelativeTo(diag.getParent());
421         }
422         Runnable r = new Runnable() {
423
424             public void run() {
425                 boolean foundAny = false;
426                 ExternalFileType[] types = Globals.prefs.getExternalFileTypeSelection();
427                 ArrayList<File> dirs = new ArrayList<File>();
428                 if (metaData.getFileDirectory(GUIGlobals.FILE_FIELD) != null)
429                     dirs.add(new File(metaData.getFileDirectory(GUIGlobals.FILE_FIELD)));
430                 Collection<String> extensions = new ArrayList<String>();
431                 for (int i = 0; i < types.length; i++) {
432                     final ExternalFileType type = types[i];
433                     extensions.add(type.getExtension());
434                 }
435                 // Run the search operation:
436                 Map<BibtexEntry, java.util.List<File>> result =
437                         Util.findAssociatedFiles(entries, extensions, dirs);
438
439                 // Iterate over the entries:
440                 for (Iterator<BibtexEntry> i=result.keySet().iterator(); i.hasNext();) {
441                     BibtexEntry anEntry = i.next();
442                     List<File> files = result.get(anEntry);
443                     for (File f : files) {
444                                 f = relativizePath(f, dirs);
445                         boolean alreadyHas = false;
446                         for (int j = 0; j < tableModel.getRowCount(); j++) {
447                             FileListEntry existingEntry = tableModel.getEntry(j);
448                             if (new File(existingEntry.getLink()).equals(f)) {
449                                 alreadyHas = true;
450                                 break;
451                             }
452                         }
453                         if (!alreadyHas) {
454                             int index = f.getPath().lastIndexOf('.');
455                             if ((index >= 0) && (index < f.getPath().length()-1)) {
456                                 ExternalFileType type = Globals.prefs.getExternalFileTypeByExt
457                                     (f.getPath().substring(index+1));
458                                 FileListEntry flEntry = new FileListEntry(f.getName(), f.getPath(), type);
459                                 tableModel.addEntry(tableModel.getRowCount(), flEntry);
460                                 foundAny = true;
461                             } else {
462                                 FileListEntry flEntry = new FileListEntry(f.getName(), f.getPath(),
463                                         new UnknownExternalFileType(""));
464                                 tableModel.addEntry(tableModel.getRowCount(), flEntry);
465                                 foundAny = true;
466                             }
467                         }
468                     }
469                 }
470                 final int id = foundAny ? 1 : 0;
471                 SwingUtilities.invokeLater(new Runnable() {
472                     public void run() {
473                         if (diag != null)
474                             diag.dispose();
475                         if (callback != null)
476                             callback.actionPerformed(new ActionEvent(this, id, ""));
477                     }
478                 });
479
480             }
481         };
482         Thread t = new Thread(r);
483         t.start();
484         if (diag != null) {
485             diag.setVisible(true);
486         }
487         return t;
488     }
489
490     /**
491      * If the file is below one of the directories in a list, return a File specifying
492      * a path relative to that directory.
493      */
494     public static File relativizePath(File f, ArrayList<File> dirs) {
495         String pth = f.getPath();
496         for (File dir : dirs) {
497             if (pth.startsWith(dir.getPath())) {
498                 String subs = pth.substring(dir.getPath().length());
499                 if ((subs.length() > 0) && ((subs.charAt(0) == '/') || (subs.charAt(0) == '\\')))
500                     subs = subs.substring(1);
501             return new File(subs);          
502             }
503         }
504         return f;
505     }
506
507
508     /**
509      * Run a file download operation.
510      */
511     private void downloadFile() {
512         String bibtexKey = entryEditor.getEntry().getCiteKey();
513         if (bibtexKey == null) {
514             int answer = JOptionPane.showConfirmDialog(frame,
515                     Globals.lang("This entry has no BibTeX key. Generate key now?"),
516                     Globals.lang("Download file"), JOptionPane.OK_CANCEL_OPTION,
517                     JOptionPane.QUESTION_MESSAGE);
518             if (answer == JOptionPane.OK_OPTION) {
519                 ActionListener l = entryEditor.generateKeyAction;
520                 l.actionPerformed(null);
521                 bibtexKey = entryEditor.getEntry().getCiteKey();
522             }
523         }
524         DownloadExternalFile def = new DownloadExternalFile(frame,
525                 frame.basePanel().metaData(), bibtexKey);
526         try {
527             def.download(this);
528         } catch (IOException ex) {
529             ex.printStackTrace();
530         }
531     }
532
533     /**
534      * This is the callback method that the DownloadExternalFile class uses to report the result
535      * of a download operation. This call may never come, if the user cancelled the operation.
536      * @param file The FileListEntry linking to the resulting local file.
537      */
538     public void downloadComplete(FileListEntry file) {
539         tableModel.addEntry(tableModel.getRowCount(), file);
540         entryEditor.updateField(this);
541     }
542
543     class TableClickListener extends MouseAdapter {
544
545         public void mouseClicked(MouseEvent e) {
546             if ((e.getButton() == MouseEvent.BUTTON1) && (e.getClickCount() == 2)) {
547                 int row = rowAtPoint(e.getPoint());
548                 if (row >= 0) {
549                     FileListEntry entry = tableModel.getEntry(row);
550                     editListEntry(entry);
551                 }
552             }
553             else if (e.isPopupTrigger())
554                 processPopupTrigger(e);
555         }
556
557
558         public void mousePressed(MouseEvent e) {
559             if (e.isPopupTrigger())
560                 processPopupTrigger(e);
561         }
562         public void mouseReleased(MouseEvent e) {
563             if (e.isPopupTrigger())
564                 processPopupTrigger(e);
565         }
566
567
568         private void processPopupTrigger(MouseEvent e) {
569             int row = rowAtPoint(e.getPoint());
570             if (row >= 0) {
571                 setRowSelectionInterval(row, row);
572                 menu.show(FileListEditor.this, e.getX(), e.getY());
573             }
574         }
575     }
576
577
578     class FileListEditorTransferHandler extends TransferHandler {
579
580         protected DataFlavor urlFlavor;
581         protected DataFlavor stringFlavor;
582
583         public FileListEditorTransferHandler() {
584             stringFlavor = DataFlavor.stringFlavor;
585             try {
586                 urlFlavor = new DataFlavor("application/x-java-url; class=java.net.URL");
587             } catch (ClassNotFoundException e) {
588                 Globals.logger("Unable to configure drag and drop for file link table");
589                 e.printStackTrace();
590             }
591         }
592         /**
593          * Overriden to indicate which types of drags are supported (only LINK).
594          *
595          * @override
596          */
597         public int getSourceActions(JComponent c) {
598             return DnDConstants.ACTION_LINK;
599         }
600
601         /*public boolean importData(TransferSupport transferSupport) {
602
603             return importData(FileListEditor.this, transferSupport.getTransferable());
604         }*/
605
606         public boolean importData(JComponent comp, Transferable t) {
607             // If the drop target is the main table, we want to record which
608             // row the item was dropped on, to identify the entry if needed:
609             int dropRow = -1;
610             if (comp instanceof JTable) {
611                 dropRow = ((JTable) comp).getSelectedRow();
612             }
613
614             try {
615                 
616                 List files = null;
617                 // This flavor is used for dragged file links in Windows:
618                 if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
619                     // JOptionPane.showMessageDialog(null, "Received
620                     // javaFileListFlavor");
621                     files = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
622                 }
623
624                 if (t.isDataFlavorSupported(urlFlavor)) {
625                     URL dropLink = (URL) t.getTransferData(urlFlavor);
626                     System.out.println("URL: "+dropLink);
627                     //return handleDropTransfer(dropLink, dropRow);
628                 }
629
630                 // This is used when one or more files are pasted from the file manager
631                 // under Gnome. The data consists of the file paths, one file per line:
632                 if (t.isDataFlavorSupported(stringFlavor)) {
633                     String dropStr = (String)t.getTransferData(stringFlavor);
634                     files = EntryTableTransferHandler.getFilesFromDraggedFilesString(dropStr);
635                 }
636
637                         if (files != null) {
638                             final List theFiles = files;
639                     SwingUtilities.invokeLater(new Runnable() {
640                         public void run() {
641                             //addAll(files);
642                             for (Iterator i=theFiles.iterator(); i.hasNext();) {
643                                             File f = (File)i.next();
644                                 // Find the file's extension, if any:
645                                 String name = f.getAbsolutePath();
646                                 String extension = "";
647                                 ExternalFileType fileType = null;
648                                 int index = name.lastIndexOf('.');
649                                 if ((index >= 0) && (index < name.length())) {
650                                     extension = name.substring(index + 1).toLowerCase();
651                                     fileType = Globals.prefs.getExternalFileTypeByExt(extension);
652                                 }
653                                 if (fileType != null) {
654                                     DroppedFileHandler dfh = new DroppedFileHandler(frame, frame.basePanel());
655                                     dfh.handleDroppedfile(name, fileType, true, entryEditor.getEntry());
656                                 }
657                             }
658                         }
659                     });
660                     return true;
661                 }
662
663             } catch (IOException ioe) {
664                 System.err.println("failed to read dropped data: " + ioe.toString());
665             } catch (UnsupportedFlavorException ufe) {
666                 System.err.println("drop type error: " + ufe.toString());
667             }
668
669             // all supported flavors failed
670             System.err.println("can't transfer input: ");
671             DataFlavor inflavs[] = t.getTransferDataFlavors();
672             for (int i = 0; i < inflavs.length; i++) {
673                 System.out.println("  " + inflavs[i].toString());
674             }
675
676             return false;
677         }
678
679         /**
680          * This method is called to query whether the transfer can be imported.
681          *
682          * Will return true for urls, strings, javaFileLists
683          *
684          * @override
685          */
686         public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
687
688             // accept this if any input flavor matches any of our supported flavors
689             for (int i = 0; i < transferFlavors.length; i++) {
690                 DataFlavor inflav = transferFlavors[i];
691                 if (inflav.match(urlFlavor) || inflav.match(stringFlavor)
692                     || inflav.match(DataFlavor.javaFileListFlavor))
693                     return true;
694             }
695
696             // nope, never heard of this type
697             return false;
698         }
699
700     }
701 }