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.BorderFactory;
28 import javax.swing.DropMode;
29 import javax.swing.GroupLayout;
30 import javax.swing.GroupLayout.Alignment;
31 import javax.swing.JButton;
32 import javax.swing.JCheckBox;
33 import javax.swing.JFrame;
34 import javax.swing.JLabel;
35 import javax.swing.JMenu;
36 import javax.swing.JMenuBar;
37 import javax.swing.JMenuItem;
38 import javax.swing.JPanel;
39 import javax.swing.JScrollPane;
40 import javax.swing.JTable;
41 import javax.swing.JTextField;
42 import javax.swing.KeyStroke;
43 import javax.swing.LayoutStyle.ComponentPlacement;
44 import javax.swing.TransferHandler;
45 import javax.swing.WindowConstants;
46 import org.apache.commons.lang.StringUtils;
47 import saccubus.MainFrame_AboutBox;
48 import saccubus.worker.Download;
49 import saccubus.worker.profile.CommentProfile;
50 import saccubus.worker.profile.DownloadProfile;
51 import saccubus.worker.profile.GeneralProfile;
52 import saccubus.worker.profile.LoginProfile;
53 import saccubus.worker.profile.ProxyProfile;
54 import saccubus.worker.profile.VideoProfile;
56 import yukihane.inqubus.Config;
57 import yukihane.inqubus.model.Target;
58 import yukihane.inqubus.model.TargetsTableModel;
64 public class MainFrame extends JFrame {
66 private static final long serialVersionUID = 1L;
67 private static final Logger logger = Logger.getLogger(MainFrame.class.getName());
68 private final TargetsTableModel targetModel = new TargetsTableModel();
70 /** Creates new form MainFrame */
72 final URL url = MainFrame_AboutBox.class.getResource("icon.png");
73 final Image icon1 = Toolkit.getDefaultToolkit().createImage(url);
74 final URL url32 = MainFrame_AboutBox.class.getResource("icon32.png");
75 final Image icon2 = Toolkit.getDefaultToolkit().createImage(url32);
76 final List<Image> images = new ArrayList<Image>(2);
79 setIconImages(images);
81 final JPanel pnlMain = new JPanel();
82 final JScrollPane scrDisplay = new JScrollPane();
83 tblDisplay = new JTable();
84 final JPanel pnlButton = new JPanel();
85 btnStart = new JButton();
86 btnStop = new JButton();
87 btnDeselect = new JButton();
88 final JPanel pnlInputMain = new JPanel();
89 final JLabel lblId = new JLabel();
90 fldId = new JTextField();
91 final JLabel lblVideo = new JLabel();
92 cbVideoLocal = new JCheckBox();
93 fldVideo = new JTextField();
94 btnVideo = new JButton();
95 final JLabel lblComment = new JLabel();
96 cbCommentLocal = new JCheckBox();
97 fldComment = new JTextField();
98 btnComment = new JButton();
99 final JLabel lblOutput = new JLabel();
100 cbOutputEnable = new JCheckBox();
101 fldOutput = new JTextField();
103 setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
105 btnApply.addActionListener(new ApplyActionListener());
107 pnlMain.setBorder(BorderFactory.createEtchedBorder());
109 tblDisplay.setModel(targetModel);
110 tblDisplay.setDropMode(DropMode.INSERT_ROWS);
111 scrDisplay.setViewportView(tblDisplay);
113 pnlButton.setBorder(BorderFactory.createEtchedBorder());
115 btnStart.setText("開始");
117 btnStop.setText("停止");
119 btnDeselect.setText("選択解除");
121 GroupLayout gl_pnlButton = new GroupLayout(pnlButton);
122 pnlButton.setLayout(gl_pnlButton);
123 gl_pnlButton.setHorizontalGroup(
124 gl_pnlButton.createParallelGroup(Alignment.LEADING)
125 .addGroup(gl_pnlButton.createSequentialGroup()
127 .addComponent(btnStart)
128 .addPreferredGap(ComponentPlacement.RELATED)
129 .addComponent(btnStop)
130 .addPreferredGap(ComponentPlacement.RELATED, 250, Short.MAX_VALUE)
131 .addComponent(btnDeselect)
134 gl_pnlButton.setVerticalGroup(
135 gl_pnlButton.createParallelGroup(Alignment.LEADING)
136 .addGroup(gl_pnlButton.createSequentialGroup()
138 .addGroup(gl_pnlButton.createParallelGroup(Alignment.BASELINE)
139 .addComponent(btnStart)
140 .addComponent(btnStop)
141 .addComponent(btnDeselect))
142 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
145 pnlInputMain.setBorder(BorderFactory.createEtchedBorder());
149 fldId.addFocusListener(new java.awt.event.FocusAdapter() {
151 public void focusLost(java.awt.event.FocusEvent evt) {
152 idFieldFocusLost(evt);
156 lblVideo.setText("動画");
158 cbVideoLocal.setText("local");
159 cbVideoLocal.addItemListener(new java.awt.event.ItemListener() {
161 public void itemStateChanged(java.awt.event.ItemEvent evt) {
162 useMovieLocalCheckBoxItemStateChanged(evt);
166 btnVideo.setText("...");
168 lblComment.setText("コメント");
170 cbCommentLocal.setText("local");
171 cbCommentLocal.addItemListener(new java.awt.event.ItemListener() {
173 public void itemStateChanged(java.awt.event.ItemEvent evt) {
174 useMovieLocalCheckBoxItemStateChanged(evt);
178 btnComment.setText("...");
180 lblOutput.setText("出力");
182 cbOutputEnable.setText("変換");
183 cbOutputEnable.addItemListener(new java.awt.event.ItemListener() {
185 public void itemStateChanged(java.awt.event.ItemEvent evt) {
186 outputConvertCheckBoxItemStateChanged(evt);
191 GroupLayout gl_pnlInputMain = new GroupLayout(pnlInputMain);
192 pnlInputMain.setLayout(gl_pnlInputMain);
193 gl_pnlInputMain.setHorizontalGroup(
194 gl_pnlInputMain.createParallelGroup(Alignment.LEADING)
195 .addGroup(gl_pnlInputMain.createSequentialGroup()
197 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.LEADING)
198 .addGroup(gl_pnlInputMain.createSequentialGroup()
199 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.LEADING)
200 .addComponent(lblComment)
201 .addComponent(lblVideo)
203 .addComponent(lblOutput))
204 .addPreferredGap(ComponentPlacement.RELATED)
205 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.LEADING)
206 .addGroup(gl_pnlInputMain.createSequentialGroup()
207 .addComponent(cbVideoLocal)
208 .addPreferredGap(ComponentPlacement.RELATED)
209 .addComponent(fldVideo, GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE)
210 .addPreferredGap(ComponentPlacement.RELATED)
211 .addComponent(btnVideo))
212 .addComponent(fldId, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
213 .addGroup(Alignment.TRAILING, gl_pnlInputMain.createSequentialGroup()
214 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.TRAILING)
215 .addGroup(Alignment.LEADING, gl_pnlInputMain.createSequentialGroup()
216 .addComponent(cbOutputEnable)
217 .addPreferredGap(ComponentPlacement.RELATED)
218 .addComponent(fldOutput, GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE))
219 .addGroup(gl_pnlInputMain.createSequentialGroup()
220 .addComponent(cbCommentLocal)
221 .addPreferredGap(ComponentPlacement.RELATED)
222 .addComponent(fldComment, GroupLayout.DEFAULT_SIZE, 317, Short.MAX_VALUE)))
223 .addPreferredGap(ComponentPlacement.RELATED)
224 .addComponent(btnComment))))
225 .addComponent(btnApply, Alignment.TRAILING))
228 gl_pnlInputMain.setVerticalGroup(
229 gl_pnlInputMain.createParallelGroup(Alignment.LEADING)
230 .addGroup(gl_pnlInputMain.createSequentialGroup()
232 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.BASELINE)
233 .addComponent(fldId, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
234 .addComponent(lblId))
235 .addPreferredGap(ComponentPlacement.RELATED)
236 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.BASELINE)
237 .addComponent(lblVideo)
238 .addComponent(fldVideo, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
239 .addComponent(btnVideo)
240 .addComponent(cbVideoLocal))
241 .addPreferredGap(ComponentPlacement.RELATED)
242 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.BASELINE)
243 .addComponent(lblComment)
244 .addComponent(fldComment, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
245 .addComponent(btnComment)
246 .addComponent(cbCommentLocal))
247 .addPreferredGap(ComponentPlacement.RELATED)
248 .addGroup(gl_pnlInputMain.createParallelGroup(Alignment.BASELINE)
249 .addComponent(lblOutput)
250 .addComponent(fldOutput, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
251 .addComponent(cbOutputEnable))
252 .addPreferredGap(ComponentPlacement.UNRELATED)
253 .addComponent(btnApply)
254 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
257 GroupLayout gl_pnlMain = new GroupLayout(pnlMain);
258 pnlMain.setLayout(gl_pnlMain);
259 gl_pnlMain.setHorizontalGroup(
260 gl_pnlMain.createParallelGroup(Alignment.LEADING)
261 .addGroup(Alignment.TRAILING, gl_pnlMain.createSequentialGroup()
263 .addGroup(gl_pnlMain.createParallelGroup(Alignment.TRAILING)
264 .addComponent(pnlInputMain, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
265 .addComponent(scrDisplay, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 480, Short.MAX_VALUE)
266 .addComponent(pnlButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
269 gl_pnlMain.setVerticalGroup(
270 gl_pnlMain.createParallelGroup(Alignment.LEADING)
271 .addGroup(Alignment.TRAILING, gl_pnlMain.createSequentialGroup()
273 .addComponent(scrDisplay, GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
274 .addPreferredGap(ComponentPlacement.RELATED)
275 .addComponent(pnlButton, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
276 .addPreferredGap(ComponentPlacement.RELATED)
277 .addComponent(pnlInputMain, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
282 JMenuBar menuBar = initMenuBar();
283 setJMenuBar(menuBar);
285 GroupLayout layout = new GroupLayout(getContentPane());
286 getContentPane().setLayout(layout);
287 layout.setHorizontalGroup(
288 layout.createParallelGroup(Alignment.LEADING)
289 .addComponent(pnlMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
291 layout.setVerticalGroup(
292 layout.createParallelGroup(Alignment.LEADING)
293 .addComponent(pnlMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
298 pnlMain.setTransferHandler(new DownloadListTransferHandler());
299 tblDisplay.setTransferHandler(new TableTransferHandler());
302 private class ApplyActionListener implements ActionListener {
305 public void actionPerformed(ActionEvent e) {
306 final DownloadProfile prof = new InqubusDownloadProfile();
307 final String id = Util.getVideoId(fldId.getText());
309 new Download(prof, id).execute();
312 /** This method is called from within the constructor to
313 * initialize the form.
314 * WARNING: Do NOT modify this code. The content of this method is
315 * always regenerated by the Form Editor.
317 @SuppressWarnings("unchecked")
318 // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
319 private void initComponents() {
320 }// </editor-fold>//GEN-END:initComponents
322 private File searchFileMatchId(final File dir, final String id) throws UnsupportedOperationException {
323 // TODO 候補は複数返すようにして、その後の対処は呼び出しもとで行ってもらった方が良いかも
328 final File[] lists = dir.listFiles(new FilenameFilter() {
330 final Pattern pattern = Pattern.compile(id + "\\D");
333 public boolean accept(File dir, String name) {
334 return pattern.matcher(name).find();
338 if (lists.length == 1) {
340 } else if (lists.length > 1) {
341 throw new UnsupportedOperationException();
347 private void useMovieLocalCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_useMovieLocalCheckBoxItemStateChanged
348 final Config p = Config.INSTANCE;
350 final ItemSelectable source = evt.getItemSelectable();
355 if (source == cbVideoLocal) {
358 dir = new File(p.getVideoDir());
362 dir = new File(p.getCommentDir());
365 final boolean useLocal = (evt.getStateChange() == ItemEvent.SELECTED);
366 btn.setEnabled(useLocal);
370 final File f = searchFileMatchId(dir, fldId.getText());
377 text = p.getVideoFileNamePattern();
380 }//GEN-LAST:event_useMovieLocalCheckBoxItemStateChanged
382 private void outputConvertCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_outputConvertCheckBoxItemStateChanged
383 final boolean convert = (evt.getStateChange() == ItemEvent.SELECTED);
384 fldOutput.setEnabled(convert);
385 }//GEN-LAST:event_outputConvertCheckBoxItemStateChanged
387 private void idFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_idFieldFocusLost
388 final Config p = Config.INSTANCE;
389 final String id = fldId.getText();
394 if (cbVideoLocal.isSelected() && fldVideo.getText().isEmpty()) {
395 final File dir = new File(p.getVideoDir());
396 final File file = searchFileMatchId(dir, id);
398 fldVideo.setText(file.getPath());
402 if (cbCommentLocal.isSelected() && fldComment.getText().isEmpty()) {
403 final File dir = new File(p.getCommentDir());
404 final File file = searchFileMatchId(dir, id);
406 fldComment.setText(file.getPath());
410 }//GEN-LAST:event_idFieldFocusLost
411 // Variables declaration - do not modify//GEN-BEGIN:variables
412 private final JTable tblDisplay;
414 private final JButton btnStart;
415 private final JButton btnStop;
416 private final JButton btnDeselect;
418 private final JTextField fldId;
419 private final JCheckBox cbVideoLocal;
420 private final JTextField fldVideo;
421 private final JButton btnVideo;
422 private final JCheckBox cbCommentLocal;
423 private final JTextField fldComment;
424 private final JButton btnComment;
425 private final JCheckBox cbOutputEnable;
426 private final JTextField fldOutput;
428 private final JButton btnApply = new JButton("適用");
429 // End of variables declaration//GEN-END:variables
431 private void initInputPanel() {
434 final Config p = Config.INSTANCE;
436 final boolean movieLocal = p.getVideoUseLocal();
437 cbVideoLocal.setSelected(movieLocal);
438 btnVideo.setEnabled(movieLocal);
440 fldVideo.setText(p.getVideoFileNamePattern());
443 final boolean commentLocal = p.getCommentUseLocal();
444 cbCommentLocal.setSelected(commentLocal);
445 btnComment.setEnabled(commentLocal);
447 fldComment.setText(p.getCommentFileNamePattern());
450 final boolean convert = p.getOutputEnable();
451 cbOutputEnable.setSelected(convert);
452 fldOutput.setEnabled(convert);
453 fldOutput.setText(p.getOutputFileNamePattern());
457 private JMenuBar initMenuBar() {
458 final JMenuBar menuBar = new JMenuBar();
460 final JMenu mnFile = new JMenu("ファイル(F)");
463 final JMenuItem itExit = new JMenuItem("終了(X)", KeyEvent.VK_X);
464 itExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
465 itExit.addActionListener(new ActionListener() {
468 public void actionPerformed(ActionEvent e) {
469 throw new UnsupportedOperationException("Not supported yet.");
474 final JMenu mnTool = new JMenu("ツール(T)");
477 final JMenuItem itOption = new JMenuItem("オプション(O)...", KeyEvent.VK_O);
479 itOption.addActionListener(new ActionListener() {
482 public void actionPerformed(ActionEvent e) {
483 final yukihane.inqubus.gui.ConfigDialog dlg = new yukihane.inqubus.gui.ConfigDialog(MainFrame.this);
484 dlg.setLocationRelativeTo(MainFrame.this);
486 dlg.setVisible(true);
489 mnTool.add(itOption);
491 final JMenu mnHelp = new JMenu("ヘルプ(H)");
494 final JMenuItem itAbout = new JMenuItem("このソフトウェアについて(A)...", KeyEvent.VK_A);
495 itAbout.addActionListener(new ActionListener() {
498 public void actionPerformed(ActionEvent e) {
499 MainFrame_AboutBox dlg = new MainFrame_AboutBox(MainFrame.this);
501 dlg.setLocationRelativeTo(MainFrame.this);
503 dlg.setVisible(true);
511 private class DownloadListTransferHandler extends TransferHandler {
513 private static final long serialVersionUID = 1L;
514 private final Pattern movieIdPattern = Pattern.compile("(\\w\\w\\d+)");
517 public boolean canImport(TransferHandler.TransferSupport support) {
518 Transferable transferable = support.getTransferable();
519 if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
520 || transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
527 public boolean importData(TransferHandler.TransferSupport support) {
529 Transferable transferable = support.getTransferable();
530 if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
531 @SuppressWarnings("unchecked")
532 final List<File> data = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
533 Collection<Target> targets = Target.from(data);
534 targetModel.addTarget(targets);
535 } else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
536 String data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
537 Matcher matcher = movieIdPattern.matcher(data);
538 if (matcher.find()) {
539 String movieId = matcher.group(1);
540 Target target = Target.fromId(movieId);
541 targetModel.addTarget(target);
548 } catch (Exception e) {
549 logger.log(Level.SEVERE, null, e);
555 private class TableTransferHandler extends DownloadListTransferHandler {
557 private static final long serialVersionUID = 1L;
560 public boolean canImport(TransferHandler.TransferSupport support) {
561 return super.canImport(support);
565 public boolean importData(TransferHandler.TransferSupport support) {
566 return super.importData(support);
571 private class InqubusDownloadProfile implements DownloadProfile {
573 private final LoginProfile loginProfile;
574 private final ProxyProfile proxyProfile;
576 private InqubusDownloadProfile() {
577 this.loginProfile = new InqubusLoginProfile();
578 this.proxyProfile = new InqubusProxyProfile();
582 public LoginProfile getLoginInfo() {
583 return this.loginProfile;
587 public ProxyProfile getProxyProfile() {
588 return this.proxyProfile;
592 public VideoProfile getVideoProfile() {
593 throw new UnsupportedOperationException("Not supported yet.");
597 public CommentProfile getCommentProfile() {
598 throw new UnsupportedOperationException("Not supported yet.");
602 public GeneralProfile getGeneralProfile() {
603 throw new UnsupportedOperationException("Not supported yet.");
607 private class InqubusLoginProfile implements LoginProfile {
608 private final String mail;
609 private final String password;
611 private InqubusLoginProfile(){
612 final Config p = Config.INSTANCE;
613 this.mail = p.getId();
614 this.password = p.getPassword();
618 public String getMail() {
623 public String getPassword() {
624 return this.password;
628 private class InqubusProxyProfile implements ProxyProfile {
629 private final boolean use;
630 private final String host;
631 private final int port;
633 private InqubusProxyProfile(){
634 final Config p = Config.INSTANCE;
635 this.use = p.getProxyUse();
636 this.host = p.getProxyHost();
637 final String pp = p.getProxyPort();
638 this.port = StringUtils.isBlank(pp) ? -1 : Integer.parseInt(pp);
642 public boolean use() {
647 public String getHost() {
652 public int getPort() {