/* * $Id$ * * Copyright (c) 2005 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.configure; import java.awt.Component; import java.awt.Dimension; import java.awt.Frame; import java.awt.HeadlessException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.util.Properties; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.SwingUtilities; import VASSAL.build.GameModule; import VASSAL.build.module.Documentation; import VASSAL.build.module.documentation.HelpFile; import VASSAL.tools.ErrorDialog; import VASSAL.tools.SavedGameUpdater; import VASSAL.tools.ScrollPane; import VASSAL.tools.io.IOUtils; public class SavedGameUpdaterDialog extends JDialog { private static final long serialVersionUID = 1L; private DefaultListModel savedGamesModel; private SavedGameUpdater updater = new SavedGameUpdater(); private Properties oldPieceInfo; private JFileChooser fc; private static final String VERSION_KEY = "moduleVerion"; private static final String MODULE_NAME_KEY = "moduleName"; private JButton updateButton; private JTextField versionField; public SavedGameUpdaterDialog(Frame owner) throws HeadlessException { super(owner, false); setTitle("Update Saved Games"); initComponents(); fc = new JFileChooser(); fc.setCurrentDirectory(GameModule.getGameModule().getFileChooser().getCurrentDirectory()); } private void initComponents() { setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); Box versionBox = Box.createHorizontalBox(); versionBox.add(new JLabel("Module version of saved games: ")); versionField = new JTextField(8); versionField.setEditable(false); versionField.setMaximumSize(new Dimension(versionField.getMaximumSize().width, versionField.getPreferredSize().height)); versionBox.add(versionField); JButton importButton = new JButton("Import GamePiece info"); importButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { importPieceInfo(); } }); versionBox.add(importButton); add(versionBox); JButton exportButton = new JButton("Export GamePiece info"); exportButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { exportPieceInfo(); } }); Box importExportBox = Box.createHorizontalBox(); importExportBox.add(importButton); importExportBox.add(exportButton); add(importExportBox); Box savedGamesBox = Box.createHorizontalBox(); Box left = Box.createVerticalBox(); left.add(new JLabel("Saved Games:")); JButton chooseGamesButton = new JButton("Choose"); chooseGamesButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { chooseSavedGames(); } }); left.add(chooseGamesButton); savedGamesBox.add(left); savedGamesModel = new DefaultListModel(); JList savedGamesList = new JList(savedGamesModel); savedGamesList.setVisibleRowCount(5); savedGamesList.setCellRenderer(new DefaultListCellRenderer() { private static final long serialVersionUID = 1L; public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); setText(((File) value).getName()); return this; } }); savedGamesBox.add(new ScrollPane(savedGamesList)); add(savedGamesBox); Box buttonsBox = Box.createHorizontalBox(); updateButton = new JButton("Update games"); updateButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { updateGames(); } }); updateButton.setEnabled(false); buttonsBox.add(updateButton); JButton helpButton = new JButton("Help"); HelpFile hf = null; try { hf = new HelpFile(null, new File( new File(Documentation.getDocumentationBaseDir(), "ReferenceManual"), "SavedGameUpdater.htm")); } catch (MalformedURLException ex) { ErrorDialog.bug(ex); } helpButton.addActionListener(new ShowHelpAction(hf.getContents(), null)); buttonsBox.add(helpButton); JButton closeButton = new JButton("Close"); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); buttonsBox.add(closeButton); add(buttonsBox); pack(); setLocationRelativeTo(getOwner()); } private void updateGames() { updateButton.setEnabled(false); Runnable runnable = new Runnable() { public void run() { for (int i=0,n=savedGamesModel.size();i<n;++i) { try { File savedGame = (File)savedGamesModel.getElementAt(i); updater.updateSavedGame(oldPieceInfo,savedGame); GameModule.getGameModule().warn("Updated "+savedGame.getName()+" from version "+versionField.getText()+" to "+GameModule.getGameModule().getGameVersion()); } // FIXME: review error message catch (final IOException e) { Runnable showError = new Runnable() { public void run() { showErrorMessage(e,"Update failed","Unable to save file"); } }; try { SwingUtilities.invokeAndWait(showError); } // FIXME: review error message catch (InterruptedException e1) { } // FIXME: review error message catch (InvocationTargetException e1) { } } } updateButton.setEnabled(true); } }; new Thread(runnable).start(); } private void chooseSavedGames() { fc.setMultiSelectionEnabled(true); if (JFileChooser.CANCEL_OPTION != fc.showOpenDialog(this)) { File[] selectedFiles = fc.getSelectedFiles(); if (selectedFiles != null) { savedGamesModel.clear(); for (int i = 0; i < selectedFiles.length; i++) { savedGamesModel.addElement(selectedFiles[i]); } } } } private void exportPieceInfo() { fc.setMultiSelectionEnabled(false); if (JFileChooser.CANCEL_OPTION != fc.showSaveDialog(this)) { final Properties p = updater.getPieceSlotsMap(); p.put(MODULE_NAME_KEY, GameModule.getGameModule().getGameName()); p.put(VERSION_KEY, GameModule.getGameModule().getGameVersion()); BufferedOutputStream out = null; try { out = new BufferedOutputStream( new FileOutputStream(fc.getSelectedFile())); p.store(out, null); out.close(); } // FIXME: review error message catch (IOException e) { showErrorMessage(e, "Export failed","Unable to write info"); } finally { IOUtils.closeQuietly(out); } } } private void importPieceInfo() { fc.setMultiSelectionEnabled(false); if (JFileChooser.CANCEL_OPTION != fc.showOpenDialog(this)) { oldPieceInfo = new Properties(); BufferedInputStream in = null; try { in = new BufferedInputStream(new FileInputStream(fc.getSelectedFile())); oldPieceInfo.load(in); in.close(); String moduleVersion = oldPieceInfo.getProperty(VERSION_KEY); String moduleName = oldPieceInfo.getProperty(MODULE_NAME_KEY); if (!GameModule.getGameModule().getGameName().equals(moduleName)) { showErrorMessage(null,"Import failed","Imported info is from the wrong module: "+moduleName); oldPieceInfo = null; versionField.setText(null); } else if (GameModule.getGameModule().getGameVersion().equals(moduleVersion)) { showErrorMessage(null,"Import failed","Imported info is from the current version, "+moduleVersion+".\nLoad the older version in the editor and export the GamePiece info,\nThen load this module again and import the older version's info"); oldPieceInfo = null; versionField.setText(null); } else { versionField.setText(moduleVersion); } } // FIXME: review error message catch (IOException e) { showErrorMessage(e,"Import failed","Unable to import info"); oldPieceInfo = null; } catch (IllegalArgumentException e) { // catches malformed input files showErrorMessage(e, "Import failed", "Malformed input file"); oldPieceInfo = null; } finally { IOUtils.closeQuietly(in); } } updateButton.setEnabled(oldPieceInfo != null); } private void showErrorMessage(Exception e, String title, String defaultMessage) { String msg = e == null ? null : e.getMessage(); if (msg == null) { msg = defaultMessage; } JOptionPane.showMessageDialog(this, msg, title, JOptionPane.ERROR_MESSAGE); } }