1 package charactermanaj.ui;
\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
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
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
75 public class PartsManageDialog extends JDialog {
\r
77 private static final long serialVersionUID = 1L;
\r
79 protected static final String STRINGS_RESOURCE = "languages/partsmanagedialog";
\r
82 private static final Logger logger = Logger.getLogger(PartsManageDialog.class.getName());
\r
84 private CharacterData characterData;
\r
86 private PartsManageTableModel partsManageTableModel;
\r
88 private JTable partsManageTable;
\r
90 private JTextField txtHomepage;
\r
92 private JTextField txtAuthor;
\r
94 private boolean updated;
\r
97 public PartsManageDialog(JFrame parent, CharacterData characterData) {
\r
98 super(parent, true);
\r
100 if (characterData == null) {
\r
101 throw new IllegalArgumentException();
\r
103 this.characterData = characterData;
\r
105 setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
\r
106 addWindowListener(new WindowAdapter() {
\r
108 public void windowClosing(WindowEvent e) {
\r
113 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()
\r
114 .getLocalizedProperties(STRINGS_RESOURCE);
\r
116 setTitle(strings.getProperty("title"));
\r
118 Container contentPane = getContentPane();
\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
126 GridBagLayout partsListPanelLayout = new GridBagLayout();
\r
127 partsListPanel.setLayout(partsListPanelLayout);
\r
129 partsManageTableModel = new PartsManageTableModel();
\r
130 partsManageTable = new JTable(partsManageTableModel) {
\r
131 private static final long serialVersionUID = 1L;
\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
141 Timestamp current = row.getTimestamp();
\r
142 Timestamp lastModified = row.getLastModified();
\r
144 boolean warnings = false;
\r
146 if (current != null && !current.equals(lastModified)) {
\r
147 // 現在のパーツの最終更新日と、パーツ管理情報の作成時のパーツの最終更新日が不一致の場合
\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
157 if (isCellSelected(rowIdx, columnIdx)) {
\r
158 comp.setBackground(getSelectionBackground());
\r
160 comp.setBackground(getBackground());
\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
173 JScrollPane partsManageTableSP = new JScrollPane(partsManageTable);
\r
175 partsManageTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
\r
176 public void valueChanged(ListSelectionEvent e) {
\r
177 if (!e.getValueIsAdjusting()) {
\r
178 onChangeSelection();
\r
183 partsManageTableModel.addTableModelListener(new TableModelListener() {
\r
184 public void tableChanged(TableModelEvent e) {
\r
185 onTableDataChange(e.getFirstRow(), e.getLastRow());
\r
189 GridBagConstraints gbc = new GridBagConstraints();
\r
192 gbc.gridheight = 1;
\r
194 gbc.anchor = GridBagConstraints.EAST;
\r
195 gbc.fill = GridBagConstraints.BOTH;
\r
196 gbc.insets = new Insets(3, 3, 3, 3);
\r
201 partsListPanel.add(partsManageTableSP, gbc);
\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
209 Action actSortByAuthor = new AbstractAction(strings.getProperty("sortByAuthor")) {
\r
210 private static final long serialVersionUID = 1L;
\r
211 public void actionPerformed(ActionEvent e) {
\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
224 gbc.gridheight = 1;
\r
228 partsListPanel.add(new JButton(actSortByName), gbc);
\r
234 partsListPanel.add(new JButton(actSortByAuthor), gbc);
\r
240 partsListPanel.add(new JButton(actSortByTimestamp), gbc);
\r
246 partsListPanel.add(Box.createHorizontalGlue(), gbc);
\r
248 contentPane.add(partsListPanel, BorderLayout.CENTER);
\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
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
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
270 popupMenu.add(actApplyAllLastModified);
\r
271 popupMenu.add(new JSeparator());
\r
272 popupMenu.add(actApplyAllVersion);
\r
273 popupMenu.add(actApplyAllDownloadURL);
\r
275 partsManageTable.setComponentPopupMenu(popupMenu);
\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
287 gbc.gridheight = 1;
\r
289 gbc.anchor = GridBagConstraints.EAST;
\r
290 gbc.fill = GridBagConstraints.BOTH;
\r
291 gbc.insets = new Insets(3, 3, 3, 3);
\r
296 authorPanel.add(new JLabel(strings.getProperty("author"), JLabel.RIGHT), gbc);
\r
302 txtAuthor = new JTextField();
\r
303 authorPanel.add(txtAuthor, gbc);
\r
309 authorPanel.add(new JLabel(strings.getProperty("homepage"), JLabel.RIGHT), gbc);
\r
315 txtHomepage = new JTextField();
\r
316 authorPanel.add(txtHomepage, gbc);
\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
328 authorPanel.add(new JButton(actBrowseHomepage), gbc);
\r
330 if (!DesktopUtilities.isSupported()) {
\r
331 actBrowseHomepage.setEnabled(false);
\r
334 txtAuthor.getDocument().addDocumentListener(new DocumentListener() {
\r
335 public void removeUpdate(DocumentEvent e) {
\r
338 public void insertUpdate(DocumentEvent e) {
\r
341 public void changedUpdate(DocumentEvent e) {
\r
345 txtHomepage.getDocument().addDocumentListener(new DocumentListener() {
\r
346 public void removeUpdate(DocumentEvent e) {
\r
349 public void insertUpdate(DocumentEvent e) {
\r
352 public void changedUpdate(DocumentEvent e) {
\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
364 Action actClose = new AbstractAction(strings.getProperty("cancel")) {
\r
365 private static final long serialVersionUID = 1L;
\r
366 public void actionPerformed(ActionEvent e) {
\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
380 btnPanel.add(Box.createHorizontalGlue(), gbc);
\r
382 gbc.gridx = Main.isLinuxOrMacOSX() ? 2 : 1;
\r
385 btnPanel.add(new JButton(actOK), gbc);
\r
387 gbc.gridx = Main.isLinuxOrMacOSX() ? 1 : 2;
\r
390 btnPanel.add(new JButton(actClose), gbc);
\r
393 JPanel southPanel = new JPanel(new BorderLayout());
\r
394 southPanel.add(authorPanel, BorderLayout.NORTH);
\r
395 southPanel.add(btnPanel, BorderLayout.SOUTH);
\r
397 contentPane.add(southPanel, BorderLayout.SOUTH);
\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
410 partsManageTableModel.initModel(characterData);
\r
414 setLocationRelativeTo(parent);
\r
417 private Semaphore authorEditSemaphore = new Semaphore(1);
\r
419 protected void onChangeSelection() {
\r
421 authorEditSemaphore.acquire();
\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
429 if (authors.size() > 1) {
\r
430 AppConfig appConfig = AppConfig.getInstance();
\r
431 txtAuthor.setBackground(appConfig.getAuthorEditConflictBgColor());
\r
432 txtHomepage.setBackground(appConfig.getAuthorEditConflictBgColor());
\r
434 Color bgColor = UIManager.getColor("TextField.background");
\r
435 if (bgColor == null) {
\r
436 bgColor = Color.white;
\r
438 txtAuthor.setBackground(bgColor);
\r
439 txtHomepage.setBackground(bgColor);
\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
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
458 // 選択されているAuthorが二個以上あれば編集可能だがテキストには表示しない.
\r
459 txtAuthor.setText("");
\r
460 txtHomepage.setText("");
\r
464 authorEditSemaphore.release();
\r
467 } catch (InterruptedException ex) {
\r
468 ErrorMessageHelper.showErrorDialog(this, ex);
\r
470 } catch (RuntimeException ex) {
\r
471 ErrorMessageHelper.showErrorDialog(this, ex);
\r
475 protected void onTableDataChange(int firstRow, int lastRow) {
\r
476 onChangeSelection();
\r
479 protected void onApplyAllLastModified() {
\r
480 int[] selRows = partsManageTable.getSelectedRows();
\r
481 if (selRows.length == 0) {
\r
482 Toolkit tk = Toolkit.getDefaultToolkit();
\r
486 Arrays.sort(selRows);
\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
493 partsManageTableModel.fireTableRowsUpdated(selRows[0],
\r
494 selRows[selRows.length - 1]);
\r
497 protected void onApplyAllDownloadURL() {
\r
498 int[] selRows = partsManageTable.getSelectedRows();
\r
499 if (selRows.length == 0) {
\r
500 Toolkit tk = Toolkit.getDefaultToolkit();
\r
504 Arrays.sort(selRows);
\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
512 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()
\r
513 .getLocalizedProperties(STRINGS_RESOURCE);
\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
524 PartsManageTableRow firstRow = partsManageTableModel.getRow(selRows[0]);
\r
525 String downloadURL = firstRow.getDownloadURL();
\r
526 if (downloadURL == null) {
\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
535 for (int selRow : selRows) {
\r
536 PartsManageTableRow row = partsManageTableModel.getRow(selRow);
\r
537 row.setDownloadURL(downloadURL_new);
\r
539 Timestamp dt = row.getTimestamp();
\r
540 row.setLastModified(dt);
\r
542 partsManageTableModel.fireTableRowsUpdated(selRows[0], selRows[selRows.length - 1]);
\r
545 protected void onApplyAllVersion() {
\r
546 Toolkit tk = Toolkit.getDefaultToolkit();
\r
547 int[] selRows = partsManageTable.getSelectedRows();
\r
548 if (selRows.length == 0) {
\r
552 Arrays.sort(selRows);
\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
560 Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()
\r
561 .getLocalizedProperties(STRINGS_RESOURCE);
\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
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
581 double version_new;
\r
583 version_new = Double.parseDouble(strVersion_new);
\r
584 } catch (Exception ex) {
\r
585 // 数値として不正であれば何もしない.
\r
590 for (int selRow : selRows) {
\r
591 PartsManageTableRow row = partsManageTableModel.getRow(selRow);
\r
592 row.setVersion(version_new);
\r
594 Timestamp dt = row.getTimestamp();
\r
595 row.setLastModified(dt);
\r
597 partsManageTableModel.fireTableRowsUpdated(selRows[0], selRows[selRows.length - 1]);
\r
600 protected void onEditHomepage() {
\r
602 if (!authorEditSemaphore.tryAcquire()) {
\r
606 String author = txtAuthor.getText();
\r
607 String homepage = txtHomepage.getText();
\r
608 partsManageTableModel.setHomepage(author, homepage);
\r
610 authorEditSemaphore.release();
\r
612 } catch (Exception ex) {
\r
613 ErrorMessageHelper.showErrorDialog(this, ex);
\r
617 protected void onEditAuthor() {
\r
619 if (!authorEditSemaphore.tryAcquire()) {
\r
623 String author = txtAuthor.getText();
\r
624 int[] selRows = partsManageTable.getSelectedRows();
\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
633 Timestamp dt = row.getTimestamp();
\r
634 row.setLastModified(dt);
\r
636 firstRow = Math.max(firstRow, selRow);
\r
637 lastRow = Math.min(lastRow, selRow);
\r
641 String homepage = partsManageTableModel.getHomepage(author);
\r
642 if (homepage == null) {
\r
645 txtHomepage.setText(homepage);
\r
647 if (firstRow >= 0) {
\r
648 partsManageTable.repaint();
\r
651 authorEditSemaphore.release();
\r
653 } catch (Exception ex) {
\r
654 ErrorMessageHelper.showErrorDialog(this, ex);
\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
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
679 URI uri = new URI(homepage);
\r
680 DesktopUtilities.browse(uri);
\r
682 } catch (Exception ex) {
\r
684 logger.log(Level.INFO, "browse failed. : " + homepage, ex);
\r
688 protected void onSortByAuthor() {
\r
689 partsManageTableModel.sortByAuthor();
\r
692 protected void onSortByName() {
\r
693 partsManageTableModel.sortByName();
\r
696 protected void onSortByTimestamp() {
\r
697 partsManageTableModel.sortByTimestamp();
\r
700 protected void onOK() {
\r
701 if (partsManageTable.isEditing()) {
\r
702 Toolkit tk = Toolkit.getDefaultToolkit();
\r
707 int mx = partsManageTableModel.getRowCount();
\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
723 authorInfo.setHomePage(homepage);
\r
727 PartsManageData partsManageData = new PartsManageData();
\r
729 // パーツごとの作者とバージョン、ダウンロード先の取得
\r
730 for (int idx = 0; idx < mx; idx++) {
\r
731 PartsManageTableRow row = partsManageTableModel.getRow(idx);
\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
739 double version = row.getVersion();
\r
740 String downloadURL = row.getDownloadURL();
\r
741 String localizedName = row.getLocalizedName();
\r
742 Timestamp lastModified = row.getLastModified();
\r
744 PartsManageData.PartsVersionInfo versionInfo = new PartsManageData.PartsVersionInfo();
\r
745 versionInfo.setVersion(version);
\r
746 versionInfo.setDownloadURL(downloadURL);
\r
747 versionInfo.setLastModified(lastModified);
\r
749 PartsIdentifier partsIdentifier = row.getPartsIdentifier();
\r
751 PartsManageData.PartsKey partsKey = new PartsManageData.PartsKey(partsIdentifier);
\r
752 partsManageData.putPartsInfo(partsKey, localizedName,
\r
753 partsAuthorInfo, versionInfo);
\r
757 PartsInfoXMLWriter xmlWriter = new PartsInfoXMLWriter();
\r
759 URI docBase = characterData.getDocBase();
\r
760 xmlWriter.savePartsManageData(docBase, partsManageData);
\r
762 } catch (Exception ex) {
\r
763 ErrorMessageHelper.showErrorDialog(this, ex);
\r
774 * @return 更新された場合はtrue、そうでなければfalse
\r
776 public boolean isUpdated() {
\r
781 class PartsManageTableRow {
\r
783 private PartsIdentifier partsIdentifier;
\r
785 private Timestamp timestamp;
\r
787 private String localizedName;
\r
789 private String author;
\r
791 private String homepage;
\r
793 private String downloadURL;
\r
795 private double version;
\r
797 private Timestamp lastModified;
\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
804 this.partsIdentifier = partsIdentifier;
\r
805 this.localizedName = partsIdentifier.getLocalizedPartsName();
\r
807 this.timestamp = new Timestamp(partsSpec.getPartsFiles().lastModified());
\r
809 this.lastModified = lastModified;
\r
811 PartsAuthorInfo autherInfo = partsSpec.getAuthorInfo();
\r
812 if (autherInfo != null) {
\r
813 author = autherInfo.getAuthor();
\r
814 homepage = autherInfo.getHomePage();
\r
816 if (author == null) {
\r
819 if (homepage == null) {
\r
822 downloadURL = partsSpec.getDownloadURL();
\r
823 version = partsSpec.getVersion();
\r
826 public PartsIdentifier getPartsIdentifier() {
\r
827 return partsIdentifier;
\r
830 public Timestamp getTimestamp() {
\r
834 public String getLocalizedName() {
\r
835 return localizedName;
\r
838 public void setLocalizedName(String localizedName) {
\r
839 if (localizedName == null || localizedName.trim().length() == 0) {
\r
840 throw new IllegalArgumentException();
\r
842 this.localizedName = localizedName;
\r
845 public String getAuthor() {
\r
849 public String getDownloadURL() {
\r
850 return downloadURL;
\r
853 public double getVersion() {
\r
857 public void setAuthor(String author) {
\r
858 this.author = author;
\r
861 public void setDownloadURL(String downloadURL) {
\r
862 this.downloadURL = downloadURL;
\r
865 public void setVersion(double version) {
\r
866 this.version = version;
\r
869 public String getHomepage() {
\r
873 public void setHomepage(String homepage) {
\r
874 this.homepage = homepage;
\r
877 public Timestamp getLastModified() {
\r
878 return lastModified;
\r
881 public void setLastModified(Timestamp lastModified) {
\r
882 this.lastModified = lastModified;
\r
886 class PartsManageTableModel extends AbstractTableModelWithComboBoxModel<PartsManageTableRow> {
\r
888 private static final long serialVersionUID = 1L;
\r
890 private static final Logger logger = Logger
\r
891 .getLogger(PartsManageTableModel.class.getName());
\r
893 private static Properties strings = LocalizedResourcePropertyLoader
\r
894 .getCachedInstance().getLocalizedProperties(
\r
895 PartsManageDialog.STRINGS_RESOURCE);
\r
900 public enum Columns {
\r
901 PartsID("column.partsid", false, String.class) {
\r
903 public Object getValue(PartsManageTableRow row) {
\r
904 return row.getPartsIdentifier().getPartsName();
\r
907 LastModified("column.lastmodified", false, String.class) {
\r
909 public Object getValue(PartsManageTableRow row) {
\r
910 return row.getTimestamp().toString();
\r
913 Category("column.category", false, String.class) {
\r
915 public Object getValue(PartsManageTableRow row) {
\r
916 return row.getPartsIdentifier().getPartsCategory()
\r
917 .getLocalizedCategoryName();
\r
920 PartsName("column.partsname", true, String.class) {
\r
922 public Object getValue(PartsManageTableRow row) {
\r
923 return row.getLocalizedName();
\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
933 row.setLocalizedName(localizedName);
\r
937 Author("column.author", true, String.class) {
\r
939 public Object getValue(PartsManageTableRow row) {
\r
940 return row.getAuthor();
\r
943 public void setValue(PartsManageTableRow row, Object value) {
\r
944 String author = (String) value;
\r
945 if (author == null) {
\r
948 String oldValue = row.getAuthor();
\r
949 if (oldValue != null && oldValue.equals(author)) {
\r
952 row.setAuthor(author);
\r
955 Version("column.version", true, Double.class) {
\r
957 public Object getValue(PartsManageTableRow row) {
\r
958 return row.getVersion() > 0 ? row.getVersion() : null;
\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
966 Double oldValue = row.getVersion();
\r
967 if (oldValue != null && oldValue.equals(version)) {
\r
970 row.setVersion(version);
\r
973 DownloadURL("column.downloadURL", true, String.class) {
\r
975 public Object getValue(PartsManageTableRow row) {
\r
976 return row.getDownloadURL();
\r
979 public void setValue(PartsManageTableRow row, Object value) {
\r
980 String downloadURL = (String) value;
\r
981 if (downloadURL == null) {
\r
984 String oldValue = row.getDownloadURL();
\r
985 if (oldValue != null && oldValue.equals(downloadURL)) {
\r
988 row.setDownloadURL(downloadURL);
\r
992 private final Class<?> columnClass;
\r
994 private final boolean editable;
\r
996 private final String columnName;
\r
998 private String displayName;
\r
1000 private int width;
\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
1009 public abstract Object getValue(PartsManageTableRow row);
\r
1011 public boolean isEditable() {
\r
1015 public Class<?> getColumnClass() {
\r
1016 return columnClass;
\r
1019 public String getDisplayName() {
\r
1021 return displayName;
\r
1024 public int getWidth() {
\r
1029 public void setValue(PartsManageTableRow row, Object value) {
\r
1033 private void init() {
\r
1034 if (displayName != null) {
\r
1037 displayName = strings.getProperty(columnName);
\r
1039 .parseInt(strings.getProperty(columnName + ".width"));
\r
1044 public int getColumnCount() {
\r
1045 return Columns.values().length;
\r
1049 public String getColumnName(int column) {
\r
1050 return Columns.values()[column].getDisplayName();
\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
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
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
1074 column.setValue(row, aValue);
\r
1077 Timestamp dt = row.getTimestamp();
\r
1078 row.setLastModified(dt);
\r
1081 fireTableRowsUpdated(rowIndex, columnIndex);
\r
1085 public Class<?> getColumnClass(int columnIndex) {
\r
1086 Columns column = Columns.values()[columnIndex];
\r
1087 return column.getColumnClass();
\r
1091 public boolean isCellEditable(int rowIndex, int columnIndex) {
\r
1092 Columns column = Columns.values()[columnIndex];
\r
1093 return column.isEditable();
\r
1096 public void initModel(CharacterData characterData) {
\r
1097 if (characterData == null) {
\r
1098 throw new IllegalArgumentException();
\r
1102 // 既存のパーツ管理情報ファイルがあれば読み込む
\r
1103 URI docBase = characterData.getDocBase();
\r
1104 PartsManageData partsManageData = null;
\r
1105 if (docBase != null) {
\r
1107 PartsInfoXMLReader reader = new PartsInfoXMLReader();
\r
1108 partsManageData = reader.loadPartsManageData(docBase);
\r
1110 } catch (Exception ex) {
\r
1111 logger.log(Level.WARNING, ex.toString(), ex);
\r
1114 if (partsManageData == null) {
\r
1115 partsManageData = new PartsManageData();
\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
1124 // パーツ管理情報ファイルから、パーツ管理情報を設定した時点の
\r
1125 // ファイルサイズや更新日時などを読み取る.
\r
1126 PartsKey partsKey = new PartsKey(partsIdentifier);
\r
1127 PartsVersionInfo versionInfo = partsManageData
\r
1128 .getVersion(partsKey);
\r
1130 Timestamp lastModified = null;
\r
1132 if (versionInfo != null) {
\r
1133 lastModified = versionInfo.getLastModified();
\r
1136 PartsManageTableRow row = new PartsManageTableRow(
\r
1137 partsIdentifier, partsSpec, lastModified);
\r
1146 * ホームページを設定する.<br>
\r
1147 * ホームページはAuthorに対して1つであるが、Authorが自由編集可能であるため便宜的にRowに持たせている.<br>
\r
1148 * 結果として同じAuthorに対して同じ値を設定する必要がある.<br>
\r
1149 * ホームページはテーブルに表示されないのでリスナーへの通知は行わない.<br>
\r
1152 * 作者、空またはnullは何もしない.
\r
1156 public void setHomepage(String author, String homepage) {
\r
1157 if (author == null || author.length() == 0) {
\r
1160 for (PartsManageTableRow row : elements) {
\r
1161 String targetAuthor = row.getAuthor();
\r
1162 if (targetAuthor == null) {
\r
1163 targetAuthor = "";
\r
1165 if (targetAuthor.equals(author)) {
\r
1166 row.setHomepage(homepage);
\r
1172 * ホームページを取得する.<br>
\r
1173 * 該当する作者がないか、作者がnullまたは空の場合は常にnullを返す.<br>
\r
1177 * @return ホームページ、またはnull
\r
1179 public String getHomepage(String author) {
\r
1180 if (author == null || author.length() == 0) {
\r
1183 for (PartsManageTableRow row : elements) {
\r
1184 String targetAuthor = row.getAuthor();
\r
1185 if (targetAuthor == null) {
\r
1186 targetAuthor = "";
\r
1188 if (targetAuthor.equals(author)) {
\r
1189 return row.getHomepage();
\r
1195 protected static final Comparator<PartsManageTableRow> NAMED_SORTER
\r
1196 = new Comparator<PartsManageTableRow>() {
\r
1197 public int compare(PartsManageTableRow o1, PartsManageTableRow o2) {
\r
1199 int ret = o1.getPartsIdentifier().getPartsCategory().compareTo(
\r
1200 o2.getPartsIdentifier().getPartsCategory());
\r
1203 String lnm1 = o1.getLocalizedName();
\r
1204 String lnm2 = o2.getLocalizedName();
\r
1205 if (lnm1 == null) {
\r
1208 if (lnm2 == null) {
\r
1211 ret = lnm1.compareTo(lnm2);
\r
1214 // それでも判定できなければ元の識別子で判定する.
\r
1215 ret = o1.getPartsIdentifier().compareTo(o2.getPartsIdentifier());
\r
1221 public void sortByName() {
\r
1222 Collections.sort(elements, NAMED_SORTER);
\r
1223 fireTableDataChanged();
\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
1232 // それでも判定できなければ名前順と同じ
\r
1233 ret = NAMED_SORTER.compare(o1, o2);
\r
1238 fireTableDataChanged();
\r
1241 public void sortByAuthor() {
\r
1242 Collections.sort(elements, new Comparator<PartsManageTableRow>() {
\r
1243 public int compare(PartsManageTableRow o1, PartsManageTableRow o2) {
\r
1245 String author1 = o1.getAuthor();
\r
1246 String author2 = o2.getAuthor();
\r
1247 if (author1 == null) {
\r
1250 if (author2 == null) {
\r
1253 int ret = author1.compareTo(author2);
\r
1255 // それでも判定できなければ名前順と同じ
\r
1256 ret = NAMED_SORTER.compare(o1, o2);
\r
1261 fireTableDataChanged();
\r