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