OSDN Git Service

mavenによるビルドに変更
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / ui / PartsManageDialog.java
1 package charactermanaj.ui;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.Color;\r
5 import java.awt.Component;\r
6 import java.awt.Container;\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.event.ActionEvent;\r
12 import java.awt.event.KeyEvent;\r
13 import java.awt.event.WindowAdapter;\r
14 import java.awt.event.WindowEvent;\r
15 import java.net.URI;\r
16 import java.sql.Timestamp;\r
17 import java.util.Arrays;\r
18 import java.util.Collections;\r
19 import java.util.Comparator;\r
20 import java.util.HashMap;\r
21 import java.util.HashSet;\r
22 import java.util.Map;\r
23 import java.util.Properties;\r
24 import java.util.concurrent.Semaphore;\r
25 import java.util.logging.Level;\r
26 import java.util.logging.Logger;\r
27 \r
28 import javax.swing.AbstractAction;\r
29 import javax.swing.Action;\r
30 import javax.swing.ActionMap;\r
31 import javax.swing.BorderFactory;\r
32 import javax.swing.Box;\r
33 import javax.swing.InputMap;\r
34 import javax.swing.JButton;\r
35 import javax.swing.JComponent;\r
36 import javax.swing.JDialog;\r
37 import javax.swing.JFrame;\r
38 import javax.swing.JLabel;\r
39 import javax.swing.JOptionPane;\r
40 import javax.swing.JPanel;\r
41 import javax.swing.JPopupMenu;\r
42 import javax.swing.JRootPane;\r
43 import javax.swing.JScrollPane;\r
44 import javax.swing.JSeparator;\r
45 import javax.swing.JTable;\r
46 import javax.swing.JTextField;\r
47 import javax.swing.KeyStroke;\r
48 import javax.swing.UIManager;\r
49 import javax.swing.event.DocumentEvent;\r
50 import javax.swing.event.DocumentListener;\r
51 import javax.swing.event.ListSelectionEvent;\r
52 import javax.swing.event.ListSelectionListener;\r
53 import javax.swing.event.TableModelEvent;\r
54 import javax.swing.event.TableModelListener;\r
55 import javax.swing.table.TableCellRenderer;\r
56 import javax.swing.table.TableColumnModel;\r
57 \r
58 import charactermanaj.Main;\r
59 import charactermanaj.model.AppConfig;\r
60 import charactermanaj.model.CharacterData;\r
61 import charactermanaj.model.PartsAuthorInfo;\r
62 import charactermanaj.model.PartsCategory;\r
63 import charactermanaj.model.PartsIdentifier;\r
64 import charactermanaj.model.PartsManageData;\r
65 import charactermanaj.model.PartsManageData.PartsKey;\r
66 import charactermanaj.model.PartsManageData.PartsVersionInfo;\r
67 import charactermanaj.model.PartsSpec;\r
68 import charactermanaj.model.io.PartsInfoXMLReader;\r
69 import charactermanaj.model.io.PartsInfoXMLWriter;\r
70 import charactermanaj.ui.model.AbstractTableModelWithComboBoxModel;\r
71 import charactermanaj.util.DesktopUtilities;\r
72 import charactermanaj.util.ErrorMessageHelper;\r
73 import charactermanaj.util.LocalizedResourcePropertyLoader;\r
74 \r
75 public class PartsManageDialog extends JDialog {\r
76 \r
77         private static final long serialVersionUID = 1L;\r
78         \r
79         protected static final String STRINGS_RESOURCE = "languages/partsmanagedialog";\r
80         \r
81         \r
82         private static final Logger logger = Logger.getLogger(PartsManageDialog.class.getName());\r
83 \r
84         private CharacterData characterData;\r
85         \r
86         private PartsManageTableModel partsManageTableModel;\r
87         \r
88         private JTable partsManageTable;\r
89         \r
90         private JTextField txtHomepage;\r
91         \r
92         private JTextField txtAuthor;\r
93         \r
94         private boolean updated;\r
95 \r
96         \r
97         public PartsManageDialog(JFrame parent, CharacterData characterData) {\r
98                 super(parent, true);\r
99                 \r
100                 if (characterData == null) {\r
101                         throw new IllegalArgumentException();\r
102                 }\r
103                 this.characterData = characterData;\r
104                 \r
105                 setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);\r
106                 addWindowListener(new WindowAdapter() {\r
107                         @Override\r
108                         public void windowClosing(WindowEvent e) {\r
109                                 onClose();\r
110                         }\r
111                 });\r
112 \r
113                 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
114                                 .getLocalizedProperties(STRINGS_RESOURCE);\r
115 \r
116                 setTitle(strings.getProperty("title"));\r
117 \r
118                 Container contentPane = getContentPane();\r
119                 \r
120                 // パーツリストテーブル\r
121                 JPanel partsListPanel = new JPanel();\r
122                 partsListPanel.setBorder(BorderFactory.createCompoundBorder(\r
123                                 BorderFactory.createEmptyBorder(5, 5, 5, 5), BorderFactory\r
124                                                 .createTitledBorder(strings.getProperty("partslist"))));\r
125 \r
126                 GridBagLayout partsListPanelLayout = new GridBagLayout();\r
127                 partsListPanel.setLayout(partsListPanelLayout);\r
128                 \r
129                 partsManageTableModel = new PartsManageTableModel();\r
130                 partsManageTable = new JTable(partsManageTableModel) {\r
131                         private static final long serialVersionUID = 1L;\r
132 \r
133                         @Override\r
134                         public Component prepareRenderer(TableCellRenderer renderer,\r
135                                         int rowIdx, int columnIdx) {\r
136                                 PartsManageTableModel.Columns column = PartsManageTableModel.Columns\r
137                                                 .values()[columnIdx];\r
138                                 Component comp = super.prepareRenderer(renderer, rowIdx, columnIdx);\r
139                                 PartsManageTableRow row = partsManageTableModel.getRow(rowIdx);\r
140 \r
141                                 Timestamp current = row.getTimestamp();\r
142                                 Timestamp lastModified = row.getLastModified();\r
143 \r
144                                 boolean warnings = false;\r
145 \r
146                                 if (current != null && !current.equals(lastModified)) {\r
147                                         // 現在のパーツの最終更新日と、パーツ管理情報の作成時のパーツの最終更新日が不一致の場合\r
148                                         warnings = true;\r
149                                 }\r
150 \r
151                                 // 背景色、警告行は赤色に\r
152                                 if (warnings && column == PartsManageTableModel.Columns.LastModified) {\r
153                                         AppConfig appConfig = AppConfig.getInstance();\r
154                                         Color invalidBgColor = appConfig.getInvalidBgColor();\r
155                                         comp.setBackground(invalidBgColor);\r
156                                 } else {\r
157                                         if (isCellSelected(rowIdx, columnIdx)) {\r
158                                                 comp.setBackground(getSelectionBackground());\r
159                                         } else {\r
160                                                 comp.setBackground(getBackground());\r
161                                         }\r
162                                 }\r
163 \r
164                                 return comp;\r
165                         }\r
166                 };\r
167                 partsManageTable.setShowGrid(true);\r
168                 partsManageTable.setGridColor(AppConfig.getInstance().getGridColor());\r
169                 partsManageTableModel.adjustColumnModel(partsManageTable.getColumnModel());\r
170                 partsManageTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);\r
171                 partsManageTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);\r
172 \r
173                 JScrollPane partsManageTableSP = new JScrollPane(partsManageTable);\r
174                 \r
175                 partsManageTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
176                         public void valueChanged(ListSelectionEvent e) {\r
177                                 if (!e.getValueIsAdjusting()) {\r
178                                         onChangeSelection();\r
179                                 }\r
180                         }\r
181                 });\r
182                 \r
183                 partsManageTableModel.addTableModelListener(new TableModelListener() {\r
184                         public void tableChanged(TableModelEvent e) {\r
185                                 onTableDataChange(e.getFirstRow(), e.getLastRow());\r
186                         }\r
187                 });\r
188                 \r
189                 GridBagConstraints gbc = new GridBagConstraints();\r
190                 gbc.gridx = 0;\r
191                 gbc.gridy = 0;\r
192                 gbc.gridheight = 1;\r
193                 gbc.gridwidth = 4;\r
194                 gbc.anchor = GridBagConstraints.EAST;\r
195                 gbc.fill = GridBagConstraints.BOTH;\r
196                 gbc.insets = new Insets(3, 3, 3, 3);\r
197                 gbc.ipadx = 0;\r
198                 gbc.ipady = 0;\r
199                 gbc.weightx = 1.;\r
200                 gbc.weighty = 1.;\r
201                 partsListPanel.add(partsManageTableSP, gbc);\r
202                 \r
203                 Action actSortByName = new AbstractAction(strings.getProperty("sortByName")) {\r
204                         private static final long serialVersionUID = 1L;\r
205                         public void actionPerformed(ActionEvent e) {\r
206                                 onSortByName();\r
207                         }\r
208                 };\r
209                 Action actSortByAuthor = new AbstractAction(strings.getProperty("sortByAuthor")) {\r
210                         private static final long serialVersionUID = 1L;\r
211                         public void actionPerformed(ActionEvent e) {\r
212                                 onSortByAuthor();\r
213                         }\r
214                 };\r
215                 Action actSortByTimestamp = new AbstractAction(strings.getProperty("sortByTimestamp")) {\r
216                         private static final long serialVersionUID = 1L;\r
217                         public void actionPerformed(ActionEvent e) {\r
218                                 onSortByTimestamp();\r
219                         }\r
220                 };\r
221                 \r
222                 gbc.gridx = 0;\r
223                 gbc.gridy = 1;\r
224                 gbc.gridheight = 1;\r
225                 gbc.gridwidth = 1;\r
226                 gbc.weightx = 0.;\r
227                 gbc.weighty = 0.;\r
228                 partsListPanel.add(new JButton(actSortByName), gbc);\r
229 \r
230                 gbc.gridx = 1;\r
231                 gbc.gridy = 1;\r
232                 gbc.weightx = 0.;\r
233                 gbc.weighty = 0.;\r
234                 partsListPanel.add(new JButton(actSortByAuthor), gbc);\r
235 \r
236                 gbc.gridx = 2;\r
237                 gbc.gridy = 1;\r
238                 gbc.weightx = 0.;\r
239                 gbc.weighty = 0.;\r
240                 partsListPanel.add(new JButton(actSortByTimestamp), gbc);\r
241 \r
242                 gbc.gridx = 3;\r
243                 gbc.gridy = 1;\r
244                 gbc.weightx = 1.;\r
245                 gbc.weighty = 0.;\r
246                 partsListPanel.add(Box.createHorizontalGlue(), gbc);\r
247 \r
248                 contentPane.add(partsListPanel, BorderLayout.CENTER);\r
249 \r
250                 // テーブルのコンテキストメニュー\r
251                 final JPopupMenu popupMenu = new JPopupMenu();\r
252                 Action actApplyAllLastModified = new AbstractAction(strings.getProperty("applyAllLastModified")) {\r
253                         private static final long serialVersionUID = 1L;\r
254                         public void actionPerformed(ActionEvent e) {\r
255                                 onApplyAllLastModified();\r
256                         }\r
257                 };\r
258                 Action actApplyAllDownloadURL = new AbstractAction(strings.getProperty("applyAllDownloadURL")) {\r
259                         private static final long serialVersionUID = 1L;\r
260                         public void actionPerformed(ActionEvent e) {\r
261                                 onApplyAllDownloadURL();\r
262                         }\r
263                 };\r
264                 Action actApplyAllVersion = new AbstractAction(strings.getProperty("applyAllVersion")) {\r
265                         private static final long serialVersionUID = 1L;\r
266                         public void actionPerformed(ActionEvent e) {\r
267                                 onApplyAllVersion();\r
268                         }\r
269                 };\r
270                 popupMenu.add(actApplyAllLastModified);\r
271                 popupMenu.add(new JSeparator());\r
272                 popupMenu.add(actApplyAllVersion);\r
273                 popupMenu.add(actApplyAllDownloadURL);\r
274                 \r
275                 partsManageTable.setComponentPopupMenu(popupMenu);\r
276                 \r
277                 // 作者情報パネル\r
278                 JPanel authorPanel = new JPanel();\r
279                 authorPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory\r
280                                 .createEmptyBorder(5, 5, 5, 5), BorderFactory\r
281                                 .createTitledBorder(strings.getProperty("author.info"))));\r
282                 GridBagLayout authorPanelLayout = new GridBagLayout();\r
283                 authorPanel.setLayout(authorPanelLayout);\r
284                 \r
285                 gbc.gridx = 0;\r
286                 gbc.gridy = 0;\r
287                 gbc.gridheight = 1;\r
288                 gbc.gridwidth = 1;\r
289                 gbc.anchor = GridBagConstraints.EAST;\r
290                 gbc.fill = GridBagConstraints.BOTH;\r
291                 gbc.insets = new Insets(3, 3, 3, 3);\r
292                 gbc.ipadx = 0;\r
293                 gbc.ipady = 0;\r
294                 gbc.weightx = 0.;\r
295                 gbc.weighty = 0.;\r
296                 authorPanel.add(new JLabel(strings.getProperty("author"), JLabel.RIGHT), gbc);\r
297 \r
298                 gbc.gridx = 1;\r
299                 gbc.gridy = 0;\r
300                 gbc.gridwidth = 2;\r
301                 gbc.weightx = 1.;\r
302                 txtAuthor = new JTextField();\r
303                 authorPanel.add(txtAuthor, gbc);\r
304 \r
305                 gbc.gridx = 0;\r
306                 gbc.gridy = 1;\r
307                 gbc.gridwidth = 1;\r
308                 gbc.weightx = 0.;\r
309                 authorPanel.add(new JLabel(strings.getProperty("homepage"), JLabel.RIGHT), gbc);\r
310 \r
311                 gbc.gridx = 1;\r
312                 gbc.gridy = 1;\r
313                 gbc.gridwidth = 1;\r
314                 gbc.weightx = 1.;\r
315                 txtHomepage = new JTextField();\r
316                 authorPanel.add(txtHomepage, gbc);\r
317 \r
318                 gbc.gridx = 2;\r
319                 gbc.gridy = 1;\r
320                 gbc.gridwidth = 1;\r
321                 gbc.weightx = 0.;\r
322                 Action actBrowseHomepage = new AbstractAction(strings.getProperty("open")) {\r
323                         private static final long serialVersionUID = 1L;\r
324                         public void actionPerformed(ActionEvent e) {\r
325                                 onBrosweHomepage();\r
326                         }\r
327                 };\r
328                 authorPanel.add(new JButton(actBrowseHomepage), gbc);\r
329 \r
330                 if (!DesktopUtilities.isSupported()) {\r
331                         actBrowseHomepage.setEnabled(false);\r
332                 }\r
333                 \r
334                 txtAuthor.getDocument().addDocumentListener(new DocumentListener() {\r
335                         public void removeUpdate(DocumentEvent e) {\r
336                                 onEditAuthor();\r
337                         }\r
338                         public void insertUpdate(DocumentEvent e) {\r
339                                 onEditAuthor();\r
340                         }\r
341                         public void changedUpdate(DocumentEvent e) {\r
342                                 onEditAuthor();\r
343                         }\r
344                 });\r
345                 txtHomepage.getDocument().addDocumentListener(new DocumentListener() {\r
346                         public void removeUpdate(DocumentEvent e) {\r
347                                 onEditHomepage();\r
348                         }\r
349                         public void insertUpdate(DocumentEvent e) {\r
350                                 onEditHomepage();\r
351                         }\r
352                         public void changedUpdate(DocumentEvent e) {\r
353                                 onEditHomepage();\r
354                         }\r
355                 });\r
356                 \r
357                 \r
358                 // ボタンパネル\r
359                 JPanel btnPanel = new JPanel();\r
360                 btnPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 45));\r
361                 GridBagLayout btnPanelLayout = new GridBagLayout();\r
362                 btnPanel.setLayout(btnPanelLayout);\r
363                 \r
364                 Action actClose = new AbstractAction(strings.getProperty("cancel")) {\r
365                         private static final long serialVersionUID = 1L;\r
366                         public void actionPerformed(ActionEvent e) {\r
367                                 onClose();\r
368                         }\r
369                 };\r
370                 Action actOK = new AbstractAction(strings.getProperty("update")) {\r
371                         private static final long serialVersionUID = 1L;\r
372                         public void actionPerformed(ActionEvent e) {\r
373                                 onOK();\r
374                         }\r
375                 };\r
376                 \r
377                 gbc.gridx = 0;\r
378                 gbc.gridy = 0;\r
379                 gbc.weightx = 1.;\r
380                 btnPanel.add(Box.createHorizontalGlue(), gbc);\r
381                 \r
382                 gbc.gridx = Main.isLinuxOrMacOSX() ? 2 : 1;\r
383                 gbc.gridy = 0;\r
384                 gbc.weightx = 0.;\r
385                 btnPanel.add(new JButton(actOK), gbc);\r
386 \r
387                 gbc.gridx = Main.isLinuxOrMacOSX() ? 1 : 2;\r
388                 gbc.gridy = 0;\r
389                 gbc.weightx = 0.;\r
390                 btnPanel.add(new JButton(actClose), gbc);\r
391                 \r
392                 // ダイアログ下部\r
393                 JPanel southPanel = new JPanel(new BorderLayout());\r
394                 southPanel.add(authorPanel, BorderLayout.NORTH);\r
395                 southPanel.add(btnPanel, BorderLayout.SOUTH);\r
396 \r
397                 contentPane.add(southPanel, BorderLayout.SOUTH);\r
398                 \r
399                 // キーボード\r
400                 \r
401                 Toolkit tk = Toolkit.getDefaultToolkit();\r
402                 JRootPane rootPane = getRootPane();\r
403                 InputMap im = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);\r
404                 ActionMap am = rootPane.getActionMap();\r
405                 im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "closePartsManageDialog");\r
406                 im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, tk.getMenuShortcutKeyMask()), "closePartsManageDialog");\r
407                 am.put("closePartsManageDialog", actClose);\r
408 \r
409                 // モデル構築\r
410                 partsManageTableModel.initModel(characterData);\r
411                 \r
412                 // ウィンドウ配置\r
413                 setSize(500, 400);\r
414                 setLocationRelativeTo(parent);\r
415         }\r
416 \r
417         private Semaphore authorEditSemaphore = new Semaphore(1);\r
418         \r
419         protected void onChangeSelection() {\r
420                 try {\r
421                         authorEditSemaphore.acquire();\r
422                         try {\r
423                                 int [] selRows = partsManageTable.getSelectedRows();\r
424                                 HashSet<String> authors = new HashSet<String>();\r
425                                 for (int selRow : selRows) {\r
426                                         PartsManageTableRow row = partsManageTableModel.getRow(selRow);\r
427                                         authors.add(row.getAuthor() == null ? "" : row.getAuthor());\r
428                                 }\r
429                                 if (authors.size() > 1) {\r
430                                         AppConfig appConfig = AppConfig.getInstance();\r
431                                         txtAuthor.setBackground(appConfig.getAuthorEditConflictBgColor());\r
432                                         txtHomepage.setBackground(appConfig.getAuthorEditConflictBgColor());\r
433                                 } else {\r
434                                         Color bgColor = UIManager.getColor("TextField.background");\r
435                                         if (bgColor == null) {\r
436                                                 bgColor = Color.white;\r
437                                         }\r
438                                         txtAuthor.setBackground(bgColor);\r
439                                         txtHomepage.setBackground(bgColor);\r
440                                 }\r
441                                 if (authors.isEmpty()) {\r
442                                         // 選択されているauthorがない場合は全部編集不可\r
443                                         txtAuthor.setEditable(false);\r
444                                         txtAuthor.setText("");\r
445                                         txtHomepage.setEditable(false);\r
446                                         txtHomepage.setText("");\r
447                                 } else {\r
448                                         // 選択されているAuthorが1つ以上あればAuthorは編集可\r
449                                         txtAuthor.setEditable(true);\r
450                                         txtHomepage.setEditable(true);\r
451                                         if (authors.size() == 1) {\r
452                                                 // 選択されているAuthorが一個であれば、それを表示\r
453                                                 String author = authors.iterator().next();\r
454                                                 String homepage = partsManageTableModel.getHomepage(author);\r
455                                                 txtAuthor.setText(author);\r
456                                                 txtHomepage.setText(homepage);\r
457                                         } else {\r
458                                                 // 選択されているAuthorが二個以上あれば編集可能だがテキストには表示しない.\r
459                                                 txtAuthor.setText("");\r
460                                                 txtHomepage.setText("");\r
461                                         }\r
462                                 }\r
463                         } finally {\r
464                                 authorEditSemaphore.release();\r
465                         }\r
466 \r
467                 } catch (InterruptedException ex) {\r
468                         ErrorMessageHelper.showErrorDialog(this, ex);\r
469 \r
470                 } catch (RuntimeException ex) {\r
471                         ErrorMessageHelper.showErrorDialog(this, ex);\r
472                 }\r
473         }\r
474         \r
475         protected void onTableDataChange(int firstRow, int lastRow) {\r
476                 onChangeSelection();\r
477         }\r
478         \r
479         protected void onApplyAllLastModified() {\r
480                 int[] selRows = partsManageTable.getSelectedRows();\r
481                 if (selRows.length == 0) {\r
482                         Toolkit tk = Toolkit.getDefaultToolkit();\r
483                         tk.beep();\r
484                         return;\r
485                 }\r
486                 Arrays.sort(selRows);\r
487 \r
488                 for (int selRow : selRows) {\r
489                         PartsManageTableRow row = partsManageTableModel.getRow(selRow);\r
490                         Timestamp dt = row.getTimestamp();\r
491                         row.setLastModified(dt);\r
492                 }\r
493                 partsManageTableModel.fireTableRowsUpdated(selRows[0],\r
494                                 selRows[selRows.length - 1]);\r
495         }\r
496 \r
497         protected void onApplyAllDownloadURL() {\r
498                 int[] selRows = partsManageTable.getSelectedRows();\r
499                 if (selRows.length == 0) {\r
500                         Toolkit tk = Toolkit.getDefaultToolkit();\r
501                         tk.beep();\r
502                         return;\r
503                 }\r
504                 Arrays.sort(selRows);\r
505 \r
506                 HashSet<String> authors = new HashSet<String>();\r
507                 for (int selRow : selRows) {\r
508                         PartsManageTableRow row = partsManageTableModel.getRow(selRow);\r
509                         authors.add(row.getAuthor() == null ? "" : row.getAuthor());\r
510                 }\r
511 \r
512                 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
513                                 .getLocalizedProperties(STRINGS_RESOURCE);\r
514 \r
515                 if (authors.size() > 1) {\r
516                         if (JOptionPane.showConfirmDialog(this,\r
517                                         strings.getProperty("confirm.authorConflict"),\r
518                                         strings.getProperty("confirm"),\r
519                                         JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) {\r
520                                 return;\r
521                         }\r
522                 }\r
523                 \r
524                 PartsManageTableRow firstRow = partsManageTableModel.getRow(selRows[0]);\r
525                 String downloadURL = firstRow.getDownloadURL();\r
526                 if (downloadURL == null) {\r
527                         downloadURL = "";\r
528                 }\r
529                 String downloadURL_new = JOptionPane.showInputDialog(this, strings.getProperty("input.downloadURL"), downloadURL);\r
530                 if (downloadURL_new == null || downloadURL.equals(downloadURL_new)) {\r
531                         // キャンセルされたか、内容に変化ない場合は何もしない\r
532                         return;\r
533                 }\r
534                 \r
535                 for (int selRow : selRows) {\r
536                         PartsManageTableRow row = partsManageTableModel.getRow(selRow);\r
537                         row.setDownloadURL(downloadURL_new);\r
538 \r
539                         Timestamp dt = row.getTimestamp();\r
540                         row.setLastModified(dt);\r
541                 }\r
542                 partsManageTableModel.fireTableRowsUpdated(selRows[0], selRows[selRows.length - 1]);\r
543         }\r
544         \r
545         protected void onApplyAllVersion() {\r
546                 Toolkit tk = Toolkit.getDefaultToolkit();\r
547                 int[] selRows = partsManageTable.getSelectedRows();\r
548                 if (selRows.length == 0) {\r
549                         tk.beep();\r
550                         return;\r
551                 }\r
552                 Arrays.sort(selRows);\r
553 \r
554                 HashSet<String> authors = new HashSet<String>();\r
555                 for (int selRow : selRows) {\r
556                         PartsManageTableRow row = partsManageTableModel.getRow(selRow);\r
557                         authors.add(row.getAuthor() == null ? "" : row.getAuthor());\r
558                 }\r
559 \r
560                 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
561                                 .getLocalizedProperties(STRINGS_RESOURCE);\r
562 \r
563                 if (authors.size() > 1) {\r
564                         if (JOptionPane.showConfirmDialog(this,\r
565                                         strings.getProperty("confirm.authorConflict"),\r
566                                         strings.getProperty("confirm"),\r
567                                         JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION) {\r
568                                 return;\r
569                         }\r
570                 }\r
571 \r
572                 PartsManageTableRow firstRow = partsManageTableModel.getRow(selRows[0]);\r
573                 double version = firstRow.getVersion();\r
574                 String strVersion = (version < 0) ? "" : Double.toString(version);\r
575                 String strVersion_new = JOptionPane.showInputDialog(this,\r
576                                 strings.getProperty("input.version"), strVersion);\r
577                 if (strVersion_new == null || strVersion.equals(strVersion_new)) {\r
578                         // キャンセルされたか、内容に変化ない場合は何もしない\r
579                         return;\r
580                 }\r
581                 double version_new;\r
582                 try {\r
583                         version_new = Double.parseDouble(strVersion_new);\r
584                 } catch (Exception ex) {\r
585                         // 数値として不正であれば何もしない.\r
586                         tk.beep();\r
587                         return;\r
588                 }\r
589                 \r
590                 for (int selRow : selRows) {\r
591                         PartsManageTableRow row = partsManageTableModel.getRow(selRow);\r
592                         row.setVersion(version_new);\r
593 \r
594                         Timestamp dt = row.getTimestamp();\r
595                         row.setLastModified(dt);\r
596                 }\r
597                 partsManageTableModel.fireTableRowsUpdated(selRows[0], selRows[selRows.length - 1]);\r
598         }\r
599         \r
600         protected void onEditHomepage() {\r
601                 try {\r
602                         if (!authorEditSemaphore.tryAcquire()) {\r
603                                 return;\r
604                         }\r
605                         try {\r
606                                 String author = txtAuthor.getText();\r
607                                 String homepage = txtHomepage.getText();\r
608                                 partsManageTableModel.setHomepage(author, homepage);\r
609                         } finally {\r
610                                 authorEditSemaphore.release();\r
611                         }\r
612                 } catch (Exception ex) {\r
613                         ErrorMessageHelper.showErrorDialog(this, ex);\r
614                 }\r
615         }\r
616 \r
617         protected void onEditAuthor() {\r
618                 try {\r
619                         if (!authorEditSemaphore.tryAcquire()) {\r
620                                 return;\r
621                         }\r
622                         try {\r
623                                 String author = txtAuthor.getText();\r
624                                 int[] selRows = partsManageTable.getSelectedRows();\r
625                                 int firstRow = -1;\r
626                                 int lastRow = Integer.MAX_VALUE;\r
627                                 for (int selRow : selRows) {\r
628                                         PartsManageTableRow row = partsManageTableModel.getRow(selRow);\r
629                                         String oldValue = row.getAuthor();\r
630                                         if (oldValue == null || !oldValue.equals(author)) {\r
631                                                 row.setAuthor(author);\r
632 \r
633                                                 Timestamp dt = row.getTimestamp();\r
634                                                 row.setLastModified(dt);\r
635 \r
636                                                 firstRow = Math.max(firstRow, selRow);\r
637                                                 lastRow = Math.min(lastRow, selRow);\r
638                                         }\r
639                                 }\r
640                                 \r
641                                 String homepage = partsManageTableModel.getHomepage(author);\r
642                                 if (homepage == null) {\r
643                                         homepage = "";\r
644                                 }\r
645                                 txtHomepage.setText(homepage);\r
646                                 \r
647                                 if (firstRow >= 0) {\r
648                                         partsManageTable.repaint();\r
649                                 }\r
650                         } finally {\r
651                                 authorEditSemaphore.release();                          \r
652                         }\r
653                 } catch (Exception ex) {\r
654                         ErrorMessageHelper.showErrorDialog(this, ex);\r
655                 }\r
656         }\r
657         \r
658         protected void onClose() {\r
659                 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()\r
660                                 .getLocalizedProperties(STRINGS_RESOURCE);\r
661                 if (JOptionPane.showConfirmDialog(this,\r
662                                 strings.getProperty("confirm.cancel"),\r
663                                 strings.getProperty("confirm"),\r
664                                 JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {\r
665                         return;\r
666                 }\r
667                 updated = false;\r
668                 dispose();\r
669         }\r
670         \r
671         protected void onBrosweHomepage() {\r
672                 Toolkit tk = Toolkit.getDefaultToolkit();\r
673                 String homepage = txtHomepage.getText();\r
674                 if (homepage == null || homepage.trim().length() == 0) {\r
675                         tk.beep();\r
676                         return;\r
677                 }\r
678                 try {\r
679                         URI uri = new URI(homepage);\r
680                         DesktopUtilities.browse(uri);\r
681 \r
682                 } catch (Exception ex) {\r
683                         tk.beep();\r
684                         logger.log(Level.INFO, "browse failed. : " + homepage, ex);\r
685                 }\r
686         }\r
687         \r
688         protected void onSortByAuthor() {\r
689                 partsManageTableModel.sortByAuthor();\r
690         }\r
691         \r
692         protected void onSortByName() {\r
693                 partsManageTableModel.sortByName();\r
694         }\r
695         \r
696         protected void onSortByTimestamp() {\r
697                 partsManageTableModel.sortByTimestamp();\r
698         }\r
699         \r
700         protected void onOK() {\r
701                 if (partsManageTable.isEditing()) {\r
702                         Toolkit tk = Toolkit.getDefaultToolkit();\r
703                         tk.beep();\r
704                         return;\r
705                 }\r
706                 \r
707                 int mx = partsManageTableModel.getRowCount();\r
708 \r
709                 // 作者ごとのホームページ情報の取得\r
710                 // (同一作者につきホームページは一つ)\r
711                 HashMap<String, PartsAuthorInfo> authorInfoMap = new HashMap<String, PartsAuthorInfo>();\r
712                 for (int idx = 0; idx < mx; idx++) {\r
713                         PartsManageTableRow row = partsManageTableModel.getRow(idx);\r
714                         String author = row.getAuthor();\r
715                         String homepage = row.getHomepage();\r
716                         if (author != null && author.trim().length() > 0) {\r
717                                 PartsAuthorInfo authorInfo = authorInfoMap.get(author.trim());\r
718                                 if (authorInfo == null) {\r
719                                         authorInfo = new PartsAuthorInfo();\r
720                                         authorInfo.setAuthor(author.trim());\r
721                                         authorInfoMap.put(authorInfo.getAuthor(), authorInfo);\r
722                                 }\r
723                                 authorInfo.setHomePage(homepage);\r
724                         }\r
725                 }\r
726 \r
727                 PartsManageData partsManageData = new PartsManageData();\r
728                 \r
729                 // パーツごとの作者とバージョン、ダウンロード先の取得\r
730                 for (int idx = 0; idx < mx; idx++) {\r
731                         PartsManageTableRow row = partsManageTableModel.getRow(idx);\r
732                         \r
733                         String author = row.getAuthor();\r
734                         PartsAuthorInfo partsAuthorInfo = null;\r
735                         if (author != null && author.trim().length() > 0) {\r
736                                 partsAuthorInfo = authorInfoMap.get(author.trim());\r
737                         }\r
738                         \r
739                         double version = row.getVersion();\r
740                         String downloadURL = row.getDownloadURL();\r
741                         String localizedName = row.getLocalizedName();\r
742                         Timestamp lastModified = row.getLastModified();\r
743                         \r
744                         PartsManageData.PartsVersionInfo versionInfo = new PartsManageData.PartsVersionInfo();\r
745                         versionInfo.setVersion(version);\r
746                         versionInfo.setDownloadURL(downloadURL);\r
747                         versionInfo.setLastModified(lastModified);\r
748 \r
749                         PartsIdentifier partsIdentifier = row.getPartsIdentifier();\r
750                         \r
751                         PartsManageData.PartsKey partsKey = new PartsManageData.PartsKey(partsIdentifier);\r
752                         partsManageData.putPartsInfo(partsKey, localizedName,\r
753                                         partsAuthorInfo, versionInfo);\r
754                 }\r
755                 \r
756                 // パーツ管理情報を書き込む.\r
757                 PartsInfoXMLWriter xmlWriter = new PartsInfoXMLWriter();\r
758                 try {\r
759                         URI docBase = characterData.getDocBase();\r
760                         xmlWriter.savePartsManageData(docBase, partsManageData);\r
761 \r
762                 } catch (Exception ex) {\r
763                         ErrorMessageHelper.showErrorDialog(this, ex);\r
764                         return;\r
765                 }\r
766                 \r
767                 updated = true;\r
768                 dispose();\r
769         }\r
770 \r
771         /**\r
772          * パーツ管理情報が更新されたか?\r
773          * \r
774          * @return 更新された場合はtrue、そうでなければfalse\r
775          */\r
776         public boolean isUpdated() {\r
777                 return updated;\r
778         }\r
779 }\r
780 \r
781 class PartsManageTableRow {\r
782         \r
783         private PartsIdentifier partsIdentifier;\r
784         \r
785         private Timestamp timestamp;\r
786         \r
787         private String localizedName;\r
788         \r
789         private String author;\r
790         \r
791         private String homepage;\r
792         \r
793         private String downloadURL;\r
794         \r
795         private double version;\r
796         \r
797         private Timestamp lastModified;\r
798 \r
799         public PartsManageTableRow(PartsIdentifier partsIdentifier,\r
800                         PartsSpec partsSpec, Timestamp lastModified) {\r
801                 if (partsIdentifier == null || partsSpec == null) {\r
802                         throw new IllegalArgumentException();\r
803                 }\r
804                 this.partsIdentifier = partsIdentifier;\r
805                 this.localizedName = partsIdentifier.getLocalizedPartsName();\r
806 \r
807                 this.timestamp = new Timestamp(partsSpec.getPartsFiles().lastModified());\r
808                 \r
809                 this.lastModified = lastModified;\r
810                 \r
811                 PartsAuthorInfo autherInfo = partsSpec.getAuthorInfo();\r
812                 if (autherInfo != null) {\r
813                         author = autherInfo.getAuthor();\r
814                         homepage = autherInfo.getHomePage();\r
815                 }\r
816                 if (author == null) {\r
817                         author = "";\r
818                 }\r
819                 if (homepage == null) {\r
820                         homepage = "";\r
821                 }\r
822                 downloadURL = partsSpec.getDownloadURL();\r
823                 version = partsSpec.getVersion();\r
824         }\r
825         \r
826         public PartsIdentifier getPartsIdentifier() {\r
827                 return partsIdentifier;\r
828         }\r
829         \r
830         public Timestamp getTimestamp() {\r
831                 return timestamp;\r
832         }\r
833 \r
834         public String getLocalizedName() {\r
835                 return localizedName;\r
836         }\r
837         \r
838         public void setLocalizedName(String localizedName) {\r
839                 if (localizedName == null || localizedName.trim().length() == 0) {\r
840                         throw new IllegalArgumentException();\r
841                 }\r
842                 this.localizedName = localizedName;\r
843         }\r
844         \r
845         public String getAuthor() {\r
846                 return author;\r
847         }\r
848         \r
849         public String getDownloadURL() {\r
850                 return downloadURL;\r
851         }\r
852         \r
853         public double getVersion() {\r
854                 return version;\r
855         }\r
856         \r
857         public void setAuthor(String author) {\r
858                 this.author = author;\r
859         }\r
860         \r
861         public void setDownloadURL(String downloadURL) {\r
862                 this.downloadURL = downloadURL;\r
863         }\r
864         \r
865         public void setVersion(double version) {\r
866                 this.version = version;\r
867         }\r
868         \r
869         public String getHomepage() {\r
870                 return homepage;\r
871         }\r
872         \r
873         public void setHomepage(String homepage) {\r
874                 this.homepage = homepage;\r
875         }\r
876         \r
877         public Timestamp getLastModified() {\r
878                 return lastModified;\r
879         }\r
880 \r
881         public void setLastModified(Timestamp lastModified) {\r
882                 this.lastModified = lastModified;\r
883         }\r
884 }\r
885 \r
886 class PartsManageTableModel extends AbstractTableModelWithComboBoxModel<PartsManageTableRow> {\r
887 \r
888         private static final long serialVersionUID = 1L;\r
889 \r
890         private static final Logger logger = Logger\r
891                         .getLogger(PartsManageTableModel.class.getName());\r
892 \r
893         private static Properties strings = LocalizedResourcePropertyLoader\r
894                         .getCachedInstance().getLocalizedProperties(\r
895                                         PartsManageDialog.STRINGS_RESOURCE);\r
896 \r
897         /**\r
898          * カラムの定義\r
899          */\r
900         public enum Columns {\r
901                 PartsID("column.partsid", false, String.class) {\r
902                         @Override\r
903                         public Object getValue(PartsManageTableRow row) {\r
904                                 return row.getPartsIdentifier().getPartsName();\r
905                         }\r
906                 },\r
907                 LastModified("column.lastmodified", false, String.class) {\r
908                         @Override\r
909                         public Object getValue(PartsManageTableRow row) {\r
910                                 return row.getTimestamp().toString();\r
911                         }\r
912                 },\r
913                 Category("column.category", false, String.class) {\r
914                         @Override\r
915                         public Object getValue(PartsManageTableRow row) {\r
916                                 return row.getPartsIdentifier().getPartsCategory()\r
917                                                 .getLocalizedCategoryName();\r
918                         }\r
919                 },\r
920                 PartsName("column.partsname", true, String.class) {\r
921                         @Override\r
922                         public Object getValue(PartsManageTableRow row) {\r
923                                 return row.getLocalizedName();\r
924                         }\r
925                         @Override\r
926                         public void setValue(PartsManageTableRow row, Object value) {\r
927                                 String localizedName = (String) value;\r
928                                 if (localizedName != null && localizedName.trim().length() > 0) {\r
929                                         String oldValue = row.getLocalizedName();\r
930                                         if (oldValue != null && oldValue.equals(localizedName)) {\r
931                                                 return; // 変化なし\r
932                                         }\r
933                                         row.setLocalizedName(localizedName);\r
934                                 }\r
935                         }\r
936                 },\r
937                 Author("column.author", true, String.class) {\r
938                         @Override\r
939                         public Object getValue(PartsManageTableRow row) {\r
940                                 return row.getAuthor();\r
941                         }\r
942                         @Override\r
943                         public void setValue(PartsManageTableRow row, Object value) {\r
944                                 String author = (String) value;\r
945                                 if (author == null) {\r
946                                         author = "";\r
947                                 }\r
948                                 String oldValue = row.getAuthor();\r
949                                 if (oldValue != null && oldValue.equals(author)) {\r
950                                         return; // 変化なし\r
951                                 }\r
952                                 row.setAuthor(author);\r
953                         }\r
954                 },\r
955                 Version("column.version", true, Double.class) {\r
956                         @Override\r
957                         public Object getValue(PartsManageTableRow row) {\r
958                                 return row.getVersion() > 0 ? row.getVersion() : null;\r
959                         }\r
960                         @Override\r
961                         public void setValue(PartsManageTableRow row, Object value) {\r
962                                 Double version = (Double) value;\r
963                                 if (version == null || version.doubleValue() <= 0) {\r
964                                         version = Double.valueOf(0.);\r
965                                 }\r
966                                 Double oldValue = row.getVersion();\r
967                                 if (oldValue != null && oldValue.equals(version)) {\r
968                                         return; // 変化なし\r
969                                 }\r
970                                 row.setVersion(version);\r
971                         }\r
972                 },\r
973                 DownloadURL("column.downloadURL", true, String.class) {\r
974                         @Override\r
975                         public Object getValue(PartsManageTableRow row) {\r
976                                 return row.getDownloadURL();\r
977                         }\r
978                         @Override\r
979                         public void setValue(PartsManageTableRow row, Object value) {\r
980                                 String downloadURL = (String) value;\r
981                                 if (downloadURL == null) {\r
982                                         downloadURL = "";\r
983                                 }\r
984                                 String oldValue = row.getDownloadURL();\r
985                                 if (oldValue != null && oldValue.equals(downloadURL)) {\r
986                                         return; // 変化なし\r
987                                 }\r
988                                 row.setDownloadURL(downloadURL);\r
989                         }\r
990                 };\r
991 \r
992                 private final Class<?> columnClass;\r
993 \r
994                 private final boolean editable;\r
995 \r
996                 private final String columnName;\r
997 \r
998                 private String displayName;\r
999 \r
1000                 private int width;\r
1001 \r
1002                 private Columns(String columnName, boolean editable,\r
1003                                 Class<?> columnClass) {\r
1004                         this.columnName = columnName;\r
1005                         this.editable = editable;\r
1006                         this.columnClass = columnClass;\r
1007                 }\r
1008 \r
1009                 public abstract Object getValue(PartsManageTableRow row);\r
1010 \r
1011                 public boolean isEditable() {\r
1012                         return editable;\r
1013                 }\r
1014 \r
1015                 public Class<?> getColumnClass() {\r
1016                         return columnClass;\r
1017                 }\r
1018 \r
1019                 public String getDisplayName() {\r
1020                         init();\r
1021                         return displayName;\r
1022                 }\r
1023 \r
1024                 public int getWidth() {\r
1025                         init();\r
1026                         return width;\r
1027                 }\r
1028 \r
1029                 public void setValue(PartsManageTableRow row, Object value) {\r
1030                         // 何もしない.\r
1031                 }\r
1032 \r
1033                 private void init() {\r
1034                         if (displayName != null) {\r
1035                                 return;\r
1036                         }\r
1037                         displayName = strings.getProperty(columnName);\r
1038                         width = Integer\r
1039                                         .parseInt(strings.getProperty(columnName + ".width"));\r
1040                 }\r
1041         }\r
1042 \r
1043         \r
1044         public int getColumnCount() {\r
1045                 return Columns.values().length;\r
1046         }\r
1047         \r
1048         @Override\r
1049         public String getColumnName(int column) {\r
1050                 return Columns.values()[column].getDisplayName();\r
1051         }\r
1052         \r
1053         public void adjustColumnModel(TableColumnModel columnModel) {\r
1054                 Columns[] columns = Columns.values();\r
1055                 for (int idx = 0; idx < columns.length; idx++) {\r
1056                         columnModel.getColumn(idx).setPreferredWidth(\r
1057                                         columns[idx].getWidth());\r
1058                 }\r
1059         }\r
1060 \r
1061         public Object getValueAt(int rowIndex, int columnIndex) {\r
1062                 PartsManageTableRow row = getRow(rowIndex);\r
1063                 Columns column = Columns.values()[columnIndex];\r
1064                 return column.getValue(row);\r
1065         }\r
1066         \r
1067         @Override\r
1068         public void setValueAt(Object aValue, int rowIndex, int columnIndex) {\r
1069                 PartsManageTableRow row = getRow(rowIndex);\r
1070                 Columns column = Columns.values()[columnIndex];\r
1071                 if (!column.isEditable()) {\r
1072                         return;\r
1073                 }\r
1074                 column.setValue(row, aValue);\r
1075 \r
1076                 // 更新日を最新にする\r
1077                 Timestamp dt = row.getTimestamp();\r
1078                 row.setLastModified(dt);\r
1079 \r
1080                 // 変更通知\r
1081                 fireTableRowsUpdated(rowIndex, columnIndex);\r
1082         }\r
1083         \r
1084         @Override\r
1085         public Class<?> getColumnClass(int columnIndex) {\r
1086                 Columns column = Columns.values()[columnIndex];\r
1087                 return column.getColumnClass();\r
1088         }\r
1089         \r
1090         @Override\r
1091         public boolean isCellEditable(int rowIndex, int columnIndex) {\r
1092                 Columns column = Columns.values()[columnIndex];\r
1093                 return column.isEditable();\r
1094         }\r
1095         \r
1096         public void initModel(CharacterData characterData) {\r
1097                 if (characterData == null) {\r
1098                         throw new IllegalArgumentException();\r
1099                 }\r
1100                 clear();\r
1101 \r
1102                 // 既存のパーツ管理情報ファイルがあれば読み込む\r
1103                 URI docBase = characterData.getDocBase();\r
1104                 PartsManageData partsManageData = null;\r
1105                 if (docBase != null) {\r
1106                         try {\r
1107                                 PartsInfoXMLReader reader = new PartsInfoXMLReader();\r
1108                                 partsManageData = reader.loadPartsManageData(docBase);\r
1109 \r
1110                         } catch (Exception ex) {\r
1111                                 logger.log(Level.WARNING, ex.toString(), ex);\r
1112                         }\r
1113                 }\r
1114                 if (partsManageData == null) {\r
1115                         partsManageData = new PartsManageData();\r
1116                 }\r
1117 \r
1118                 for (PartsCategory partsCategory : characterData.getPartsCategories()) {\r
1119                         for (Map.Entry<PartsIdentifier, PartsSpec> entry : characterData\r
1120                                         .getPartsSpecMap(partsCategory).entrySet()) {\r
1121                                 PartsIdentifier partsIdentifier = entry.getKey();\r
1122                                 PartsSpec partsSpec = entry.getValue();\r
1123                                 \r
1124                                 // パーツ管理情報ファイルから、パーツ管理情報を設定した時点の\r
1125                                 // ファイルサイズや更新日時などを読み取る.\r
1126                                 PartsKey partsKey = new PartsKey(partsIdentifier);\r
1127                                 PartsVersionInfo versionInfo = partsManageData\r
1128                                                 .getVersion(partsKey);\r
1129 \r
1130                                 Timestamp lastModified = null;\r
1131 \r
1132                                 if (versionInfo != null) {\r
1133                                         lastModified = versionInfo.getLastModified();\r
1134                                 }\r
1135 \r
1136                                 PartsManageTableRow row = new PartsManageTableRow(\r
1137                                                 partsIdentifier, partsSpec, lastModified);\r
1138                                 addRow(row);\r
1139                         }\r
1140                 }\r
1141 \r
1142                 sortByAuthor();\r
1143         }\r
1144 \r
1145         /**\r
1146          * ホームページを設定する.<br>\r
1147          * ホームページはAuthorに対して1つであるが、Authorが自由編集可能であるため便宜的にRowに持たせている.<br>\r
1148          * 結果として同じAuthorに対して同じ値を設定する必要がある.<br>\r
1149          * ホームページはテーブルに表示されないのでリスナーへの通知は行わない.<br>\r
1150          * \r
1151          * @param author\r
1152          *            作者、空またはnullは何もしない.\r
1153          * @param homepage\r
1154          *            ホームページ\r
1155          */\r
1156         public void setHomepage(String author, String homepage) {\r
1157                 if (author == null || author.length() == 0) {\r
1158                         return;\r
1159                 }\r
1160                 for (PartsManageTableRow row : elements) {\r
1161                         String targetAuthor = row.getAuthor();\r
1162                         if (targetAuthor == null) {\r
1163                                 targetAuthor = "";\r
1164                         }\r
1165                         if (targetAuthor.equals(author)) {\r
1166                                 row.setHomepage(homepage);\r
1167                         }\r
1168                 }\r
1169         }\r
1170 \r
1171         /**\r
1172          * ホームページを取得する.<br>\r
1173          * 該当する作者がないか、作者がnullまたは空の場合は常にnullを返す.<br>\r
1174          * \r
1175          * @param author\r
1176          *            作者\r
1177          * @return ホームページ、またはnull\r
1178          */\r
1179         public String getHomepage(String author) {\r
1180                 if (author == null || author.length() == 0) {\r
1181                         return null;\r
1182                 }\r
1183                 for (PartsManageTableRow row : elements) {\r
1184                         String targetAuthor = row.getAuthor();\r
1185                         if (targetAuthor == null) {\r
1186                                 targetAuthor = "";\r
1187                         }\r
1188                         if (targetAuthor.equals(author)) {\r
1189                                 return row.getHomepage();\r
1190                         }\r
1191                 }\r
1192                 return null;\r
1193         }\r
1194         \r
1195         protected static final Comparator<PartsManageTableRow> NAMED_SORTER\r
1196                 = new Comparator<PartsManageTableRow>() {\r
1197                 public int compare(PartsManageTableRow o1, PartsManageTableRow o2) {\r
1198                         // カテゴリで順序づけ\r
1199                         int ret = o1.getPartsIdentifier().getPartsCategory().compareTo(\r
1200                                         o2.getPartsIdentifier().getPartsCategory());\r
1201                         if (ret == 0) {\r
1202                                 // 表示名で順序づけ\r
1203                                 String lnm1 = o1.getLocalizedName();\r
1204                                 String lnm2 = o2.getLocalizedName();\r
1205                                 if (lnm1 == null) {\r
1206                                         lnm1 = "";\r
1207                                 }\r
1208                                 if (lnm2 == null) {\r
1209                                         lnm2 = "";\r
1210                                 }\r
1211                                 ret = lnm1.compareTo(lnm2);\r
1212                         }\r
1213                         if (ret == 0) {\r
1214                                 // それでも判定できなければ元の識別子で判定する.\r
1215                                 ret = o1.getPartsIdentifier().compareTo(o2.getPartsIdentifier());\r
1216                         }\r
1217                         return ret;\r
1218                 }\r
1219         };\r
1220         \r
1221         public void sortByName() {\r
1222                 Collections.sort(elements, NAMED_SORTER);\r
1223                 fireTableDataChanged();\r
1224         }\r
1225         \r
1226         public void sortByTimestamp() {\r
1227                 Collections.sort(elements, new Comparator<PartsManageTableRow>() {\r
1228                         public int compare(PartsManageTableRow o1, PartsManageTableRow o2) {\r
1229                                 // 更新日で順序づけ (新しいもの順)\r
1230                                 int ret = o1.getTimestamp().compareTo(o2.getTimestamp()) * -1;\r
1231                                 if (ret == 0) {\r
1232                                         // それでも判定できなければ名前順と同じ\r
1233                                         ret = NAMED_SORTER.compare(o1, o2);\r
1234                                 }\r
1235                                 return ret;\r
1236                         }\r
1237                 });\r
1238                 fireTableDataChanged();\r
1239         }\r
1240 \r
1241         public void sortByAuthor() {\r
1242                 Collections.sort(elements, new Comparator<PartsManageTableRow>() {\r
1243                         public int compare(PartsManageTableRow o1, PartsManageTableRow o2) {\r
1244                                 // 作者で順序づけ\r
1245                                 String author1 = o1.getAuthor();\r
1246                                 String author2 = o2.getAuthor();\r
1247                                 if (author1 == null) {\r
1248                                         author1 = "";\r
1249                                 }\r
1250                                 if (author2 == null) {\r
1251                                         author2 = "";\r
1252                                 }\r
1253                                 int ret = author1.compareTo(author2);\r
1254                                 if (ret == 0) {\r
1255                                         // それでも判定できなければ名前順と同じ\r
1256                                         ret = NAMED_SORTER.compare(o1, o2);\r
1257                                 }\r
1258                                 return ret;\r
1259                         }\r
1260                 });\r
1261                 fireTableDataChanged();\r
1262         }\r
1263 }\r