OSDN Git Service

コンフィグクラスパッケージ移動
[coroid/inqubus.git] / frontend / src / yukihane / inqubus / gui / MainFrame.java
1 /*
2  * MainFrame.java
3  *
4  * Created on 2011/05/28, 18:14:51
5  */
6 package yukihane.inqubus.gui;
7
8 import java.awt.Image;
9 import java.awt.ItemSelectable;
10 import java.awt.Toolkit;
11 import java.awt.datatransfer.DataFlavor;
12 import java.awt.datatransfer.Transferable;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.ItemEvent;
16 import java.awt.event.KeyEvent;
17 import java.io.File;
18 import java.io.FilenameFilter;
19 import java.net.URL;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.List;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27 import javax.swing.JButton;
28 import javax.swing.JMenu;
29 import javax.swing.JMenuBar;
30 import javax.swing.JMenuItem;
31 import javax.swing.JTextField;
32 import javax.swing.KeyStroke;
33 import javax.swing.TransferHandler;
34 import saccubus.MainFrame_AboutBox;
35 import yukihane.inqubus.Config;
36 import yukihane.inqubus.model.Target;
37 import yukihane.inqubus.model.TargetsTableModel;
38
39 /**
40  *
41  * @author yuki
42  */
43 public class MainFrame extends javax.swing.JFrame {
44
45     private static final long serialVersionUID = 1L;
46     private static final Logger logger = Logger.getLogger(MainFrame.class.getName());
47     private final TargetsTableModel targetModel = new TargetsTableModel();
48
49     /** Creates new form MainFrame */
50     public MainFrame() {
51         initComponents();
52         initInputPanel();
53         jPanel1.setTransferHandler(new DownloadListTransferHandler());
54         jTable1.setTransferHandler(new TableTransferHandler());
55     }
56
57     /** This method is called from within the constructor to
58      * initialize the form.
59      * WARNING: Do NOT modify this code. The content of this method is
60      * always regenerated by the Form Editor.
61      */
62     @SuppressWarnings("unchecked")
63     // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
64     private void initComponents() {
65         final URL url = MainFrame_AboutBox.class.getResource("icon.png");
66         final Image icon1 = Toolkit.getDefaultToolkit().createImage(url);
67         final URL url32 = MainFrame_AboutBox.class.getResource("icon32.png");
68         final Image icon2 = Toolkit.getDefaultToolkit().createImage(url32);
69         final List<Image> images = new ArrayList<Image>(2);
70         images.add(icon1);
71         images.add(icon2);
72         setIconImages(images);
73
74         jPanel1 = new javax.swing.JPanel();
75         jScrollPane1 = new javax.swing.JScrollPane();
76         jTable1 = new javax.swing.JTable();
77         jPanel2 = new javax.swing.JPanel();
78         jButton2 = new javax.swing.JButton();
79         jButton3 = new javax.swing.JButton();
80         jButton4 = new javax.swing.JButton();
81         jPanel3 = new javax.swing.JPanel();
82         idLabel = new javax.swing.JLabel();
83         idField = new javax.swing.JTextField();
84         movieLabel = new javax.swing.JLabel();
85         useMovieLocalCheckBox = new javax.swing.JCheckBox();
86         movieFileField = new javax.swing.JTextField();
87         movieFileSelectButton = new javax.swing.JButton();
88         commentLabel = new javax.swing.JLabel();
89         useCommentLocalCheckBox = new javax.swing.JCheckBox();
90         commentFileField = new javax.swing.JTextField();
91         commentFileSelectButton = new javax.swing.JButton();
92         outputLabel = new javax.swing.JLabel();
93         outputConvertCheckBox = new javax.swing.JCheckBox();
94         outputFileField = new javax.swing.JTextField();
95         applyButton = new javax.swing.JButton();
96
97         setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
98
99         jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
100
101         jTable1.setModel(targetModel);
102         jTable1.setDropMode(javax.swing.DropMode.INSERT_ROWS);
103         jScrollPane1.setViewportView(jTable1);
104
105         jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
106
107         jButton2.setText("開始");
108
109         jButton3.setText("停止");
110
111         jButton4.setText("選択解除");
112
113         javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
114         jPanel2.setLayout(jPanel2Layout);
115         jPanel2Layout.setHorizontalGroup(
116             jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
117             .addGroup(jPanel2Layout.createSequentialGroup()
118                 .addContainerGap()
119                 .addComponent(jButton2)
120                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
121                 .addComponent(jButton3)
122                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 250, Short.MAX_VALUE)
123                 .addComponent(jButton4)
124                 .addContainerGap())
125         );
126         jPanel2Layout.setVerticalGroup(
127             jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
128             .addGroup(jPanel2Layout.createSequentialGroup()
129                 .addContainerGap()
130                 .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
131                     .addComponent(jButton2)
132                     .addComponent(jButton3)
133                     .addComponent(jButton4))
134                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
135         );
136
137         jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
138
139         idLabel.setText("ID");
140
141         idField.addFocusListener(new java.awt.event.FocusAdapter() {
142
143             public void focusLost(java.awt.event.FocusEvent evt) {
144                 idFieldFocusLost(evt);
145             }
146         });
147
148         movieLabel.setText("動画");
149
150         useMovieLocalCheckBox.setText("local");
151         useMovieLocalCheckBox.addItemListener(new java.awt.event.ItemListener() {
152
153             public void itemStateChanged(java.awt.event.ItemEvent evt) {
154                 useMovieLocalCheckBoxItemStateChanged(evt);
155             }
156         });
157
158         movieFileSelectButton.setText("...");
159
160         commentLabel.setText("コメント");
161
162         useCommentLocalCheckBox.setText("local");
163         useCommentLocalCheckBox.addItemListener(new java.awt.event.ItemListener() {
164
165             public void itemStateChanged(java.awt.event.ItemEvent evt) {
166                 useMovieLocalCheckBoxItemStateChanged(evt);
167             }
168         });
169
170         commentFileSelectButton.setText("...");
171
172         outputLabel.setText("出力");
173
174         outputConvertCheckBox.setText("変換");
175         outputConvertCheckBox.addItemListener(new java.awt.event.ItemListener() {
176
177             public void itemStateChanged(java.awt.event.ItemEvent evt) {
178                 outputConvertCheckBoxItemStateChanged(evt);
179             }
180         });
181
182         applyButton.setText("適用");
183
184         javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
185         jPanel3.setLayout(jPanel3Layout);
186         jPanel3Layout.setHorizontalGroup(
187             jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
188             .addGroup(jPanel3Layout.createSequentialGroup()
189                 .addContainerGap()
190                 .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
191                     .addGroup(jPanel3Layout.createSequentialGroup()
192                         .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
193                             .addComponent(commentLabel)
194                             .addComponent(movieLabel)
195                             .addComponent(idLabel)
196                             .addComponent(outputLabel))
197                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
198                         .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
199                             .addGroup(jPanel3Layout.createSequentialGroup()
200                                 .addComponent(useMovieLocalCheckBox)
201                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
202                                 .addComponent(movieFileField, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE)
203                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
204                                 .addComponent(movieFileSelectButton))
205                             .addComponent(idField, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
206                             .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
207                                 .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
208                                     .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel3Layout.createSequentialGroup()
209                                         .addComponent(outputConvertCheckBox)
210                                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
211                                         .addComponent(outputFileField, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
212                                     .addGroup(jPanel3Layout.createSequentialGroup()
213                                         .addComponent(useCommentLocalCheckBox)
214                                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
215                                         .addComponent(commentFileField, javax.swing.GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE)))
216                                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
217                                 .addComponent(commentFileSelectButton))))
218                     .addComponent(applyButton, javax.swing.GroupLayout.Alignment.TRAILING))
219                 .addContainerGap())
220         );
221         jPanel3Layout.setVerticalGroup(
222             jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
223             .addGroup(jPanel3Layout.createSequentialGroup()
224                 .addContainerGap()
225                 .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
226                     .addComponent(idField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
227                     .addComponent(idLabel))
228                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
229                 .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
230                     .addComponent(movieLabel)
231                     .addComponent(movieFileField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
232                     .addComponent(movieFileSelectButton)
233                     .addComponent(useMovieLocalCheckBox))
234                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
235                 .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
236                     .addComponent(commentLabel)
237                     .addComponent(commentFileField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
238                     .addComponent(commentFileSelectButton)
239                     .addComponent(useCommentLocalCheckBox))
240                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
241                 .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
242                     .addComponent(outputLabel)
243                     .addComponent(outputFileField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
244                     .addComponent(outputConvertCheckBox))
245                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
246                 .addComponent(applyButton)
247                 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
248         );
249
250         javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
251         jPanel1.setLayout(jPanel1Layout);
252         jPanel1Layout.setHorizontalGroup(
253             jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
254             .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
255                 .addContainerGap()
256                 .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
257                     .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
258                     .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 480, Short.MAX_VALUE)
259                     .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
260                 .addContainerGap())
261         );
262         jPanel1Layout.setVerticalGroup(
263             jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
264             .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
265                 .addContainerGap()
266                 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
267                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
268                 .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
269                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
270                 .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
271                 .addGap(24, 24, 24))
272         );
273
274
275         JMenuBar menuBar = initMenuBar();
276         setJMenuBar(menuBar);
277
278         javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
279         getContentPane().setLayout(layout);
280         layout.setHorizontalGroup(
281             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
282             .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
283         );
284         layout.setVerticalGroup(
285             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
286             .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
287         );
288
289         pack();
290     }// </editor-fold>//GEN-END:initComponents
291
292     private File searchFileMatchId(final File dir, final String id) throws UnsupportedOperationException {
293         // TODO 候補は複数返すようにして、その後の対処は呼び出しもとで行ってもらった方が良いかも
294         if (id.isEmpty()) {
295             return null;
296         }
297
298         final File[] lists = dir.listFiles(new FilenameFilter() {
299
300             final Pattern pattern = Pattern.compile(id + "\\D");
301
302             @Override
303             public boolean accept(File dir, String name) {
304                 return pattern.matcher(name).find();
305             }
306         });
307
308         if (lists.length == 1) {
309             return lists[0];
310         } else if (lists.length > 1) {
311             throw new UnsupportedOperationException();
312         } else {
313             return null;
314         }
315     }
316
317     private void useMovieLocalCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_useMovieLocalCheckBoxItemStateChanged
318         final Config p = Config.INSTANCE;
319
320         final ItemSelectable source = evt.getItemSelectable();
321
322         JButton btn;
323         JTextField field;
324         File dir;
325         if (source == useMovieLocalCheckBox) {
326             btn = movieFileSelectButton;
327             field = movieFileField;
328             dir = new File(p.getVideoDir());
329         } else {
330             btn = commentFileSelectButton;
331             field = commentFileField;
332             dir = new File(p.getCommentDir());
333         }
334
335         final boolean useLocal = (evt.getStateChange() == ItemEvent.SELECTED);
336         btn.setEnabled(useLocal);
337
338         String text;
339         if (useLocal) {
340             final File f = searchFileMatchId(dir, idField.getText());
341             if (f != null) {
342                 text = f.getPath();
343             } else {
344                 text = "";
345             }
346         } else {
347             text = p.getVideoFileNamePattern();
348         }
349         field.setText(text);
350     }//GEN-LAST:event_useMovieLocalCheckBoxItemStateChanged
351
352     private void outputConvertCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_outputConvertCheckBoxItemStateChanged
353         final boolean convert = (evt.getStateChange() == ItemEvent.SELECTED);
354         outputFileField.setEnabled(convert);
355     }//GEN-LAST:event_outputConvertCheckBoxItemStateChanged
356
357     private void idFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_idFieldFocusLost
358         final Config p = Config.INSTANCE;
359         final String id = idField.getText();
360         if (id.isEmpty()) {
361             return;
362         }
363
364         if (useMovieLocalCheckBox.isSelected() && movieFileField.getText().isEmpty()) {
365             final File dir = new File(p.getVideoDir());
366             final File file = searchFileMatchId(dir, id);
367             if (file != null) {
368                 movieFileField.setText(file.getPath());
369             }
370         }
371
372         if (useCommentLocalCheckBox.isSelected() && commentFileField.getText().isEmpty()) {
373             final File dir = new File(p.getCommentDir());
374             final File file = searchFileMatchId(dir, id);
375             if (file != null) {
376                 commentFileField.setText(file.getPath());
377             }
378         }
379
380     }//GEN-LAST:event_idFieldFocusLost
381     // Variables declaration - do not modify//GEN-BEGIN:variables
382     private javax.swing.JButton applyButton;
383     private javax.swing.JTextField commentFileField;
384     private javax.swing.JButton commentFileSelectButton;
385     private javax.swing.JLabel commentLabel;
386     private javax.swing.JTextField idField;
387     private javax.swing.JLabel idLabel;
388     private javax.swing.JButton jButton2;
389     private javax.swing.JButton jButton3;
390     private javax.swing.JButton jButton4;
391     private javax.swing.JPanel jPanel1;
392     private javax.swing.JPanel jPanel2;
393     private javax.swing.JPanel jPanel3;
394     private javax.swing.JScrollPane jScrollPane1;
395     private javax.swing.JTable jTable1;
396     private javax.swing.JTextField movieFileField;
397     private javax.swing.JButton movieFileSelectButton;
398     private javax.swing.JLabel movieLabel;
399     private javax.swing.JCheckBox outputConvertCheckBox;
400     private javax.swing.JTextField outputFileField;
401     private javax.swing.JLabel outputLabel;
402     private javax.swing.JCheckBox useCommentLocalCheckBox;
403     private javax.swing.JCheckBox useMovieLocalCheckBox;
404     // End of variables declaration//GEN-END:variables
405
406     private void initInputPanel() {
407         idField.setText("");
408
409         final Config p = Config.INSTANCE;
410
411         final boolean movieLocal = p.getVideoUseLocal();
412         useMovieLocalCheckBox.setSelected(movieLocal);
413         movieFileSelectButton.setEnabled(movieLocal);
414         if (!movieLocal) {
415             movieFileField.setText(p.getVideoFileNamePattern());
416         }
417
418         final boolean commentLocal = p.getCommentUseLocal();
419         useCommentLocalCheckBox.setSelected(commentLocal);
420         commentFileSelectButton.setEnabled(commentLocal);
421         if (!commentLocal) {
422             commentFileField.setText(p.getCommentFileNamePattern());
423         }
424
425         final boolean convert = p.getOutputEnable();
426         outputConvertCheckBox.setSelected(convert);
427         outputFileField.setEnabled(convert);
428         outputFileField.setText(p.getOutputFileNamePattern());
429
430     }
431
432     private JMenuBar initMenuBar() {
433         final JMenuBar menuBar = new JMenuBar();
434
435         final JMenu mnFile = new JMenu("ファイル(F)");
436         menuBar.add(mnFile);
437
438         final JMenuItem itExit = new JMenuItem("終了(X)", KeyEvent.VK_X);
439         itExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
440         itExit.addActionListener(new ActionListener() {
441
442             @Override
443             public void actionPerformed(ActionEvent e) {
444                 throw new UnsupportedOperationException("Not supported yet.");
445             }
446         });
447         mnFile.add(itExit);
448
449         final JMenu mnTool = new JMenu("ツール(T)");
450         menuBar.add(mnTool);
451
452         final JMenuItem itOption = new JMenuItem("オプション(O)...", KeyEvent.VK_O);
453         // TODO ショートカットキー
454         itOption.addActionListener(new ActionListener() {
455
456             @Override
457             public void actionPerformed(ActionEvent e) {
458                 final yukihane.inqubus.gui.ConfigDialog dlg = new yukihane.inqubus.gui.ConfigDialog(MainFrame.this);
459                 dlg.setLocationRelativeTo(MainFrame.this);
460                 dlg.setModal(true);
461                 dlg.setVisible(true);
462             }
463         });
464         mnTool.add(itOption);
465
466         final JMenu mnHelp = new JMenu("ヘルプ(H)");
467         menuBar.add(mnHelp);
468
469         final JMenuItem itAbout = new JMenuItem("このソフトウェアについて(A)...", KeyEvent.VK_A);
470         itAbout.addActionListener(new ActionListener() {
471
472             @Override
473             public void actionPerformed(ActionEvent e) {
474                 MainFrame_AboutBox dlg = new MainFrame_AboutBox(MainFrame.this);
475                 dlg.pack();
476                 dlg.setLocationRelativeTo(MainFrame.this);
477                 dlg.setModal(true);
478                 dlg.setVisible(true);
479             }
480         });
481         mnHelp.add(itAbout);
482
483         return menuBar;
484     }
485
486     private class DownloadListTransferHandler extends TransferHandler {
487
488         private static final long serialVersionUID = 1L;
489         private final Pattern movieIdPattern = Pattern.compile("(\\w\\w\\d+)");
490
491         @Override
492         public boolean canImport(TransferHandler.TransferSupport support) {
493             Transferable transferable = support.getTransferable();
494             if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
495                     || transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
496                 return true;
497             }
498             return false;
499         }
500
501         @Override
502         public boolean importData(TransferHandler.TransferSupport support) {
503             try {
504                 Transferable transferable = support.getTransferable();
505                 if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
506                     @SuppressWarnings("unchecked")
507                     final List<File> data = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
508                     Collection<Target> targets = Target.from(data);
509                     targetModel.addTarget(targets);
510                 } else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
511                     String data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
512                     Matcher matcher = movieIdPattern.matcher(data);
513                     if (matcher.find()) {
514                         String movieId = matcher.group(1);
515                         Target target = Target.fromId(movieId);
516                         targetModel.addTarget(target);
517                     } else {
518                         return false;
519                     }
520
521                 }
522                 return false;
523             } catch (Exception e) {
524                 logger.log(Level.SEVERE, null, e);
525                 return false;
526             }
527         }
528     }
529
530     private class TableTransferHandler extends DownloadListTransferHandler {
531
532         private static final long serialVersionUID = 1L;
533
534         @Override
535         public boolean canImport(TransferHandler.TransferSupport support) {
536             return super.canImport(support);
537         }
538
539         @Override
540         public boolean importData(TransferHandler.TransferSupport support) {
541             return super.importData(support);
542         }
543     }
544 }