OSDN Git Service

mavenによるビルドに変更
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / ui / SelectCharatersDirDialog.java
1 package charactermanaj.ui;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.Container;\r
5 import java.awt.Dimension;\r
6 import java.awt.Font;\r
7 import java.awt.GridBagConstraints;\r
8 import java.awt.GridBagLayout;\r
9 import java.awt.Insets;\r
10 import java.awt.Toolkit;\r
11 import java.awt.dnd.DropTarget;\r
12 import java.awt.event.ActionEvent;\r
13 import java.awt.event.FocusAdapter;\r
14 import java.awt.event.FocusEvent;\r
15 import java.awt.event.KeyEvent;\r
16 import java.awt.event.WindowAdapter;\r
17 import java.awt.event.WindowEvent;\r
18 import java.io.File;\r
19 import java.util.ArrayList;\r
20 import java.util.List;\r
21 import java.util.Properties;\r
22 import java.util.logging.Level;\r
23 import java.util.logging.Logger;\r
24 \r
25 import javax.swing.AbstractAction;\r
26 import javax.swing.BorderFactory;\r
27 import javax.swing.Box;\r
28 import javax.swing.InputMap;\r
29 import javax.swing.JButton;\r
30 import javax.swing.JCheckBox;\r
31 import javax.swing.JComboBox;\r
32 import javax.swing.JDialog;\r
33 import javax.swing.JFileChooser;\r
34 import javax.swing.JFrame;\r
35 import javax.swing.JLabel;\r
36 import javax.swing.JOptionPane;\r
37 import javax.swing.JPanel;\r
38 import javax.swing.JRootPane;\r
39 import javax.swing.KeyStroke;\r
40 \r
41 import charactermanaj.Main;\r
42 import charactermanaj.model.io.WorkingSetPersist;\r
43 import charactermanaj.ui.util.FileDropTarget;\r
44 import charactermanaj.util.ErrorMessageHelper;\r
45 import charactermanaj.util.LocalizedResourcePropertyLoader;\r
46 \r
47 /**\r
48  * 起動時にキャラクターデータディレクトリを選択するためのモーダルダイアログ.<br>\r
49  * \r
50  * @author seraphy\r
51  */\r
52 public class SelectCharatersDirDialog extends JDialog {\r
53 \r
54         private static final long serialVersionUID = -888834575856349442L;\r
55 \r
56         private static final Logger logger = Logger.getLogger(SelectCharatersDirDialog.class.getName());\r
57 \r
58         /**\r
59          * 最後に使用したキャラクターデータディレクトリと、その履歴情報.\r
60          */\r
61         private final RecentCharactersDir recentCharactersDir;\r
62         \r
63         /**\r
64          * 既定のディレクトリ\r
65          */\r
66         private File defaultCharactersDir;\r
67         \r
68         \r
69         /**\r
70          * 選択されたディレクトリ\r
71          */\r
72         private File selectedCharacterDir;\r
73         \r
74         /**\r
75          * 次回起動時に問い合わせない\r
76          */\r
77         private boolean doNotAskAgain;\r
78         \r
79         \r
80         /**\r
81          * ディレクトリ選択コンボ\r
82          */\r
83         private JComboBox combDir;\r
84         \r
85         /**\r
86          * 次回起動時に問い合わせないチェックボックス\r
87          */\r
88         private JCheckBox chkDoNotAsk;\r
89         \r
90         \r
91         \r
92         public File getDefaultCharactersDir() {\r
93                 return defaultCharactersDir;\r
94         }\r
95 \r
96         public void setDefaultCharactersDir(File defaultCharactersDir) {\r
97                 this.defaultCharactersDir = defaultCharactersDir;\r
98         }\r
99         \r
100         public File getSelectedCharacterDir() {\r
101                 return selectedCharacterDir;\r
102         }\r
103         \r
104         public boolean isDoNotAskAgain() {\r
105                 return doNotAskAgain;\r
106         }\r
107         \r
108         /**\r
109          * コンストラクタ\r
110          * \r
111          * @param parent\r
112          *            親(通常は、null)\r
113          * @param recentCharactersDir\r
114          *            最後に使用したキャラクターデータディレクトリと、その履歴情報.\r
115          */\r
116         protected SelectCharatersDirDialog(JFrame parent, RecentCharactersDir recentCharactersDir) {\r
117                 super(parent, true);\r
118                 try {\r
119                         if (recentCharactersDir == null) {\r
120                                 throw new IllegalArgumentException(\r
121                                                 "recentCharactersDirにnullは指定できません。");\r
122                         }\r
123                         this.recentCharactersDir = recentCharactersDir;\r
124                         \r
125                         setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);\r
126                         addWindowListener(new WindowAdapter() {\r
127                                 @Override\r
128                                 public void windowClosing(WindowEvent e) {\r
129                                         onClose();\r
130                                 }\r
131                         });\r
132                         initComponent();\r
133                         \r
134                 } catch (RuntimeException ex) {\r
135                         logger.log(Level.SEVERE, "キャラクターディレクトリ選択ダイアログの生成に失敗しました。", ex);\r
136                         dispose();\r
137                         throw ex;\r
138                 }\r
139         }\r
140         \r
141         private void initComponent() {\r
142                 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
143                         .getLocalizedProperties("languages/selectCharatersDirDialog");\r
144                 \r
145                 Container contentPane = getContentPane();\r
146                 contentPane.setLayout(new BorderLayout(3, 3));\r
147                 \r
148                 AbstractAction actOk = new AbstractAction(strings.getProperty("btn.ok")) {\r
149                         private static final long serialVersionUID = 1L;\r
150                         public void actionPerformed(ActionEvent e) {\r
151                                 onOK();\r
152                         }\r
153                 };\r
154                 \r
155                 AbstractAction actClose = new AbstractAction(strings.getProperty("btn.cancel")) {\r
156                         private static final long serialVersionUID = 1L;\r
157                         public void actionPerformed(ActionEvent e) {\r
158                                 onClose();\r
159                         }\r
160                 };\r
161 \r
162                 AbstractAction actBrowse = new AbstractAction(strings.getProperty("btn.chooseDir")) {\r
163                         private static final long serialVersionUID = 1L;\r
164                         public void actionPerformed(ActionEvent e) {\r
165                                 onBrowse();\r
166                         }\r
167                 };\r
168 \r
169                 AbstractAction actRemoveRecent = new AbstractAction(strings.getProperty("btn.clearRecentList")) {\r
170                         private static final long serialVersionUID = 1L;\r
171                         public void actionPerformed(ActionEvent e) {\r
172                                 onRemoveRecent();\r
173                         }\r
174                 };\r
175 \r
176                 AbstractAction actRemoveWorkingSets = new AbstractAction(\r
177                                 strings.getProperty("btn.clearWorkingSets")) {\r
178                         private static final long serialVersionUID = 1L;\r
179                         public void actionPerformed(ActionEvent e) {\r
180                                 onRemoveWorkingSets();\r
181                         }\r
182                 };\r
183 \r
184                 final JButton btnRemoveWorkingSets = new JButton(actRemoveWorkingSets);\r
185                 final JButton btnRemoveRecent = new JButton(actRemoveRecent);\r
186                 final JButton btnOK = new JButton(actOk);\r
187                 final JButton btnCancel = new JButton(actClose);\r
188                 final JButton btnBroseForDir = new JButton(actBrowse);\r
189 \r
190                 Toolkit tk = Toolkit.getDefaultToolkit();\r
191                 final JRootPane rootPane = getRootPane();\r
192                 FocusAdapter focusAdapter = new FocusAdapter() {\r
193                         @Override\r
194                         public void focusGained(FocusEvent e) {\r
195                                 JButton btn = (JButton) e.getSource();\r
196                                 rootPane.setDefaultButton(btn);\r
197                         }\r
198                         @Override\r
199                         public void focusLost(FocusEvent e) {\r
200                                 rootPane.setDefaultButton(btnOK);\r
201                         }\r
202                 };\r
203                 rootPane.setDefaultButton(btnOK);\r
204                 InputMap im = rootPane.getInputMap();\r
205                 im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close");\r
206                 im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, tk.getMenuShortcutKeyMask()), "close");\r
207                 rootPane.getActionMap().put("close", actClose);\r
208                 \r
209                 btnRemoveWorkingSets.addFocusListener(focusAdapter);\r
210                 btnRemoveRecent.addFocusListener(focusAdapter);\r
211                 btnOK.addFocusListener(focusAdapter);\r
212                 btnCancel.addFocusListener(focusAdapter);\r
213                 btnBroseForDir.addFocusListener(focusAdapter);\r
214 \r
215 \r
216                 JPanel dirPanel = new JPanel(new BorderLayout(3, 3));\r
217                 dirPanel.setBorder(BorderFactory.createEmptyBorder(3, 10, 3, 3));\r
218                 \r
219                 JLabel lbl = new JLabel(strings.getProperty("caption"), JLabel.CENTER);\r
220                 lbl.setFont(lbl.getFont().deriveFont(Font.BOLD));\r
221                 lbl.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));\r
222                 Dimension dim = lbl.getPreferredSize();\r
223                 dim.width = Integer.parseInt(strings.getProperty("width"));\r
224                 lbl.setPreferredSize(dim);\r
225                 dirPanel.add(lbl, BorderLayout.NORTH);\r
226 \r
227                 combDir = new JComboBox();\r
228                 combDir.setEditable(true);\r
229                 \r
230                 dirPanel.add(combDir, BorderLayout.CENTER);\r
231                 \r
232                 dirPanel.add(new JLabel(strings.getProperty("lbl.dir")), BorderLayout.WEST);\r
233                 dirPanel.add(btnBroseForDir, BorderLayout.EAST);\r
234                 \r
235                 contentPane.add(dirPanel, BorderLayout.NORTH);\r
236                 \r
237                 JPanel btnPanel = new JPanel();\r
238                 GridBagLayout gbl = new GridBagLayout();\r
239                 btnPanel.setLayout(gbl);\r
240                 \r
241                 chkDoNotAsk = new JCheckBox(strings.getProperty("chk.doNotAskAgein"));\r
242                 chkDoNotAsk.setSelected(recentCharactersDir.isDoNotAskAgain());\r
243                 \r
244                 GridBagConstraints gbc = new GridBagConstraints();\r
245                 gbc.gridx = 0;\r
246                 gbc.gridy = 0;\r
247                 gbc.gridwidth = 5;\r
248                 gbc.gridheight = 1;\r
249                 gbc.weightx = 1.;\r
250                 gbc.weighty = 0.;\r
251                 gbc.fill = GridBagConstraints.BOTH;\r
252                 gbc.anchor = GridBagConstraints.WEST;\r
253                 gbc.ipadx = 0;\r
254                 gbc.ipady = 0;\r
255                 gbc.insets = new Insets(3, 3, 3, 3);\r
256                 \r
257                 btnPanel.add(chkDoNotAsk, gbc);\r
258 \r
259                 gbc.gridx = 0;\r
260                 gbc.gridy = 1;\r
261                 gbc.gridwidth = 1;\r
262                 gbc.gridheight = 1;\r
263                 gbc.weightx = 0.;\r
264                 gbc.weighty = 0.;\r
265                 btnPanel.add(btnRemoveRecent, gbc);\r
266 \r
267                 gbc.gridx = 1;\r
268                 gbc.gridy = 1;\r
269                 gbc.gridwidth = 1;\r
270                 gbc.gridheight = 1;\r
271                 gbc.weightx = 0.;\r
272                 gbc.weighty = 0.;\r
273                 btnPanel.add(btnRemoveWorkingSets, gbc);\r
274 \r
275                 gbc.gridx = 2;\r
276                 gbc.gridy = 1;\r
277                 gbc.gridwidth = 1;\r
278                 gbc.gridheight = 1;\r
279                 gbc.weightx = 1.;\r
280                 gbc.weighty = 0.;\r
281                 \r
282                 btnPanel.add(Box.createGlue(), gbc);\r
283 \r
284                 gbc.gridx = Main.isLinuxOrMacOSX() ? 4 : 3;\r
285                 gbc.gridy = 1;\r
286                 gbc.gridwidth = 1;\r
287                 gbc.gridheight = 1;\r
288                 gbc.weightx = 0.;\r
289                 gbc.weighty = 0.;\r
290 \r
291                 btnPanel.add(btnOK, gbc);\r
292 \r
293 \r
294                 gbc.gridx = Main.isLinuxOrMacOSX() ? 3 : 4;\r
295                 gbc.gridy = 1;\r
296                 gbc.gridwidth = 1;\r
297                 gbc.gridheight = 1;\r
298                 gbc.weightx = 0.;\r
299                 gbc.weighty = 0.;\r
300                 btnPanel.add(btnCancel, gbc);\r
301                 \r
302                 gbc.gridx = 5;\r
303                 gbc.gridy = 1;\r
304                 gbc.gridwidth = 1;\r
305                 gbc.gridheight = 1;\r
306                 gbc.weightx = 0.;\r
307                 gbc.weighty = 0.;\r
308                 gbc.ipadx = 32;\r
309                 gbc.ipady = 0;\r
310                 \r
311                 btnPanel.add(Box.createGlue(), gbc);\r
312 \r
313                 setTitle(strings.getProperty("title"));\r
314                 setResizable(false);\r
315                 \r
316                 contentPane.add(btnPanel, BorderLayout.SOUTH);\r
317 \r
318                 // フォルダのドロップによる入力を許可\r
319                 new DropTarget(this, new FileDropTarget() {\r
320                         @Override\r
321                         protected void onDropFiles(List<File> dropFiles) {\r
322                                 setSelectFile(dropFiles);\r
323                         }\r
324 \r
325                         @Override\r
326                         protected void onException(Exception ex) {\r
327                                 ErrorMessageHelper.showErrorDialog(SelectCharatersDirDialog.this, ex);\r
328                         }\r
329                 });\r
330 \r
331                 pack();\r
332                 setLocationRelativeTo(null);\r
333         }\r
334         \r
335         /**\r
336          * ドロップによるファイル名の設定.<br>\r
337          * 最初の1つだけを使用する.<br>\r
338          * リストが空であるか、最初のファイルが、フォルダでなければ何もしない.<br>\r
339          * \r
340          * @param dropFiles\r
341          *            ドロップされたファイルリスト\r
342          */\r
343         protected void setSelectFile(List<File> dropFiles) {\r
344                 if (dropFiles.isEmpty()) {\r
345                         return;\r
346                 }\r
347                 File dropFile = dropFiles.get(0);\r
348                 if ( !dropFile.exists() || !dropFile.isDirectory()) {\r
349                         return;\r
350                 }\r
351                 combDir.setSelectedItem(dropFile);\r
352         }\r
353 \r
354         protected void onClose() {\r
355                 selectedCharacterDir = null;\r
356                 dispose();\r
357         }\r
358         \r
359         protected void onOK() {\r
360                 try {\r
361                         Object value = combDir.getSelectedItem();\r
362                         if (value != null && value instanceof String) {\r
363                                 value = new File((String) value);\r
364                         }\r
365                         \r
366                         if (value != null && value instanceof File) {\r
367                                 File file = (File) value;\r
368                                 if (!file.exists()) {\r
369                                         boolean result = file.mkdirs();\r
370                                         logger.log(Level.INFO, "mkdirs(" + file+ ") succeeded=" + result);\r
371                                 }\r
372                                 if (file.isDirectory()) {\r
373                                         logger.log(Level.CONFIG, "selectedCharactersDir=" + file);\r
374                                         selectedCharacterDir = file;\r
375                                         doNotAskAgain = chkDoNotAsk.isSelected();\r
376                                         dispose();\r
377                                         return;\r
378                                 }\r
379                         }\r
380 \r
381                         // 選択されていないかファイルでない場合\r
382                         Toolkit tk = Toolkit.getDefaultToolkit();\r
383                         tk.beep();\r
384 \r
385                 } catch (Exception ex) {\r
386                         ErrorMessageHelper.showErrorDialog(this, ex);\r
387                 }\r
388         }\r
389         \r
390         protected void onBrowse() {\r
391                 try {\r
392                         Object selectedItem = combDir.getSelectedItem();\r
393                         String directoryTxt = null;\r
394                         if (selectedItem != null) {\r
395                                 directoryTxt = selectedItem.toString();\r
396                         }\r
397                         JFileChooser dirChooser = new JFileChooser(directoryTxt);\r
398                         dirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);\r
399 \r
400                         if (dirChooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) {\r
401                                 return;\r
402                         }\r
403                         File dir = dirChooser.getSelectedFile();\r
404                         if (dir != null) {\r
405                                 combDir.setSelectedItem(dir);\r
406                         }\r
407 \r
408                 } catch (Exception ex) {\r
409                         ErrorMessageHelper.showErrorDialog(this, ex);\r
410                 }\r
411         }\r
412 \r
413         protected void onRemoveWorkingSets() {\r
414                 try {\r
415                         Properties strings = LocalizedResourcePropertyLoader\r
416                                         .getCachedInstance().getLocalizedProperties(\r
417                                                         "languages/selectCharatersDirDialog");\r
418 \r
419                         // 削除の確認ダイアログ\r
420                         if (JOptionPane.showConfirmDialog(this,\r
421                                         strings.getProperty("confirm.clearWorkingSets"),\r
422                                         strings.getProperty("confirm.clearWorkingSets.title"),\r
423                                         JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION) {\r
424                                 return;\r
425                         }\r
426 \r
427                         // 全てのワーキングセットをクリアする.\r
428                         WorkingSetPersist workingSetPersist = WorkingSetPersist\r
429                                         .getInstance();\r
430                         workingSetPersist.removeAllWorkingSet();\r
431 \r
432                 } catch (Exception ex) {\r
433                         ErrorMessageHelper.showErrorDialog(this, ex);\r
434                 }\r
435         }\r
436         \r
437         protected void onRemoveRecent() {\r
438                 try {\r
439                         Object current = combDir.getSelectedItem();\r
440 \r
441                         recentCharactersDir.clrar();\r
442                         setRecents();\r
443 \r
444                         if (current != null) {\r
445                                 combDir.setSelectedItem(current);\r
446                         }\r
447 \r
448                 } catch (Exception ex) {\r
449                         ErrorMessageHelper.showErrorDialog(this, ex);\r
450                 }\r
451         }\r
452         \r
453         protected void setRecents() {\r
454                 // 現在の候補をクリア.\r
455                 while (combDir.getItemCount() > 0) {\r
456                         combDir.removeItemAt(0);\r
457                 }\r
458 \r
459                 // 前回使用したディレクトリを最優先候補\r
460                 ArrayList<File> priorityDirs = new ArrayList<File>();\r
461                 File lastUseCatacterDir = recentCharactersDir.getLastUseCharacterDir();\r
462                 if (lastUseCatacterDir != null) {\r
463                         if (defaultCharactersDir != null && !lastUseCatacterDir.equals(defaultCharactersDir)) {\r
464                                 combDir.addItem(lastUseCatacterDir);\r
465                                 priorityDirs.add(lastUseCatacterDir);\r
466                         }\r
467                 }\r
468                 // デフォルトのキャラクターデータを第2位に設定\r
469                 if (defaultCharactersDir != null) {\r
470                         combDir.addItem(defaultCharactersDir);\r
471                         priorityDirs.add(defaultCharactersDir);\r
472                 }\r
473                 // それ以外の履歴を設定\r
474                 for (File charactersDir : recentCharactersDir\r
475                                 .getRecentCharacterDirsOrderByNewly()) {\r
476                         if (charactersDir == null) {\r
477                                 continue;\r
478                         }\r
479                         if (!priorityDirs.contains(charactersDir)) {\r
480                                 combDir.addItem(charactersDir);\r
481                         }\r
482                 }\r
483                 // 第一候補を選択状態とする.\r
484                 if (combDir.getItemCount() > 0) {\r
485                         combDir.setSelectedIndex(0);\r
486                 }\r
487         }\r
488         \r
489 \r
490         /**\r
491          * キャラクターデータディレクトリを履歴および既定のディレクトリから、任意の使用するディレクトリを選択する.<br>\r
492          * 既定のディレクトリは常に選択候補とする.<br>\r
493          * 新しいディレクトリを指定した場合は、履歴に追加される.<br>\r
494          * 「再度問い合わせなし」を選択している場合で、そのディレクトリが実在すれば、選択ダイアログを表示せず、それを返す.<br>\r
495          * \r
496          * @param defaultCharacterDir\r
497          *            既定のディレクトリ\r
498          * @return 選択したディレクトリ、キャンセルした場合はnull\r
499          */\r
500         public static File getCharacterDir(File defaultCharacterDir) {\r
501                 RecentCharactersDir recentChars;\r
502                 try {\r
503                         recentChars = RecentCharactersDir.load();\r
504 \r
505                 } catch (Exception ex) {\r
506                         logger.log(Level.WARNING, "最後に使用したキャラクターディレクトリ情報の読み込みに失敗しました。", ex);\r
507                         recentChars = null;\r
508                 }\r
509                 if (recentChars == null) {\r
510                         recentChars = new RecentCharactersDir();\r
511                 }\r
512 \r
513                 logger.log(Level.CONFIG, "RecentCharacterDirs.doNotAskAgain=" + recentChars.isDoNotAskAgain());\r
514                 if (recentChars.isDoNotAskAgain()) {\r
515                         // 「再度問い合わせ無し」の場合で、過去のディレクトリが有効であれば、それを返す.\r
516                         File recentCharDir = recentChars.getLastUseCharacterDir();\r
517                         if (recentCharDir != null && recentCharDir.exists() && recentCharDir.isDirectory()) {\r
518                                 return recentCharDir;\r
519                         }\r
520                         recentChars.setDoNotAskAgain(false); // 不正である場合は「再度問い合わせ無し」をリセットする.\r
521                 }\r
522 \r
523                 File selectedCharacterDir;\r
524                 SelectCharatersDirDialog dlg = new SelectCharatersDirDialog(null, recentChars);\r
525                 dlg.setDefaultCharactersDir(defaultCharacterDir);\r
526                 dlg.setRecents();\r
527                 dlg.setVisible(true);\r
528                 \r
529                 selectedCharacterDir = dlg.getSelectedCharacterDir();\r
530                 if (selectedCharacterDir != null) {\r
531                         recentChars.setLastUseCharacterDir(selectedCharacterDir);\r
532                         try {\r
533                                 recentChars.setDoNotAskAgain(dlg.isDoNotAskAgain());\r
534                                 recentChars.saveRecents();\r
535 \r
536                         } catch (Exception ex) {\r
537                                 logger.log(Level.WARNING, "最後に使用したキャラクターディレクトリ情報の保存に失敗しました。",\r
538                                                 ex);\r
539                         }\r
540                 }\r
541                 return selectedCharacterDir;\r
542         }\r
543 }\r