4 * Created on 2011/05/28, 18:14:51
6 package yukihane.inqubus.gui;
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;
18 import java.io.FilenameFilter;
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.Properties;
36 import yukihane.inqubus.model.Target;
37 import yukihane.inqubus.model.TargetsTableModel;
43 public class MainFrame extends javax.swing.JFrame {
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();
49 /** Creates new form MainFrame */
53 jPanel1.setTransferHandler(new DownloadListTransferHandler());
54 jTable1.setTransferHandler(new TableTransferHandler());
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.
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);
72 setIconImages(images);
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();
97 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
99 jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
101 jTable1.setModel(targetModel);
102 jTable1.setDropMode(javax.swing.DropMode.INSERT_ROWS);
103 jScrollPane1.setViewportView(jTable1);
105 jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
107 jButton2.setText("開始");
109 jButton3.setText("停止");
111 jButton4.setText("選択解除");
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()
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)
126 jPanel2Layout.setVerticalGroup(
127 jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
128 .addGroup(jPanel2Layout.createSequentialGroup()
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))
137 jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
139 idLabel.setText("ID");
141 idField.addFocusListener(new java.awt.event.FocusAdapter() {
143 public void focusLost(java.awt.event.FocusEvent evt) {
144 idFieldFocusLost(evt);
148 movieLabel.setText("動画");
150 useMovieLocalCheckBox.setText("local");
151 useMovieLocalCheckBox.addItemListener(new java.awt.event.ItemListener() {
153 public void itemStateChanged(java.awt.event.ItemEvent evt) {
154 useMovieLocalCheckBoxItemStateChanged(evt);
158 movieFileSelectButton.setText("...");
160 commentLabel.setText("コメント");
162 useCommentLocalCheckBox.setText("local");
163 useCommentLocalCheckBox.addItemListener(new java.awt.event.ItemListener() {
165 public void itemStateChanged(java.awt.event.ItemEvent evt) {
166 useMovieLocalCheckBoxItemStateChanged(evt);
170 commentFileSelectButton.setText("...");
172 outputLabel.setText("出力");
174 outputConvertCheckBox.setText("変換");
175 outputConvertCheckBox.addItemListener(new java.awt.event.ItemListener() {
177 public void itemStateChanged(java.awt.event.ItemEvent evt) {
178 outputConvertCheckBoxItemStateChanged(evt);
182 applyButton.setText("適用");
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()
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))
221 jPanel3Layout.setVerticalGroup(
222 jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
223 .addGroup(jPanel3Layout.createSequentialGroup()
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))
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()
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))
262 jPanel1Layout.setVerticalGroup(
263 jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
264 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
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)
275 JMenuBar menuBar = initMenuBar();
276 setJMenuBar(menuBar);
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)
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)
290 }// </editor-fold>//GEN-END:initComponents
292 private File searchFileMatchId(final File dir, final String id) throws UnsupportedOperationException {
293 // TODO 候補は複数返すようにして、その後の対処は呼び出しもとで行ってもらった方が良いかも
298 final File[] lists = dir.listFiles(new FilenameFilter() {
300 final Pattern pattern = Pattern.compile(id + "\\D");
303 public boolean accept(File dir, String name) {
304 return pattern.matcher(name).find();
308 if (lists.length == 1) {
310 } else if (lists.length > 1) {
311 throw new UnsupportedOperationException();
317 private void useMovieLocalCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_useMovieLocalCheckBoxItemStateChanged
318 final Properties p = Properties.INSTANCE;
320 final ItemSelectable source = evt.getItemSelectable();
325 if (source == useMovieLocalCheckBox) {
326 btn = movieFileSelectButton;
327 field = movieFileField;
328 dir = new File(p.getVideoDir());
330 btn = commentFileSelectButton;
331 field = commentFileField;
332 dir = new File(p.getCommentDir());
335 final boolean useLocal = (evt.getStateChange() == ItemEvent.SELECTED);
336 btn.setEnabled(useLocal);
340 final File f = searchFileMatchId(dir, idField.getText());
347 text = p.getVideoFileNamePattern();
350 }//GEN-LAST:event_useMovieLocalCheckBoxItemStateChanged
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
357 private void idFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_idFieldFocusLost
358 final Properties p = Properties.INSTANCE;
359 final String id = idField.getText();
364 if (useMovieLocalCheckBox.isSelected() && movieFileField.getText().isEmpty()) {
365 final File dir = new File(p.getVideoDir());
366 final File file = searchFileMatchId(dir, id);
368 movieFileField.setText(file.getPath());
372 if (useCommentLocalCheckBox.isSelected() && commentFileField.getText().isEmpty()) {
373 final File dir = new File(p.getCommentDir());
374 final File file = searchFileMatchId(dir, id);
376 commentFileField.setText(file.getPath());
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
406 private void initInputPanel() {
409 final Properties p = Properties.INSTANCE;
411 final boolean movieLocal = p.getVideoUseLocal();
412 useMovieLocalCheckBox.setSelected(movieLocal);
413 movieFileSelectButton.setEnabled(movieLocal);
415 movieFileField.setText(p.getVideoFileNamePattern());
418 final boolean commentLocal = p.getCommentUseLocal();
419 useCommentLocalCheckBox.setSelected(commentLocal);
420 commentFileSelectButton.setEnabled(commentLocal);
422 commentFileField.setText(p.getCommentFileNamePattern());
425 final boolean convert = p.getOutputEnable();
426 outputConvertCheckBox.setSelected(convert);
427 outputFileField.setEnabled(convert);
428 outputFileField.setText(p.getOutputFileNamePattern());
432 private JMenuBar initMenuBar() {
433 final JMenuBar menuBar = new JMenuBar();
435 final JMenu mnFile = new JMenu("ファイル(F)");
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() {
443 public void actionPerformed(ActionEvent e) {
444 throw new UnsupportedOperationException("Not supported yet.");
449 final JMenu mnTool = new JMenu("ツール(T)");
452 final JMenuItem itOption = new JMenuItem("オプション(O)...", KeyEvent.VK_O);
454 itOption.addActionListener(new ActionListener() {
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);
461 dlg.setVisible(true);
464 mnTool.add(itOption);
466 final JMenu mnHelp = new JMenu("ヘルプ(H)");
469 final JMenuItem itAbout = new JMenuItem("このソフトウェアについて(A)...", KeyEvent.VK_A);
470 itAbout.addActionListener(new ActionListener() {
473 public void actionPerformed(ActionEvent e) {
474 MainFrame_AboutBox dlg = new MainFrame_AboutBox(MainFrame.this);
476 dlg.setLocationRelativeTo(MainFrame.this);
478 dlg.setVisible(true);
486 private class DownloadListTransferHandler extends TransferHandler {
488 private static final long serialVersionUID = 1L;
489 private final Pattern movieIdPattern = Pattern.compile("(\\w\\w\\d+)");
492 public boolean canImport(TransferHandler.TransferSupport support) {
493 Transferable transferable = support.getTransferable();
494 if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
495 || transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
502 public boolean importData(TransferHandler.TransferSupport support) {
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);
523 } catch (Exception e) {
524 logger.log(Level.SEVERE, null, e);
530 private class TableTransferHandler extends DownloadListTransferHandler {
532 private static final long serialVersionUID = 1L;
535 public boolean canImport(TransferHandler.TransferSupport support) {
536 return super.canImport(support);
540 public boolean importData(TransferHandler.TransferSupport support) {
541 return super.importData(support);