OSDN Git Service

d0a3fd7483e69fc2e353a35d050b97a31e5e6cdf
[importpicture/importpicture.git] / src / osm / jp / gpx / matchtime / gui / AdjustTime.java
1 package osm.jp.gpx.matchtime.gui;
2
3 import osm.jp.gpx.matchtime.gui.restamp.RestampDialog;
4 import java.awt.*;
5 import java.awt.event.ActionEvent;
6 import java.io.File;
7 import java.io.IOException;
8 import java.text.SimpleDateFormat;
9 import java.util.Date;
10 import java.util.ResourceBundle;
11 import java.util.TimeZone;
12 import java.util.logging.Level;
13 import java.util.logging.Logger;
14 import javax.swing.*;
15 import osm.jp.gpx.*;
16 import org.apache.commons.imaging.Imaging;
17 import org.apache.commons.imaging.common.ImageMetadata;
18 import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
19 import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
20 import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
21
22 /**
23  * 本プログラムのメインクラス
24  */
25 @SuppressWarnings("serial")
26 public class AdjustTime extends JFrame
27 {
28     public static final String PROGRAM_NAME = "AdjustTime for JOSM";
29     public static final String PROGRAM_VARSION = "5.01";
30     public static final String PROGRAM_UPDATE = "2019/09/11";
31
32     AppParameters params;
33     public static SimpleDateFormat dfjp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
34
35     // Used for addNotify check.
36     boolean fComponentsAdjusted = false;
37     public static ResourceBundle i18n = ResourceBundle.getBundle("i18n");
38     
39     //{{DECLARE_CONTROLS
40     JTabbedPane cardPanel;       // ウィザード形式パネル(タブ型)
41     JPanel[] cards;
42     int cardPanelNo = 0;
43     JPanel argsPanel;           // パラメータ設定パネル       (上部)
44     JScrollPane imageSPane;     // スクロールパネル
45     JLabel imageLabel;          // 基準時刻画像表示
46     ButtonGroup baseTimeGroup;  // 基準時刻の指定グループ
47     JRadioButton exifBase;              // EXIF日時を基準にする/ !(ファイル更新日時を基準にする)
48     JRadioButton fupdateBase;   // File更新日時を基準にする/ !(EXIF日時を基準にする)
49     JCheckBox noFirstNode;      // GPX: <trkseg>セグメントの最初の1ノードは無視する。 {ON | OFF}
50     JCheckBox gpxReuse;         // 生成されたGPXファイル(ファイル名が'_.gpx'で終わるもの)も対象にする。 {ON | OFF}
51     JTextArea textArea;         // 実行結果表示領域
52     ParameterPanelFolder arg1_srcFolder;
53     ParameterPanelImageFile arg2_baseTimeImg;
54     ParameterPanel arg3_basetime;       // 基準時刻:
55     JCheckBox outputIMG;        // IMGの変換 する/しない
56     JCheckBox outputIMG_all;    // 'out of GPX time'でもIMGの変換をする {ON | OFF}
57     JCheckBox exifON;           // EXIF 書き出しモード / !(EXIFの書き換えはしない)
58     JCheckBox gpxOutputWpt;     // GPXに<WPT>を書き出す
59     JCheckBox gpxOverwriteMagvar;       // ソースGPXの<MAGVAR>を無視する
60     JCheckBox gpxOutputSpeed;   // GPXに<SPEED>を書き出す
61     ParameterPanelFolder arg5_outputFolder;       // EXIF 書き出しフォルダ
62     ParameterPanelGpx arg4_gpxFolder;           // GPXファイル・フォルダ
63     
64     JPanel buttonPanel;         // ボタンパネル   (下部)
65     JButton openButton;         // [Fit]ボタン
66     JButton zoomInButton;       // [Zoom in]ボタン
67     JButton zoomOutButton;      // [Zoom out]ボタン
68     
69     JButton doButton;       // [処理実行]ボタン
70     //}}
71
72     //{{DECLARE_MENUS
73     java.awt.MenuBar mainMenuBar;
74     java.awt.Menu menu1;
75     java.awt.MenuItem miDoNewFileList;
76     java.awt.MenuItem miDoDirSize;
77     java.awt.MenuItem miDoReadXML;
78     java.awt.MenuItem miExit;
79     java.awt.Menu menu2;
80     java.awt.MenuItem miRestamp;
81     java.awt.Menu menu3;
82     java.awt.MenuItem miAbout;
83     //}}
84
85     class SymWindow extends java.awt.event.WindowAdapter {
86         /**
87          * このFrameが閉じられるときの動作。
88          * このパネルが閉じられたら、このアプリケーションも終了させる。
89          */
90         @Override
91         public void windowClosing(java.awt.event.WindowEvent event) {
92             Object object = event.getSource();
93             if (object == AdjustTime.this) {
94                 DbMang_WindowClosing(event);
95             }
96         }
97     }
98
99     class SymAction implements java.awt.event.ActionListener {
100         @Override
101         public void actionPerformed(java.awt.event.ActionEvent event) {
102             Object object = event.getSource();
103             if (object == miAbout) {
104                 miAbout_Action(event);
105             }
106             else if (object == miRestamp) {
107                 try {
108                     miRestamp_Action(event);
109                 } catch (IOException ex) {
110                     Logger.getLogger(AdjustTime.class.getName()).log(Level.SEVERE, null, ex);
111                 }
112             }
113             else if (object == miExit) {
114                 miExit_Action(event);
115             }
116             else if (object == openButton) {
117                 imageView_Action(event);
118             }
119             else if (object == zoomInButton) {
120                 zoomin_Action(event);
121             }
122             else if (object == zoomOutButton) {
123                 zoomout_Action(event);
124             }
125             else if (object == arg2_baseTimeImg.argField) {
126                 imageView_Action(event);
127             }
128             else if (object == arg2_baseTimeImg.openButton) {
129                 selectImage_Action(event);
130                 imageView_Action(event);
131             }
132             else if (object == outputIMG) {
133                 outputIMG_Action(event);
134             }
135             else if (object == outputIMG_all) {
136                 outputIMGall_Action(event);
137             }
138             else if (object == exifON) {
139                 exifON_Action(event);
140             }
141             else if (object == gpxOutputWpt) {
142                 gpxOutputWpt_Action(event);
143             }
144             else if (object == gpxOutputSpeed) {
145                 gpxOutputSpeed_Action(event);
146             }
147             else if (object == doButton) {
148                 doButton_Action(event);
149             }
150         }
151     }
152     
153     /**
154      * データベース内のテーブルを一覧で表示するFrame
155      * @throws IOException 
156      */
157     @SuppressWarnings("OverridableMethodCallInConstructor")
158     public AdjustTime() throws IOException
159     {
160         dfjp.setTimeZone(TimeZone.getTimeZone("JST"));
161
162         // INIT_CONTROLS
163         Container container = getContentPane();
164         container.setLayout(new BorderLayout());
165         setSize(
166             getInsets().left + getInsets().right + 720,
167             getInsets().top + getInsets().bottom + 480
168         );
169         setTitle(AdjustTime.PROGRAM_NAME +" v"+ AdjustTime.PROGRAM_VARSION);
170         
171         //---- CENTER -----
172         JPanel mainPanel = new JPanel();
173         mainPanel.setLayout(new BorderLayout());
174         container.add(mainPanel, BorderLayout.CENTER);
175         
176         //---- SOUTH -----
177         JPanel southPanel = new JPanel(new BorderLayout());
178         southPanel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH);
179         southPanel.add(Box.createVerticalStrut(10), BorderLayout.NORTH);
180         container.add(southPanel, BorderLayout.SOUTH);
181         
182         //---- SPACE -----
183         container.add(Box.createVerticalStrut(30), BorderLayout.NORTH);
184         container.add(Box.createHorizontalStrut(10), BorderLayout.WEST);
185         container.add(Box.createHorizontalStrut(10), BorderLayout.EAST);
186         
187         params = new AppParameters();
188         
189         //---------------------------------------------------------------------
190         cardPanel = new JTabbedPane(JTabbedPane.LEFT);
191         mainPanel.add(cardPanel, BorderLayout.CENTER);
192         
193         cards = new JPanel[5];
194         cardPanelNo = 0;
195
196         //---------------------------------------------------------------------
197         // 1.[対象フォルダ]設定パネル
198         int cardNo = 0;
199         {
200             Card card = new Card(cardPanel, i18n.getString("tab.100"), -1, 1);
201             cardPanel.addTab(card.getTitle(), card);
202             cards[cardNo] = card;
203
204             JLabel label1 = new JLabel();
205             label1.setText(i18n.getString("label.100"));
206             card.mainPanel.add(label1, BorderLayout.NORTH);
207
208             argsPanel = new JPanel();
209             argsPanel.setLayout(new BoxLayout(argsPanel, BoxLayout.Y_AXIS));
210             arg1_srcFolder = new ParameterPanelFolder(i18n.getString("label.110") +": ", params.getProperty(AppParameters.IMG_SOURCE_FOLDER));
211             argsPanel.add(arg1_srcFolder);
212             card.mainPanel.add(argsPanel, BorderLayout.CENTER);
213         }
214         
215         //---------------------------------------------------------------------
216         // 2.[基準時刻画像]設定パネル
217         cardNo++;
218         {
219             Card card = new Card(cardPanel, i18n.getString("tab.200"), 0, 2);
220             cardPanel.addTab(card.getTitle(), card);
221             cards[cardNo] = card;
222
223             JLabel label2 = new JLabel();
224             label2.setText(i18n.getString("label.200"));
225             card.mainPanel.add(label2, BorderLayout.NORTH);
226
227             argsPanel = new JPanel();
228
229             // 基準時刻画像
230             argsPanel.setLayout(new BoxLayout(argsPanel, BoxLayout.Y_AXIS));
231             arg2_baseTimeImg = new ParameterPanelImageFile(
232                 i18n.getString("label.210") +": ", 
233                 params.getProperty(AppParameters.IMG_BASE_FILE), 
234                 arg1_srcFolder
235             );
236             argsPanel.add(arg2_baseTimeImg);
237
238             baseTimeGroup = new ButtonGroup();
239
240             // EXIFの日時を基準にする
241             exifBase = new JRadioButton(i18n.getString("label.220"));
242
243             // ファイル更新日時を基準にする
244             fupdateBase = new JRadioButton(i18n.getString("label.230"));
245             baseTimeGroup.add(exifBase);
246             baseTimeGroup.add(fupdateBase);
247             argsPanel.add(exifBase);
248             argsPanel.add(fupdateBase);
249             if (params.getProperty(AppParameters.GPX_BASETIME).equals("EXIF_TIME")) {
250                 fupdateBase.setSelected(false);
251                 exifBase.setSelected(true);
252             }
253             else {
254                 fupdateBase.setSelected(true);
255                 exifBase.setSelected(false);
256             }
257             card.mainPanel.add(argsPanel, BorderLayout.CENTER);
258         }
259         
260         //---------------------------------------------------------------------
261         // 2a.基準時刻の入力画面
262         cardNo++;
263         {
264             Card card = new Card(cardPanel, i18n.getString("tab.300"), 1, 3);
265             cardPanel.addTab(card.getTitle(), card);
266             cards[cardNo] = card;
267
268             argsPanel = new JPanel();
269             argsPanel.setLayout(new GridLayout(2, 1));
270
271             // 3. 正確な撮影時刻を入力してください。
272             //    カメラの時計が正確ならば、設定を変更する必要はありません。
273             JLabel label3 = new JLabel();
274             label3.setText(i18n.getString("label.300"));
275             argsPanel.add(label3);
276
277             // 基準時刻:
278             String str310 = String.format("  %s: ", i18n.getString("label.310"));
279             arg3_basetime = new ParameterPanelTime(
280                     str310, 
281                     ImportPicture.TIME_FORMAT_STRING,
282                     arg2_baseTimeImg
283             );
284             argsPanel.add(arg3_basetime);
285             card.mainPanel.add(argsPanel, BorderLayout.NORTH);
286
287             // 参考画像
288             imageLabel = new JLabel();
289             imageSPane = new JScrollPane(imageLabel);
290             card.mainPanel.add(imageSPane, BorderLayout.CENTER);
291
292             // 画像ファイル選択ダイアログを起動するボタン
293             buttonPanel = new JPanel();
294             buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
295             openButton = new JButton(createImageIcon("images/Fit16.gif"));
296             buttonPanel.add(openButton);
297             zoomInButton = new JButton(createImageIcon("images/ZoomIn16.gif"));
298             buttonPanel.add(zoomInButton);
299             zoomOutButton = new JButton(createImageIcon("images/ZoomOut16.gif"));
300             buttonPanel.add(zoomOutButton);
301             card.mainPanel.add(buttonPanel, BorderLayout.SOUTH);
302         }
303         
304         //---------------------------------------------------------------------
305         // 3.GPXファイル設定画面
306         cardNo++;
307         {
308             // 3. GPXファイルを選択
309             Card card = new Card(cardPanel, i18n.getString("tab.400"), 2, 4);
310             cardPanel.addTab(card.getTitle(), card);
311             cards[cardNo] = card;
312
313             // 4. ヒモ付を行うGPXファイルを選択してください。
314             //    - フォルダを指定すると、フォルダ内のすべてのGPXファイルを対象とします。
315             JLabel label4 = new JLabel();
316             label4.setText(i18n.getString("label.400"));
317             card.mainPanel.add(label4, BorderLayout.NORTH);
318
319             JPanel tmpPanel4a = new JPanel();
320             tmpPanel4a.setLayout(new BoxLayout(tmpPanel4a, BoxLayout.Y_AXIS));
321
322             // "GPXフォルダ: "
323             arg4_gpxFolder = new ParameterPanelGpx(
324                 i18n.getString("label.410") + ": ", 
325                 params.getProperty(AppParameters.GPX_SOURCE_FOLDER)
326             );
327             tmpPanel4a.add(arg4_gpxFolder);
328
329             // "セグメント'trkseg'の最初の1ノードは無視する。"
330             noFirstNode = new JCheckBox(
331                 i18n.getString("label.420"), 
332                 params.getProperty(AppParameters.GPX_NO_FIRST_NODE).equals("ON")
333             );
334             tmpPanel4a.add(noFirstNode);
335
336             // "生成されたGPXファイル(ファイル名が'_.gpx'で終わるもの)も変換の対象にする"
337             gpxReuse = new JCheckBox(
338                 i18n.getString("label.430"),
339                 params.getProperty(AppParameters.GPX_REUSE).equals("ON")
340             );
341             gpxReuse.setEnabled(true);
342             tmpPanel4a.add(gpxReuse);
343             card.mainPanel.add(tmpPanel4a, BorderLayout.CENTER);
344         }
345         
346         //---------------------------------------------------------------------
347         // 4.EXIF更新設定画面
348         cardNo++;
349         {
350             Card card = new Card(cardPanel, i18n.getString("tab.500"), 3, -1);
351             cardPanel.addTab(card.getTitle(), card);
352             cards[cardNo] = card;
353             
354             // 5. EXIF変換を行うかどうかを選択してください。
355             //    - EXIF変換を行う場合には、変換ファイルを出力するフォルダも指定する必要があります。
356             //    - 出力フォルダには、書き込み権限と、十分な空き容量が必要です。
357             JLabel label5 = new JLabel();
358             label5.setText(
359                 String.format(
360                     "<html><p>5. %s</p><ul><li>%s</li><li>%s</li></ul>",
361                     i18n.getString("label.500"),
362                     i18n.getString("label.501"),
363                     i18n.getString("label.502")
364                 )
365             );
366             card.mainPanel.add(label5, BorderLayout.NORTH);
367
368             JPanel tmpPanel5 = new JPanel();
369             tmpPanel5.setLayout(new BoxLayout(tmpPanel5, BoxLayout.Y_AXIS));
370
371             // "IMGの変換をする"
372             outputIMG = new JCheckBox(
373                 i18n.getString("label.510"), 
374                 Boolean.parseBoolean(params.getProperty(AppParameters.IMG_OUTPUT))
375             );
376             tmpPanel5.add(outputIMG);
377
378             // "GPXファイル時間外のファイルもコピーする"
379             outputIMG_all = new JCheckBox(
380                 i18n.getString("label.520"),
381                 Boolean.parseBoolean(params.getProperty(AppParameters.IMG_OUTPUT_ALL))
382             );
383             tmpPanel5.add(outputIMG_all);
384
385             // "出力フォルダ: "
386             arg5_outputFolder = new ParameterPanelFolder(
387                 i18n.getString("label.530") + ": ",
388                 params.getProperty(AppParameters.IMG_OUTPUT_FOLDER)
389             );
390             tmpPanel5.add(arg5_outputFolder);
391
392             // "EXIFの変換をする"
393             exifON = new JCheckBox(
394                 i18n.getString("label.540"),
395                 Boolean.parseBoolean(params.getProperty(AppParameters.IMG_OUTPUT_EXIF))
396             );
397             tmpPanel5.add(exifON);
398
399             // "ポイントマーカー<WPT>をGPXファイルに出力する"
400             gpxOutputWpt = new JCheckBox(
401                 i18n.getString("label.550"),
402                 Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OUTPUT_WPT))
403             );
404             gpxOutputWpt.setEnabled(true);
405             tmpPanel5.add(gpxOutputWpt);
406
407             // "ソースGPXの<MAGVAR>を無視する"
408             gpxOverwriteMagvar = new JCheckBox(
409                 i18n.getString("label.560"),
410                 Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OVERWRITE_MAGVAR))
411             );
412             gpxOverwriteMagvar.setEnabled(true);
413             tmpPanel5.add(gpxOverwriteMagvar);
414
415             // "出力GPXに<SPEED>を上書きする"
416             gpxOutputSpeed = new JCheckBox(
417                 i18n.getString("label.570"),
418                 Boolean.parseBoolean(params.getProperty(AppParameters.GPX_OUTPUT_SPEED))
419             );
420             gpxOutputSpeed.setEnabled(true);
421             tmpPanel5.add(gpxOutputSpeed);
422
423             card.mainPanel.add(tmpPanel5, BorderLayout.CENTER);
424
425             // "処理実行"
426             doButton = new JButton(
427                 i18n.getString("button.execute"),
428                 AdjustTime.createImageIcon("images/media_playback_start.png")
429             );
430             card.mainPanel.add(doButton, BorderLayout.SOUTH);
431         }
432
433         //---------------------------------------------------------------------
434         // INIT_MENUS
435         menu1 = new java.awt.Menu("File");
436         miExit = new java.awt.MenuItem(i18n.getString("menu.quit"));
437         miExit.setFont(new Font("Dialog", Font.PLAIN, 12));
438         menu1.add(miExit);
439
440         miRestamp = new java.awt.MenuItem(i18n.getString("menu.restamp") + "...");
441         miRestamp.setFont(new Font("Dialog", Font.PLAIN, 12));
442         
443         menu2 = new java.awt.Menu(i18n.getString("menu.tools"));
444         menu2.setFont(new Font("Dialog", Font.PLAIN, 12));
445         menu2.add(miRestamp);
446
447         miAbout = new java.awt.MenuItem("About...");
448         miAbout.setFont(new Font("Dialog", Font.PLAIN, 12));
449
450         menu3 = new java.awt.Menu("Help");
451         menu3.setFont(new Font("Dialog", Font.PLAIN, 12));
452         menu3.add(miAbout);
453
454         mainMenuBar = new java.awt.MenuBar();
455         mainMenuBar.setHelpMenu(menu3);
456         mainMenuBar.add(menu1);
457         mainMenuBar.add(menu2);
458         mainMenuBar.add(menu3);
459         setMenuBar(mainMenuBar);
460
461         //{{REGISTER_LISTENERS
462         SymWindow aSymWindow = new SymWindow();
463         this.addWindowListener(aSymWindow);
464         SymAction lSymAction = new SymAction();
465         miAbout.addActionListener(lSymAction);
466         miRestamp.addActionListener(lSymAction);
467         miExit.addActionListener(lSymAction);
468         openButton.addActionListener(lSymAction);
469         zoomOutButton.addActionListener(lSymAction);
470         zoomInButton.addActionListener(lSymAction);
471         //arg2_baseTimeImg.argField.addActionListener(lSymAction);
472         arg2_baseTimeImg.openButton.addActionListener(lSymAction);
473         doButton.addActionListener(lSymAction);
474         outputIMG_all.addActionListener(lSymAction);
475         exifON.addActionListener(lSymAction);
476         gpxOutputSpeed.addActionListener(lSymAction);
477         noFirstNode.addActionListener(lSymAction);
478         gpxReuse.addActionListener(lSymAction);
479         //}}
480     }
481     
482     /**
483      * Shows or hides the component depending on the boolean flag b.
484      * @param b trueのときコンポーネントを表示; その他のとき, componentを隠す.
485      * @see java.awt.Component#isVisible
486      */
487     @Override
488     public void setVisible(boolean b) {
489         if(b) {
490             setLocation(50, 50);
491         }
492         super.setVisible(b);
493     }
494     
495     /**
496      * このクラスをインスタンスを生成して表示する。
497      * コマンドラインの引数はありません。
498      * @param args
499      */    
500     @SuppressWarnings("UseSpecificCatch")
501     static public void main(String args[]) {
502         SwingUtilities.invokeLater(() -> {
503             try {
504                 createAndShowGUI();
505             } catch (Exception e) {
506                 e.printStackTrace();
507             }
508         });
509     }
510     private static void createAndShowGUI() throws IOException {
511         (new AdjustTime()).setVisible(true);
512     }
513
514     @Override
515     public void addNotify()     {
516         // Record the size of the window prior to calling parents addNotify.
517         Dimension d = getSize();
518
519         super.addNotify();
520
521         if (fComponentsAdjusted)
522             return;
523
524         // Adjust components according to the insets
525         setSize(getInsets().left + getInsets().right + d.width, getInsets().top + getInsets().bottom + d.height);
526         Component components[] = getComponents();
527         for (Component component : components) {
528             Point p = component.getLocation();
529             p.translate(getInsets().left, getInsets().top);
530             component.setLocation(p);
531         }
532         fComponentsAdjusted = true;
533     }
534
535     void DbMang_WindowClosing(java.awt.event.WindowEvent event) {
536         setVisible(false);  // hide the Manager
537         dispose();                      // free the system resources
538         System.exit(0);         // close the application
539     }
540
541     void miAbout_Action(java.awt.event.ActionEvent event) {
542         // Action from About Create and show as modal
543         (new AboutDialog(this, true)).setVisible(true);
544     }
545     
546     void miRestamp_Action(java.awt.event.ActionEvent event) throws IOException {
547         (new RestampDialog(this, false)).setVisible(true);
548     }
549     
550     void miExit_Action(java.awt.event.ActionEvent event) {
551         // Action from Exit Create and show as modal
552         //(new hayashi.yuu.tools.gui.QuitDialog(this, true)).setVisible(true);
553         (new QuitDialog(this, true)).setVisible(true);
554     }
555
556     ImageIcon refImage;
557     
558     /**
559      * 選択された画像ファイルを表示する
560      * 基準画像ボタンがクリックされた時に、基準時刻フィールドに基準画像の作成日時を設定する。
561      * @param ev 
562      */
563     @SuppressWarnings("UseSpecificCatch")
564     public void imageView_Action(ActionEvent ev) {
565         String path = (new File(arg1_srcFolder.getText(), arg2_baseTimeImg.getText())).getPath();
566         
567         File timeFile = new File(path);
568         if (exifBase.isSelected()) {
569             try {
570                 ImageMetadata meta = Imaging.getMetadata(timeFile);
571                 JpegImageMetadata jpegMetadata = (JpegImageMetadata)meta;
572                 if (jpegMetadata != null) {
573                     TiffImageMetadata exif = jpegMetadata.getExif();
574                     if (exif != null) {
575                         String dateTimeOriginal = exif.getFieldValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL)[0];
576                         long lastModifyTime = (new SimpleDateFormat("yyyy:MM:dd HH:mm:ss")).parse(dateTimeOriginal).getTime();
577                         arg3_basetime.argField.setText(dfjp.format(new Date(lastModifyTime)));
578                     }
579                     else {
580                         arg3_basetime.argField.setText("exif == null");
581                     }
582                 }
583             }
584             catch (Exception e) {}
585         }
586         else {
587             long lastModifyTime = timeFile.lastModified();
588             arg3_basetime.argField.setText(dfjp.format(new Date(lastModifyTime)));
589         }
590         
591         int size_x = imageSPane.getWidth() - 8;
592         ImageIcon tmpIcon = new ImageIcon(path);
593         refImage = tmpIcon;
594         if (tmpIcon.getIconWidth() > size_x) {
595             refImage = new ImageIcon(tmpIcon.getImage().getScaledInstance(size_x, -1, Image.SCALE_DEFAULT));
596         }
597         imageLabel.setIcon(refImage);
598         repaint();
599     }
600
601     public void zoomin_Action(ActionEvent ev) {
602         if (refImage != null) {
603             int size_x = imageLabel.getWidth();
604             String path = (new File(arg1_srcFolder.getText(), arg2_baseTimeImg.getText())).getPath();
605             ImageIcon tmpIcon = new ImageIcon(path);
606             refImage = new ImageIcon(tmpIcon.getImage().getScaledInstance(size_x * 2, -1, Image.SCALE_DEFAULT));
607             imageLabel.setIcon(refImage);
608             repaint();
609         }
610     }
611
612     public void zoomout_Action(ActionEvent ev) {
613         if (refImage != null) {
614             int size_x = imageLabel.getWidth();
615             ImageIcon tmpIcon = refImage;
616             refImage = new ImageIcon(tmpIcon.getImage().getScaledInstance(size_x / 2, -1, Image.SCALE_DEFAULT));
617             imageLabel.setIcon(refImage);
618             repaint();
619         }
620     }
621     
622     /**
623      * ソースディレクトリが選択された時のアクション
624      * → AdjustTime.ini に書き込む
625      * @param ev
626      */
627     public void selectSource_Action(ActionEvent ev) {
628     }
629     
630     public void selectImage_Action(ActionEvent ev) {
631         JFileChooser fc;
632
633         //Set up the file chooser.
634         File sdir = new File(arg1_srcFolder.getText());
635         System.out.println(sdir.getPath());
636         if (sdir.isDirectory()) {
637             fc = new JFileChooser(sdir);
638         }
639         else {
640             fc = new JFileChooser();
641         }
642
643         //Add a custom file filter and disable the default
644         //(Accept All) file filter.
645         fc.addChoosableFileFilter(new ImageFilter());
646         fc.setAcceptAllFileFilterUsed(false);
647
648         //Add custom icons for file types.
649         fc.setFileView(new ImageFileView());
650
651         //Add the preview pane.
652         fc.setAccessory(new ImagePreview(fc));
653
654         //Show it. "選択"
655         int returnVal = fc.showDialog(this, i18n.getString("dialog.select"));
656
657         //Process the results.
658         if (returnVal == JFileChooser.APPROVE_OPTION) {
659             File file = fc.getSelectedFile();
660             arg2_baseTimeImg.argField.setText(file.getName());
661         }
662
663         //Reset the file chooser for the next time it's shown.
664         fc.setSelectedFile(null);
665     }
666     
667     /** Returns an ImageIcon, or null if the path was invalid.
668      * @param path
669      * @return  */
670     public static ImageIcon createImageIcon(String path) {
671         java.net.URL imgURL = AdjustTime.class.getResource(path);
672         if (imgURL != null) {
673             return new ImageIcon(imgURL);
674         } else {
675             System.err.println("Couldn't find file: " + path);
676             return null;
677         }
678     }
679     
680     /**
681      * checkbox[IMG変換]を変更した場合のアクション
682      *  ON ー> IMG出力フォルダのフィールドを有効にする
683      *  OFF -> IMG出力フォルダのフィールドを無効にする
684      * @param event
685      */
686     void outputIMG_Action (ActionEvent event) {
687         arg5_outputFolder.setEnabled(outputIMG.isEnabled());
688     }
689
690     /**
691      * checkbox[GPXファイル時間外のファイルもコピーする]を変更した場合のアクション
692      * @param event
693      */
694     void outputIMGall_Action (ActionEvent event) {
695     }
696
697     /**
698      * checkbox[EXIF書き出し]を変更した場合のアクション
699      * @param event
700      */
701     void exifON_Action (ActionEvent event) {
702     }
703
704     /**
705      * checkbox[GPXの<WPT>を出力する]を変更した場合のアクション
706      * @param event
707      */
708     void gpxOutputWpt_Action (ActionEvent event) {
709     }
710
711     /**
712      * checkbox[GPXの<SPPED>を書き換える]を変更した場合のアクション
713      * @param event
714      */
715     void gpxOutputSpeed_Action (ActionEvent event) {
716     }
717
718     /**
719      * [実行]ボタンをクリックしたときの動作
720      * @param event
721      */
722     @SuppressWarnings("UseSpecificCatch")
723     void doButton_Action(java.awt.event.ActionEvent event) {
724         doButton.setEnabled(false);
725
726         String[] argv = new String[0];
727         this.params.setProperty(AppParameters.GPX_NO_FIRST_NODE, String.valueOf(noFirstNode.isSelected()));
728         this.params.setProperty(AppParameters.GPX_REUSE, String.valueOf(gpxReuse.isSelected()));
729         this.params.setProperty(AppParameters.GPX_SOURCE_FOLDER, arg4_gpxFolder.getText());
730         
731         if (exifBase.isSelected()) {
732             this.params.setProperty(AppParameters.GPX_BASETIME, "EXIF_TIME");
733         }
734         else {
735             this.params.setProperty(AppParameters.GPX_BASETIME, "FILE_UPDATE");
736         }
737         try {
738             this.params.setProperty(AppParameters.IMG_SOURCE_FOLDER, arg1_srcFolder.getText());
739             this.params.setProperty(AppParameters.IMG_BASE_FILE, arg2_baseTimeImg.getText());
740             this.params.setProperty(AppParameters.IMG_TIME, ImportPicture.toUTCString(dfjp.parse(arg3_basetime.getText())));
741             this.params.setProperty(AppParameters.IMG_OUTPUT, String.valueOf(outputIMG.isSelected()));
742             this.params.setProperty(AppParameters.IMG_OUTPUT_FOLDER, arg5_outputFolder.getText());
743             this.params.setProperty(AppParameters.IMG_OUTPUT_ALL, String.valueOf(outputIMG_all.isSelected()));
744             this.params.setProperty(AppParameters.IMG_OUTPUT_EXIF, String.valueOf(exifON.isSelected()));
745             this.params.setProperty(AppParameters.GPX_OVERWRITE_MAGVAR, String.valueOf(gpxOverwriteMagvar.isSelected()));
746             this.params.setProperty(AppParameters.GPX_OUTPUT_SPEED, String.valueOf(gpxOutputSpeed.isSelected()));
747             this.params.setProperty(AppParameters.GPX_OUTPUT_WPT, String.valueOf(gpxOutputWpt.isSelected()));
748             this.params.store();
749         }
750         catch(Exception e) {
751             e.printStackTrace();
752         }
753
754         (new DoDialog(argv)).setVisible(true);
755                 
756         doButton.setEnabled(true);
757     }
758 }