Merge pull request #6 from lantzelot-swe/SavedStatesManagement
Saved states management
This commit is contained in:
commit
1ebd6eeaf9
|
@ -54,6 +54,7 @@ public class PCUGameManager
|
|||
Files.createDirectories(Paths.get("./screens/"));
|
||||
Files.createDirectories(Paths.get("./covers/"));
|
||||
Files.createDirectories(Paths.get("./games/"));
|
||||
Files.createDirectories(Paths.get("./saves/"));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@ import javax.swing.JComponent;
|
|||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
@ -52,8 +53,10 @@ public class GameDetailsBackgroundPanel extends JPanel
|
|||
private final MainViewModel model;
|
||||
private ScrollablePanel settingsPanel;
|
||||
private InfoBackgroundPanel infoPanel;
|
||||
private JTabbedPane systemSavesTabbedPane;
|
||||
private CombinedJoystickPanel joystickPanel;
|
||||
private SystemPanel systemPanel;
|
||||
private SaveStateBackgroundPanel savesBackgroundPanel;
|
||||
private JPanel buttonPanel;
|
||||
private JButton saveButton;
|
||||
private ScraperDialog scraperDialog = null;
|
||||
|
@ -163,9 +166,9 @@ public class GameDetailsBackgroundPanel extends JPanel
|
|||
gbc_systemPanel.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_systemPanel.gridx = 1;
|
||||
gbc_systemPanel.gridy = 0;
|
||||
settingsPanel.add(getSystemPanel(), gbc_systemPanel);
|
||||
settingsPanel.add(getSystemSavesTabbedPane(), gbc_systemPanel);
|
||||
GridBagConstraints gbc_joystickPanel = new GridBagConstraints();
|
||||
gbc_joystickPanel.insets = new Insets(0, 5, 0, 0);
|
||||
gbc_joystickPanel.insets = new Insets(0, 0, 0, 0);
|
||||
gbc_joystickPanel.weighty = 1.0;
|
||||
gbc_joystickPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_joystickPanel.fill = GridBagConstraints.BOTH;
|
||||
|
@ -175,6 +178,17 @@ public class GameDetailsBackgroundPanel extends JPanel
|
|||
}
|
||||
return settingsPanel;
|
||||
}
|
||||
|
||||
private JTabbedPane getSystemSavesTabbedPane()
|
||||
{
|
||||
if (systemSavesTabbedPane == null)
|
||||
{
|
||||
systemSavesTabbedPane = new JTabbedPane();
|
||||
systemSavesTabbedPane.addTab("System Settings", getSystemPanel());
|
||||
systemSavesTabbedPane.addTab("Saved states", getSavesBackgroundPanel());
|
||||
}
|
||||
return systemSavesTabbedPane;
|
||||
}
|
||||
|
||||
protected InfoBackgroundPanel getInfoBackgroundPanel()
|
||||
{
|
||||
|
@ -200,10 +214,21 @@ public class GameDetailsBackgroundPanel extends JPanel
|
|||
{
|
||||
systemPanel = new SystemPanel(model.getSystemModel());
|
||||
systemPanel
|
||||
.setBorder(new TitledBorder(null, "System Settings", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
.setBorder(new TitledBorder(null, "", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
}
|
||||
return systemPanel;
|
||||
}
|
||||
|
||||
private SaveStateBackgroundPanel getSavesBackgroundPanel()
|
||||
{
|
||||
if (savesBackgroundPanel == null)
|
||||
{
|
||||
savesBackgroundPanel = new SaveStateBackgroundPanel(model);
|
||||
savesBackgroundPanel
|
||||
.setBorder(new TitledBorder(null, "", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
}
|
||||
return savesBackgroundPanel;
|
||||
}
|
||||
|
||||
private JPanel getButtonPanel()
|
||||
{
|
||||
|
@ -269,6 +294,8 @@ public class GameDetailsBackgroundPanel extends JPanel
|
|||
{
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
//Make sure any edits to time for saved states are commited.
|
||||
savesBackgroundPanel.commitEdits();
|
||||
if (model.saveData())
|
||||
{
|
||||
getInfoBackgroundPanel().getScreensPanel().resetWhenSaved();
|
||||
|
|
|
@ -3,6 +3,7 @@ package se.lantz.gui;
|
|||
import java.awt.Desktop;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -11,10 +12,12 @@ import java.util.List;
|
|||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import se.lantz.gamebase.GamebaseImporter;
|
||||
import se.lantz.gui.checkdescriptions.CheckDescrProgressDialog;
|
||||
|
@ -28,16 +31,21 @@ import se.lantz.gui.dbrestore.RestoreProgressDialog;
|
|||
import se.lantz.gui.dbrestore.RestoreWorker;
|
||||
import se.lantz.gui.exports.ExportFileLoaderWorker;
|
||||
import se.lantz.gui.exports.ExportGamesDialog;
|
||||
import se.lantz.gui.exports.ExportProgressDialog;
|
||||
import se.lantz.gui.exports.ImportExportProgressDialog;
|
||||
import se.lantz.gui.exports.ExportSavedStatesDialog;
|
||||
import se.lantz.gui.exports.ExportSavedStatesWorker;
|
||||
import se.lantz.gui.exports.ExportWorker;
|
||||
import se.lantz.gui.imports.CarouselImportWorker;
|
||||
import se.lantz.gui.imports.GamebaseImportWorker;
|
||||
import se.lantz.gui.imports.ImportOptionsDialog;
|
||||
import se.lantz.gui.imports.ImportProgressDialog;
|
||||
import se.lantz.gui.imports.ImportSavedStatesDialog;
|
||||
import se.lantz.gui.imports.ImportSavedStatesWorker;
|
||||
import se.lantz.manager.BackupManager;
|
||||
import se.lantz.manager.ExportManager;
|
||||
import se.lantz.manager.ImportManager;
|
||||
import se.lantz.manager.RestoreManager;
|
||||
import se.lantz.manager.SavedStatesManager;
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.data.GameListData;
|
||||
import se.lantz.model.data.GameView;
|
||||
|
@ -60,8 +68,10 @@ public class MenuManager
|
|||
private JMenuItem runGameItem;
|
||||
private JMenuItem importCarouselItem;
|
||||
private JMenuItem importGamebaseItem;
|
||||
private JMenuItem importSavedStatesItem;
|
||||
private JMenuItem exportItem;
|
||||
private JMenuItem exportFLItem;
|
||||
private JMenuItem exportSavedStatesItem;
|
||||
private JMenuItem refreshItem;
|
||||
|
||||
private JMenuItem toggleFavorite1Item;
|
||||
|
@ -104,6 +114,7 @@ public class MenuManager
|
|||
private ExportManager exportManager;
|
||||
private BackupManager backupManager;
|
||||
private RestoreManager restoreManager;
|
||||
private SavedStatesManager savedStatesManager;
|
||||
private MainWindow mainWindow;
|
||||
|
||||
public MenuManager(final MainViewModel uiModel, MainWindow mainWindow)
|
||||
|
@ -115,6 +126,8 @@ public class MenuManager
|
|||
this.exportManager = new ExportManager(uiModel);
|
||||
this.backupManager = new BackupManager(uiModel);
|
||||
this.restoreManager = new RestoreManager(uiModel);
|
||||
this.savedStatesManager = new SavedStatesManager(uiModel);
|
||||
uiModel.setSavedStatesManager(savedStatesManager);
|
||||
setupMenues();
|
||||
}
|
||||
|
||||
|
@ -137,10 +150,12 @@ public class MenuManager
|
|||
fileMenu.add(importMenu);
|
||||
importMenu.add(getImportCarouselItem());
|
||||
importMenu.add(getImportGamebaseItem());
|
||||
importMenu.add(getImportSavedStatesItem());
|
||||
exportMenu = new JMenu("Export");
|
||||
exportMenu.setMnemonic('X');
|
||||
exportMenu.setMnemonic('E');
|
||||
exportMenu.add(getExportItem());
|
||||
exportMenu.add(getExportFileLoaderItem());
|
||||
exportMenu.add(getExportSavedStatesItem());
|
||||
fileMenu.add(exportMenu);
|
||||
fileMenu.addSeparator();
|
||||
fileMenu.add(getRefreshItem());
|
||||
|
@ -215,7 +230,7 @@ public class MenuManager
|
|||
addGameItem = new JMenuItem("Add new game");
|
||||
KeyStroke keyStrokeToAddGame = KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK);
|
||||
addGameItem.setAccelerator(keyStrokeToAddGame);
|
||||
addGameItem.setMnemonic('N');
|
||||
addGameItem.setMnemonic('A');
|
||||
|
||||
addGameItem.addActionListener(e -> mainWindow.getMainPanel().addNewGame());
|
||||
return addGameItem;
|
||||
|
@ -271,6 +286,14 @@ public class MenuManager
|
|||
return importGamebaseItem;
|
||||
}
|
||||
|
||||
private JMenuItem getImportSavedStatesItem()
|
||||
{
|
||||
importSavedStatesItem = new JMenuItem("Import Saved states...");
|
||||
importSavedStatesItem.setMnemonic('S');
|
||||
importSavedStatesItem.addActionListener(e -> importSavedStates());
|
||||
return importSavedStatesItem;
|
||||
}
|
||||
|
||||
private JMenuItem getExportItem()
|
||||
{
|
||||
exportItem = new JMenuItem("Export to Carousel...");
|
||||
|
@ -291,6 +314,14 @@ public class MenuManager
|
|||
return exportFLItem;
|
||||
}
|
||||
|
||||
private JMenuItem getExportSavedStatesItem()
|
||||
{
|
||||
exportSavedStatesItem = new JMenuItem("Export Saved states...");
|
||||
exportSavedStatesItem.setMnemonic('S');
|
||||
exportSavedStatesItem.addActionListener(e -> exportSavedStates());
|
||||
return exportSavedStatesItem;
|
||||
}
|
||||
|
||||
private JMenuItem getRefreshItem()
|
||||
{
|
||||
refreshItem = new JMenuItem("Reload current gamelist view");
|
||||
|
@ -728,6 +759,38 @@ public class MenuManager
|
|||
}
|
||||
}
|
||||
|
||||
private void importSavedStates()
|
||||
{
|
||||
final ImportSavedStatesDialog importSavedStatesDialog = new ImportSavedStatesDialog(MainWindow.getInstance());
|
||||
importSavedStatesDialog.pack();
|
||||
importSavedStatesDialog.setLocationRelativeTo(this.mainWindow);
|
||||
if (importSavedStatesDialog.showDialog())
|
||||
{
|
||||
savedStatesManager.setImportDirectory(importSavedStatesDialog.getTargetDirectory());
|
||||
savedStatesManager.setImportOverwrite(importSavedStatesDialog.isImportOverwrite());
|
||||
ImportExportProgressDialog dialog = new ImportExportProgressDialog(this.mainWindow, "Import saved states", true);
|
||||
ImportSavedStatesWorker worker = new ImportSavedStatesWorker(savedStatesManager, dialog);
|
||||
worker.execute();
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void exportSavedStates()
|
||||
{
|
||||
final ExportSavedStatesDialog exportSavedStatesDialog = new ExportSavedStatesDialog(MainWindow.getInstance());
|
||||
exportSavedStatesDialog.pack();
|
||||
exportSavedStatesDialog.setLocationRelativeTo(this.mainWindow);
|
||||
if (exportSavedStatesDialog.showDialog())
|
||||
{
|
||||
savedStatesManager.setExportDirectory(exportSavedStatesDialog.getTargetDirectory());
|
||||
savedStatesManager.setExportOverwrite(exportSavedStatesDialog.isExportOverwrite());
|
||||
ImportExportProgressDialog dialog = new ImportExportProgressDialog(this.mainWindow, "Export saved states", false);
|
||||
ExportSavedStatesWorker worker = new ExportSavedStatesWorker(savedStatesManager, dialog);
|
||||
worker.execute();
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void exportGames()
|
||||
{
|
||||
final ExportGamesDialog exportSelectionDialog = new ExportGamesDialog(MainWindow.getInstance(), true);
|
||||
|
@ -743,7 +806,7 @@ public class MenuManager
|
|||
exportManager.setGameViewsToExport(viewList);
|
||||
exportManager.setTargetDirectory(exportSelectionDialog.getTargetDirectory(),
|
||||
exportSelectionDialog.deleteBeforeExport());
|
||||
ExportProgressDialog dialog = new ExportProgressDialog(this.mainWindow);
|
||||
ImportExportProgressDialog dialog = new ImportExportProgressDialog(this.mainWindow, "Export games", false);
|
||||
ExportWorker worker = new ExportWorker(exportManager, dialog);
|
||||
worker.execute();
|
||||
dialog.setVisible(true);
|
||||
|
@ -757,7 +820,7 @@ public class MenuManager
|
|||
exportManager.setGamesToExport(gamesList);
|
||||
exportManager.setTargetDirectory(exportSelectionDialog.getTargetDirectory(),
|
||||
exportSelectionDialog.deleteBeforeExport());
|
||||
ExportProgressDialog dialog = new ExportProgressDialog(this.mainWindow);
|
||||
ImportExportProgressDialog dialog = new ImportExportProgressDialog(this.mainWindow, "Export games", false);
|
||||
ExportWorker worker = new ExportWorker(exportManager, dialog);
|
||||
worker.execute();
|
||||
dialog.setVisible(true);
|
||||
|
@ -781,7 +844,7 @@ public class MenuManager
|
|||
exportManager.setGameViewsToExport(viewList);
|
||||
exportManager.setTargetDirectory(exportSelectionDialog.getTargetDirectory(),
|
||||
exportSelectionDialog.deleteBeforeExport());
|
||||
ExportProgressDialog dialog = new ExportProgressDialog(this.mainWindow);
|
||||
ImportExportProgressDialog dialog = new ImportExportProgressDialog(this.mainWindow, "Export games", false);
|
||||
ExportFileLoaderWorker worker = new ExportFileLoaderWorker(exportManager, dialog);
|
||||
worker.execute();
|
||||
dialog.setVisible(true);
|
||||
|
@ -795,7 +858,7 @@ public class MenuManager
|
|||
exportManager.setGamesToExport(gamesList);
|
||||
exportManager.setTargetDirectory(exportSelectionDialog.getTargetDirectory(),
|
||||
exportSelectionDialog.deleteBeforeExport());
|
||||
ExportProgressDialog dialog = new ExportProgressDialog(this.mainWindow);
|
||||
ImportExportProgressDialog dialog = new ImportExportProgressDialog(this.mainWindow, "Export games", false);
|
||||
ExportFileLoaderWorker worker = new ExportFileLoaderWorker(exportManager, dialog);
|
||||
worker.execute();
|
||||
dialog.setVisible(true);
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.GridBagLayout;
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.SavedStatesModel.SAVESTATE;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
|
||||
public class SaveStateBackgroundPanel extends JPanel
|
||||
{
|
||||
private SaveStatePanel saveStatePanel1;
|
||||
private MainViewModel model;
|
||||
private SaveStatePanel saveStatePanel2;
|
||||
private SaveStatePanel saveStatePanel3;
|
||||
private SaveStatePanel saveStatePanel4;
|
||||
public SaveStateBackgroundPanel(MainViewModel model) {
|
||||
this.model = model;
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_saveStatePanel1 = new GridBagConstraints();
|
||||
gbc_saveStatePanel1.anchor = GridBagConstraints.NORTH;
|
||||
gbc_saveStatePanel1.weightx = 1.0;
|
||||
gbc_saveStatePanel1.fill = GridBagConstraints.BOTH;
|
||||
gbc_saveStatePanel1.gridx = 0;
|
||||
gbc_saveStatePanel1.gridy = 0;
|
||||
add(getSaveStatePanel1(), gbc_saveStatePanel1);
|
||||
GridBagConstraints gbc_saveStatePanel2 = new GridBagConstraints();
|
||||
gbc_saveStatePanel2.anchor = GridBagConstraints.NORTH;
|
||||
gbc_saveStatePanel2.weightx = 1.0;
|
||||
gbc_saveStatePanel2.fill = GridBagConstraints.BOTH;
|
||||
gbc_saveStatePanel2.gridx = 0;
|
||||
gbc_saveStatePanel2.gridy = 1;
|
||||
add(getSaveStatePanel2(), gbc_saveStatePanel2);
|
||||
GridBagConstraints gbc_saveStatePanel3 = new GridBagConstraints();
|
||||
gbc_saveStatePanel3.anchor = GridBagConstraints.NORTH;
|
||||
gbc_saveStatePanel3.weightx = 1.0;
|
||||
gbc_saveStatePanel3.fill = GridBagConstraints.BOTH;
|
||||
gbc_saveStatePanel3.gridx = 0;
|
||||
gbc_saveStatePanel3.gridy = 2;
|
||||
add(getSaveStatePanel3(), gbc_saveStatePanel3);
|
||||
GridBagConstraints gbc_saveStatePanel4 = new GridBagConstraints();
|
||||
gbc_saveStatePanel4.anchor = GridBagConstraints.NORTH;
|
||||
gbc_saveStatePanel4.weightx = 1.0;
|
||||
gbc_saveStatePanel4.weighty = 1.0;
|
||||
gbc_saveStatePanel4.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_saveStatePanel4.gridx = 0;
|
||||
gbc_saveStatePanel4.gridy = 3;
|
||||
add(getSaveStatePanel4(), gbc_saveStatePanel4);
|
||||
}
|
||||
private SaveStatePanel getSaveStatePanel1() {
|
||||
if (saveStatePanel1 == null) {
|
||||
saveStatePanel1 = new SaveStatePanel(model, SAVESTATE.Save0);
|
||||
}
|
||||
return saveStatePanel1;
|
||||
}
|
||||
private SaveStatePanel getSaveStatePanel2() {
|
||||
if (saveStatePanel2 == null) {
|
||||
saveStatePanel2 = new SaveStatePanel(model, SAVESTATE.Save1);
|
||||
}
|
||||
return saveStatePanel2;
|
||||
}
|
||||
private SaveStatePanel getSaveStatePanel3() {
|
||||
if (saveStatePanel3 == null) {
|
||||
saveStatePanel3 = new SaveStatePanel(model, SAVESTATE.Save2);
|
||||
}
|
||||
return saveStatePanel3;
|
||||
}
|
||||
private SaveStatePanel getSaveStatePanel4() {
|
||||
if (saveStatePanel4 == null) {
|
||||
saveStatePanel4 = new SaveStatePanel(model, SAVESTATE.Save3);
|
||||
}
|
||||
return saveStatePanel4;
|
||||
}
|
||||
|
||||
void commitEdits()
|
||||
{
|
||||
getSaveStatePanel1().commitEdits();
|
||||
getSaveStatePanel2().commitEdits();
|
||||
getSaveStatePanel3().commitEdits();
|
||||
getSaveStatePanel4().commitEdits();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,762 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.Beans;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.ParseException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import javax.swing.text.MaskFormatter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.manager.SavedStatesManager;
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.SavedStatesModel;
|
||||
import se.lantz.model.SavedStatesModel.SAVESTATE;
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
import se.lantz.util.FileDrop;
|
||||
import se.lantz.util.FileManager;
|
||||
|
||||
public class SaveStatePanel extends JPanel
|
||||
{
|
||||
private static final String SNAPSHOT_DIR_PROPERTY = "snapshotDir";
|
||||
private static final Logger logger = LoggerFactory.getLogger(SaveStatePanel.class);
|
||||
private JLabel screenshotLabel;
|
||||
private JTextField snapshotTextField;
|
||||
private MainViewModel model;
|
||||
private SavedStatesModel stateModel;
|
||||
private JButton snapshotButton;
|
||||
private BufferedImage currentScreenImage = null;
|
||||
private String currentGameFile = "";
|
||||
private ImageIcon missingSceenshotIcon = null;
|
||||
private JLabel timeLabel;
|
||||
private JLabel snapshotLabel;
|
||||
private JFormattedTextField timeField;
|
||||
private JButton runButton;
|
||||
private boolean gamesFileUpdated = false;
|
||||
private SAVESTATE saveState;
|
||||
private JSeparator separator;
|
||||
private JButton screenshotButton;
|
||||
|
||||
private FileNameExtensionFilter imagefilter =
|
||||
new FileNameExtensionFilter("png, gif, jpeg, bmp", "png", "gif", "jpg", "jpeg", "bmp");
|
||||
|
||||
public SaveStatePanel(MainViewModel model, SAVESTATE saveState)
|
||||
{
|
||||
this.model = model;
|
||||
this.saveState = saveState;
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
this.stateModel = model.getSavedStatesModel();
|
||||
}
|
||||
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_screenshotLabel = new GridBagConstraints();
|
||||
gbc_screenshotLabel.weighty = 1.0;
|
||||
gbc_screenshotLabel.gridheight = 3;
|
||||
gbc_screenshotLabel.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_screenshotLabel.insets = new Insets(1, 1, 0, 1);
|
||||
gbc_screenshotLabel.gridx = 0;
|
||||
gbc_screenshotLabel.gridy = 0;
|
||||
add(getScreenshotLabel(), gbc_screenshotLabel);
|
||||
GridBagConstraints gbc_timeTextField = new GridBagConstraints();
|
||||
gbc_timeTextField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_timeTextField.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_timeTextField.weighty = 1.0;
|
||||
gbc_timeTextField.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_timeTextField.gridx = 3;
|
||||
gbc_timeTextField.gridy = 1;
|
||||
add(getTimeField(), gbc_timeTextField);
|
||||
GridBagConstraints gbc_snapshotTextField = new GridBagConstraints();
|
||||
gbc_snapshotTextField.weightx = 1.0;
|
||||
gbc_snapshotTextField.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_snapshotTextField.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_snapshotTextField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_snapshotTextField.gridx = 1;
|
||||
gbc_snapshotTextField.gridy = 1;
|
||||
add(getSnapshotTextField(), gbc_snapshotTextField);
|
||||
GridBagConstraints gbc_snapshotButton = new GridBagConstraints();
|
||||
gbc_snapshotButton.insets = new Insets(-1, 0, 5, 5);
|
||||
gbc_snapshotButton.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_snapshotButton.gridx = 2;
|
||||
gbc_snapshotButton.gridy = 1;
|
||||
add(getGameButton(), gbc_snapshotButton);
|
||||
GridBagConstraints gbc_timeLabel = new GridBagConstraints();
|
||||
gbc_timeLabel.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_timeLabel.insets = new Insets(5, 5, 0, 0);
|
||||
gbc_timeLabel.gridx = 3;
|
||||
gbc_timeLabel.gridy = 0;
|
||||
add(getTimeLabel(), gbc_timeLabel);
|
||||
GridBagConstraints gbc_snapshotLabel = new GridBagConstraints();
|
||||
gbc_snapshotLabel.weightx = 1.0;
|
||||
gbc_snapshotLabel.insets = new Insets(5, 0, 0, 5);
|
||||
gbc_snapshotLabel.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_snapshotLabel.gridx = 1;
|
||||
gbc_snapshotLabel.gridy = 0;
|
||||
add(getSnapshotLabel(), gbc_snapshotLabel);
|
||||
GridBagConstraints gbc_screenshotButton = new GridBagConstraints();
|
||||
gbc_screenshotButton.weightx = 1.0;
|
||||
gbc_screenshotButton.anchor = GridBagConstraints.SOUTHWEST;
|
||||
gbc_screenshotButton.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_screenshotButton.gridx = 1;
|
||||
gbc_screenshotButton.gridy = 2;
|
||||
add(getScreenshotButton(), gbc_screenshotButton);
|
||||
GridBagConstraints gbc_runButton = new GridBagConstraints();
|
||||
gbc_runButton.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_runButton.weighty = 1.0;
|
||||
gbc_runButton.anchor = GridBagConstraints.SOUTHEAST;
|
||||
gbc_runButton.gridx = 3;
|
||||
gbc_runButton.gridy = 2;
|
||||
add(getRunButton(), gbc_runButton);
|
||||
if (saveState != SAVESTATE.Save3)
|
||||
{
|
||||
GridBagConstraints gbc_separator = new GridBagConstraints();
|
||||
gbc_separator.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_separator.insets = new Insets(5, 20, 0, 20);
|
||||
gbc_separator.gridwidth = 4;
|
||||
gbc_separator.gridx = 0;
|
||||
gbc_separator.gridy = 3;
|
||||
add(getSeparator(), gbc_separator);
|
||||
}
|
||||
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
stateModel.addPropertyChangeListener((e) -> modelChanged());
|
||||
}
|
||||
}
|
||||
|
||||
private void modelChanged()
|
||||
{
|
||||
if (!stateModel.isDataChanged())
|
||||
{
|
||||
gamesFileUpdated = false;
|
||||
}
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
if (!stateModel.getState1time().equals(getTimeField().getValue()))
|
||||
{
|
||||
getTimeField().setValue(stateModel.getState1time());
|
||||
}
|
||||
break;
|
||||
case Save1:
|
||||
if (!stateModel.getState2time().equals(getTimeField().getValue()))
|
||||
{
|
||||
getTimeField().setValue(stateModel.getState2time());
|
||||
}
|
||||
break;
|
||||
case Save2:
|
||||
if (!stateModel.getState3time().equals(getTimeField().getValue()))
|
||||
{
|
||||
getTimeField().setValue(stateModel.getState3time());
|
||||
}
|
||||
break;
|
||||
case Save3:
|
||||
if (!stateModel.getState4time().equals(getTimeField().getValue()))
|
||||
{
|
||||
getTimeField().setValue(stateModel.getState4time());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
// Read from model
|
||||
getSnapshotTextField().setText(getSnapshotFileName());
|
||||
reloadScreen();
|
||||
getRunButton().setEnabled(!getSnapshotTextField().getText().isEmpty());
|
||||
getTimeField().setEnabled(!getSnapshotTextField().getText().isEmpty());
|
||||
}
|
||||
|
||||
private String getSnapshotFileName()
|
||||
{
|
||||
String returnValue = "";
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
returnValue = stateModel.getState1File();
|
||||
break;
|
||||
case Save1:
|
||||
returnValue = stateModel.getState2File();
|
||||
break;
|
||||
case Save2:
|
||||
returnValue = stateModel.getState3File();
|
||||
break;
|
||||
case Save3:
|
||||
returnValue = stateModel.getState4File();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (gamesFileUpdated)
|
||||
{
|
||||
returnValue = returnValue + " (updated)";
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private void reloadScreen()
|
||||
{
|
||||
BufferedImage screen1Image = null;
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
screen1Image = stateModel.getState1PngImage();
|
||||
break;
|
||||
case Save1:
|
||||
screen1Image = stateModel.getState2PngImage();
|
||||
break;
|
||||
case Save2:
|
||||
screen1Image = stateModel.getState3PngImage();
|
||||
break;
|
||||
case Save3:
|
||||
screen1Image = stateModel.getState4PngImage();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
if (screen1Image != null)
|
||||
{
|
||||
if (!screen1Image.equals(currentScreenImage))
|
||||
{
|
||||
logger.debug("SETTING SCREEN 1 IMAGE");
|
||||
Image newImage = screen1Image.getScaledInstance(130, 82, Image.SCALE_SMOOTH);
|
||||
getScreenshotLabel().setIcon(new ImageIcon(newImage));
|
||||
currentScreenImage = screen1Image;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String modelScreenFile = "";
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
modelScreenFile = stateModel.getState1PngFile();
|
||||
break;
|
||||
case Save1:
|
||||
modelScreenFile = stateModel.getState2PngFile();
|
||||
break;
|
||||
case Save2:
|
||||
modelScreenFile = stateModel.getState3PngFile();
|
||||
break;
|
||||
case Save3:
|
||||
modelScreenFile = stateModel.getState4PngFile();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
if (modelScreenFile.isEmpty())
|
||||
{
|
||||
getScreenshotLabel().setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
else if (!model.getInfoModel().getGamesFile().equals(currentGameFile))
|
||||
{
|
||||
currentScreenImage = loadScreen(modelScreenFile, getScreenshotLabel());
|
||||
}
|
||||
//Keep track of which game is selected
|
||||
currentGameFile = model.getInfoModel().getGamesFile();
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage loadScreen(String filename, JLabel screenLabel)
|
||||
{
|
||||
BufferedImage image = null;
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
String fileName = model.getInfoModel().getGamesFile();
|
||||
System.out.println(fileName.toString());
|
||||
|
||||
Path saveFolderPath = new File("./saves/" + fileName).toPath();
|
||||
File imagefile = saveFolderPath.resolve(filename).toFile();
|
||||
try
|
||||
{
|
||||
image = ImageIO.read(imagefile);
|
||||
Image newImage = image.getScaledInstance(130, 82, Image.SCALE_SMOOTH);
|
||||
screenLabel.setIcon(new ImageIcon(newImage));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("can't read file: " + filename, e);
|
||||
screenLabel.setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screenLabel.setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private ImageIcon getMissingScreenshotImageIcon()
|
||||
{
|
||||
if (missingSceenshotIcon == null)
|
||||
{
|
||||
BufferedImage image = null;
|
||||
try
|
||||
{
|
||||
image = ImageIO.read(FileManager.class.getResource("/se/lantz/EmptySaveSlot.png"));
|
||||
Image newImage = image.getScaledInstance(130, 82, Image.SCALE_SMOOTH);
|
||||
missingSceenshotIcon = new ImageIcon(newImage);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("can't read missing icon", e);
|
||||
|
||||
}
|
||||
}
|
||||
return missingSceenshotIcon;
|
||||
}
|
||||
|
||||
private JLabel getScreenshotLabel()
|
||||
{
|
||||
if (screenshotLabel == null)
|
||||
{
|
||||
screenshotLabel = new JLabel("");
|
||||
new FileDrop(screenshotLabel, new FileDrop.Listener()
|
||||
{
|
||||
public void filesDropped(java.io.File[] files)
|
||||
{
|
||||
setScreenshotFileToModel(files);
|
||||
}
|
||||
});
|
||||
}
|
||||
return screenshotLabel;
|
||||
}
|
||||
|
||||
private JTextField getSnapshotTextField()
|
||||
{
|
||||
if (snapshotTextField == null)
|
||||
{
|
||||
snapshotTextField = new JTextField();
|
||||
snapshotTextField.setEditable(false);
|
||||
snapshotTextField.setPreferredSize(new Dimension(30, 20));
|
||||
new FileDrop(snapshotTextField, new FileDrop.Listener()
|
||||
{
|
||||
public void filesDropped(java.io.File[] files)
|
||||
{
|
||||
if (files.length > 0)
|
||||
{
|
||||
gamesFileUpdated = true;
|
||||
if (files[0].getName().toLowerCase().endsWith(".vsf"))
|
||||
{
|
||||
setSnapshotFileToModel(files[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
return snapshotTextField;
|
||||
}
|
||||
|
||||
private JButton getGameButton()
|
||||
{
|
||||
if (snapshotButton == null)
|
||||
{
|
||||
snapshotButton = new JButton("...");
|
||||
snapshotButton.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
selectSnapshotFile();
|
||||
}
|
||||
});
|
||||
snapshotButton.setMargin(new Insets(1, 3, 1, 3));
|
||||
}
|
||||
return snapshotButton;
|
||||
}
|
||||
|
||||
private void selectSnapshotFile()
|
||||
{
|
||||
final JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Select a Vice snapsot file for " + model.getInfoModel().getTitle());
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
String gameDir = FileManager.getConfiguredProperties().getProperty(SNAPSHOT_DIR_PROPERTY);
|
||||
if (gameDir == null)
|
||||
{
|
||||
gameDir = ".";
|
||||
}
|
||||
fileChooser.setCurrentDirectory(new File(gameDir));
|
||||
|
||||
FileNameExtensionFilter vicefilter = new FileNameExtensionFilter("Vice snapshot", "vsf");
|
||||
fileChooser.addChoosableFileFilter(vicefilter);
|
||||
fileChooser.setFileFilter(vicefilter);
|
||||
int value = fileChooser.showOpenDialog(MainWindow.getInstance());
|
||||
if (value == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
FileManager.getConfiguredProperties().put(SNAPSHOT_DIR_PROPERTY, selectedFile.toPath().getParent().toString());
|
||||
gamesFileUpdated = true;
|
||||
setSnapshotFileToModel(selectedFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSnapshotFileToModel(File file)
|
||||
{
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
stateModel.setState1File(SavedStatesManager.VSZ0);
|
||||
stateModel.setState1Path(file.toPath());
|
||||
break;
|
||||
case Save1:
|
||||
stateModel.setState2File(SavedStatesManager.VSZ1);
|
||||
stateModel.setState2Path(file.toPath());
|
||||
break;
|
||||
case Save2:
|
||||
stateModel.setState3File(SavedStatesManager.VSZ2);
|
||||
stateModel.setState3Path(file.toPath());
|
||||
break;
|
||||
case Save3:
|
||||
stateModel.setState4File(SavedStatesManager.VSZ3);
|
||||
stateModel.setState4Path(file.toPath());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private JLabel getTimeLabel()
|
||||
{
|
||||
if (timeLabel == null)
|
||||
{
|
||||
timeLabel = new JLabel("Play time");
|
||||
}
|
||||
return timeLabel;
|
||||
}
|
||||
|
||||
private JLabel getSnapshotLabel()
|
||||
{
|
||||
if (snapshotLabel == null)
|
||||
{
|
||||
snapshotLabel = new JLabel("Vice snapshot");
|
||||
}
|
||||
return snapshotLabel;
|
||||
}
|
||||
|
||||
private JFormattedTextField getTimeField()
|
||||
{
|
||||
if (timeField == null)
|
||||
{
|
||||
MaskFormatter formatter = null;
|
||||
try
|
||||
{
|
||||
formatter = new MaskFormatter("##:##:##");
|
||||
}
|
||||
catch (java.text.ParseException exc)
|
||||
{
|
||||
System.err.println("formatter is bad: " + exc.getMessage());
|
||||
System.exit(-1);
|
||||
}
|
||||
formatter.setPlaceholderCharacter('0');
|
||||
timeField = new JFormattedTextField(formatter);
|
||||
|
||||
timeField.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
/**
|
||||
* Handles increase/decrease of time value with arrow buttons
|
||||
*
|
||||
* @param e keyevent
|
||||
*/
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (e.getKeyCode() == KeyEvent.VK_UP)
|
||||
{
|
||||
increaseTime(timeField.getCaretPosition());
|
||||
}
|
||||
else if (e.getKeyCode() == KeyEvent.VK_DOWN)
|
||||
{
|
||||
decreaseTime(timeField.getCaretPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
//Only notify of change when text is altered: value is not committed before focus is lost.
|
||||
if (!timeField.getText().equals(timeField.getValue()))
|
||||
{
|
||||
stateModel.notifyChange();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
timeField.addFocusListener(new FocusAdapter()
|
||||
{
|
||||
@Override
|
||||
public void focusLost(FocusEvent e)
|
||||
{
|
||||
try
|
||||
{
|
||||
timeField.commitEdit();
|
||||
}
|
||||
catch (ParseException e1)
|
||||
{
|
||||
ExceptionHandler.handleException(e1, "");
|
||||
}
|
||||
setTimeToModel();
|
||||
}
|
||||
});
|
||||
timeField.setPreferredSize(new Dimension(55, 20));
|
||||
timeField.setMinimumSize(new Dimension(55, 20));
|
||||
}
|
||||
return timeField;
|
||||
}
|
||||
|
||||
private void increaseTime(int caretPosition)
|
||||
{
|
||||
String currentTime = timeField.getText().toString();
|
||||
String[] splitTime = currentTime.split(":");
|
||||
if (caretPosition < 2)
|
||||
{
|
||||
int newValue = Integer.parseInt(splitTime[0]) + 1;
|
||||
if (newValue < 10)
|
||||
{
|
||||
splitTime[0] = "0" + Integer.toString(newValue);
|
||||
}
|
||||
else if (newValue < 100)
|
||||
{
|
||||
splitTime[0] = Integer.toString(newValue);
|
||||
}
|
||||
}
|
||||
else if (caretPosition < 6)
|
||||
{
|
||||
int newValue = Integer.parseInt(splitTime[1]) + 1;
|
||||
if (newValue < 10)
|
||||
{
|
||||
splitTime[1] = "0" + Integer.toString(newValue);
|
||||
}
|
||||
else if (newValue < 60)
|
||||
{
|
||||
splitTime[1] = Integer.toString(newValue);
|
||||
}
|
||||
}
|
||||
else if (caretPosition < 9)
|
||||
{
|
||||
int newValue = Integer.parseInt(splitTime[2]) + 1;
|
||||
if (newValue < 10)
|
||||
{
|
||||
splitTime[2] = "0" + Integer.toString(newValue);
|
||||
}
|
||||
else if (newValue < 60)
|
||||
{
|
||||
splitTime[2] = Integer.toString(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
timeField.setText(splitTime[0] + ":" + splitTime[1] + ":" + splitTime[2]);
|
||||
timeField.setCaretPosition(caretPosition);
|
||||
}
|
||||
|
||||
private void decreaseTime(int caretPosition)
|
||||
{
|
||||
String currentTime = timeField.getText().toString();
|
||||
String[] splitTime = currentTime.split(":");
|
||||
if (caretPosition < 2)
|
||||
{
|
||||
int newValue = Integer.parseInt(splitTime[0]) - 1;
|
||||
if (newValue < 10)
|
||||
{
|
||||
splitTime[0] = "0" + Integer.toString(newValue);
|
||||
}
|
||||
else if (newValue > 0)
|
||||
{
|
||||
splitTime[0] = Integer.toString(newValue);
|
||||
}
|
||||
}
|
||||
else if (caretPosition < 6)
|
||||
{
|
||||
int newValue = Integer.parseInt(splitTime[1]) - 1;
|
||||
if (newValue < 10)
|
||||
{
|
||||
splitTime[1] = "0" + Integer.toString(newValue);
|
||||
}
|
||||
else if (newValue > 0)
|
||||
{
|
||||
splitTime[1] = Integer.toString(newValue);
|
||||
}
|
||||
}
|
||||
else if (caretPosition < 9)
|
||||
{
|
||||
int newValue = Integer.parseInt(splitTime[2]) - 1;
|
||||
if (newValue < 10)
|
||||
{
|
||||
splitTime[2] = "0" + Integer.toString(newValue);
|
||||
}
|
||||
else if (newValue > 0)
|
||||
{
|
||||
splitTime[2] = Integer.toString(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
timeField.setText(splitTime[0] + ":" + splitTime[1] + ":" + splitTime[2]);
|
||||
timeField.setCaretPosition(caretPosition);
|
||||
}
|
||||
|
||||
private void setTimeToModel()
|
||||
{
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
stateModel.setState1time(timeField.getText().toString());
|
||||
break;
|
||||
case Save1:
|
||||
stateModel.setState2time(timeField.getText().toString());
|
||||
break;
|
||||
case Save2:
|
||||
stateModel.setState3time(timeField.getText().toString());
|
||||
break;
|
||||
case Save3:
|
||||
stateModel.setState4time(timeField.getText().toString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private JButton getRunButton()
|
||||
{
|
||||
if (runButton == null)
|
||||
{
|
||||
runButton = new JButton("Run");
|
||||
runButton.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
model.runSnapshotInVice(saveState);
|
||||
}
|
||||
});
|
||||
}
|
||||
return runButton;
|
||||
}
|
||||
|
||||
private JSeparator getSeparator()
|
||||
{
|
||||
if (separator == null)
|
||||
{
|
||||
separator = new JSeparator();
|
||||
}
|
||||
return separator;
|
||||
}
|
||||
|
||||
private JButton getScreenshotButton()
|
||||
{
|
||||
if (screenshotButton == null)
|
||||
{
|
||||
screenshotButton = new JButton("...");
|
||||
screenshotButton.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
selectScreenshotFile();
|
||||
}
|
||||
});
|
||||
screenshotButton.setMargin(new Insets(1, 3, 1, 3));
|
||||
}
|
||||
return screenshotButton;
|
||||
}
|
||||
|
||||
private void selectScreenshotFile()
|
||||
{
|
||||
final JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Select screenshot for " + model.getInfoModel().getTitle() + " snapshot");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
String screensDir = FileManager.getConfiguredProperties().getProperty(SNAPSHOT_DIR_PROPERTY);
|
||||
if (screensDir == null)
|
||||
{
|
||||
screensDir = ".";
|
||||
}
|
||||
fileChooser.setCurrentDirectory(new File(screensDir));
|
||||
fileChooser.addChoosableFileFilter(imagefilter);
|
||||
fileChooser.setFileFilter(imagefilter);
|
||||
int value = fileChooser.showOpenDialog(MainWindow.getInstance());
|
||||
if (value == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
File selectedFile = fileChooser.getSelectedFile();
|
||||
FileManager.getConfiguredProperties().put(SNAPSHOT_DIR_PROPERTY, selectedFile.toPath().getParent().toString());
|
||||
setScreenshotFileToModel(new File[] { selectedFile });
|
||||
}
|
||||
}
|
||||
|
||||
private void setScreenshotFileToModel(File[] files)
|
||||
{
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
stateModel.setState1PngImage(handleScreenFileDrop(files, getScreenshotLabel()));
|
||||
break;
|
||||
case Save1:
|
||||
stateModel.setState2PngImage(handleScreenFileDrop(files, getScreenshotLabel()));
|
||||
break;
|
||||
case Save2:
|
||||
stateModel.setState3PngImage(handleScreenFileDrop(files, getScreenshotLabel()));
|
||||
break;
|
||||
case Save3:
|
||||
stateModel.setState4PngImage(handleScreenFileDrop(files, getScreenshotLabel()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage handleScreenFileDrop(File[] files, JLabel imageLabel)
|
||||
{
|
||||
BufferedImage returnImage = null;
|
||||
if (files.length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
returnImage = ImageIO.read(files[0]);
|
||||
Image newImage = returnImage.getScaledInstance(130, 82, Image.SCALE_SMOOTH);
|
||||
imageLabel.setIcon(new ImageIcon(newImage));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("can't read file: " + files[0].getName(), e);
|
||||
imageLabel.setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
}
|
||||
return returnImage;
|
||||
}
|
||||
|
||||
void commitEdits()
|
||||
{
|
||||
try
|
||||
{
|
||||
timeField.commitEdit();
|
||||
}
|
||||
catch (ParseException e1)
|
||||
{
|
||||
ExceptionHandler.handleException(e1, "");
|
||||
}
|
||||
setTimeToModel();
|
||||
}
|
||||
}
|
|
@ -30,9 +30,11 @@ import se.lantz.util.FileManager;
|
|||
|
||||
public class SelectDirPanel extends JPanel
|
||||
{
|
||||
private static final String THEC64SAVE = ".THEC64SAVE";
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
CAROUSEL_IMPORT, GB_IMPORT, CAROUSEL_EXPORT, FILELOADER_EXPORT
|
||||
CAROUSEL_IMPORT, GB_IMPORT, CAROUSEL_EXPORT, FILELOADER_EXPORT, SAVEDSTATES_IMPORT, SAVEDSTATES_EXPORT
|
||||
}
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SelectDirPanel.class);
|
||||
|
@ -40,6 +42,8 @@ public class SelectDirPanel extends JPanel
|
|||
private static final String GB_IMPORT_DIR_PROPERTY = "gbImportDir";
|
||||
private static final String CAROUSEL_EXPORT_DIR_PROPERTY = "exportDir";
|
||||
private static final String FILELOADER_EXPORT_DIR_PROPERTY = "flexportDir";
|
||||
private static final String SAVEDSTATES_IMPORT_DIR_PROPERTY = "savedStatesImportDir";
|
||||
private static final String SAVEDSTATES_EXPORT_DIR_PROPERTY = "savedStatesExportDir";
|
||||
private JTextField dirTextField;
|
||||
private JButton selectDirButton;
|
||||
|
||||
|
@ -101,6 +105,20 @@ public class SelectDirPanel extends JPanel
|
|||
configuredDir = new File("export").getAbsolutePath();
|
||||
}
|
||||
break;
|
||||
case SAVEDSTATES_IMPORT:
|
||||
configuredDir = FileManager.getConfiguredProperties().getProperty(SAVEDSTATES_IMPORT_DIR_PROPERTY);
|
||||
if (configuredDir == null)
|
||||
{
|
||||
configuredDir = new File(".").getAbsolutePath();
|
||||
}
|
||||
break;
|
||||
case SAVEDSTATES_EXPORT:
|
||||
configuredDir = FileManager.getConfiguredProperties().getProperty(SAVEDSTATES_EXPORT_DIR_PROPERTY);
|
||||
if (configuredDir == null)
|
||||
{
|
||||
configuredDir = new File(".").getAbsolutePath();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -143,6 +161,12 @@ public class SelectDirPanel extends JPanel
|
|||
case FILELOADER_EXPORT:
|
||||
selectExportDirectory(false);
|
||||
break;
|
||||
case SAVEDSTATES_IMPORT:
|
||||
selectSavedStatesImportDirectory();
|
||||
break;
|
||||
case SAVEDSTATES_EXPORT:
|
||||
selectSavedStatesExportDirectory();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -197,7 +221,7 @@ public class SelectDirPanel extends JPanel
|
|||
configuredDir = targetDirectory.toPath().toString();
|
||||
FileManager.getConfiguredProperties().put(GB_IMPORT_DIR_PROPERTY, configuredDir);
|
||||
getDirTextField().setText(configuredDir);
|
||||
gbDbFileSelectedlistener.actionPerformed(new ActionEvent(this,0,""));
|
||||
gbDbFileSelectedlistener.actionPerformed(new ActionEvent(this, 0, ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -251,6 +275,75 @@ public class SelectDirPanel extends JPanel
|
|||
}
|
||||
}
|
||||
|
||||
private void selectSavedStatesImportDirectory()
|
||||
{
|
||||
final JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Select the \"" + THEC64SAVE + "\" directory to import from");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
fileChooser.setCurrentDirectory(new File(configuredDir));
|
||||
int value = fileChooser.showDialog(this, "OK");
|
||||
if (value == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
targetDirectory = fileChooser.getSelectedFile();
|
||||
if (!targetDirectory.getName().toUpperCase().equals(THEC64SAVE))
|
||||
{
|
||||
String message = "<html>You have not selected a \"" + THEC64SAVE +
|
||||
"\" directory.<br> Are you sure you want to import from the selected directory?</html>";
|
||||
int choice = JOptionPane.showConfirmDialog(SwingUtilities.getAncestorOfClass(JDialog.class, this),
|
||||
message,
|
||||
"Folder name",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
if (choice == JOptionPane.NO_OPTION)
|
||||
{
|
||||
selectSavedStatesImportDirectory();
|
||||
}
|
||||
}
|
||||
configuredDir = targetDirectory.toPath().toString();
|
||||
FileManager.getConfiguredProperties().put(SAVEDSTATES_IMPORT_DIR_PROPERTY, configuredDir);
|
||||
getDirTextField().setText(configuredDir);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectSavedStatesExportDirectory()
|
||||
{
|
||||
final JFileChooser fileChooser = new JFileChooser()
|
||||
{
|
||||
@Override
|
||||
protected JDialog createDialog(Component parent) throws HeadlessException
|
||||
{
|
||||
//Set parent to the export dialog
|
||||
JDialog dlg = super.createDialog(SwingUtilities.getAncestorOfClass(JDialog.class, SelectDirPanel.this));
|
||||
return dlg;
|
||||
}
|
||||
};
|
||||
fileChooser.setDialogTitle("Select the \"" + THEC64SAVE + "\" directory on your PCUAE USB stick");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
fileChooser.setCurrentDirectory(new File(configuredDir));
|
||||
int value = fileChooser.showDialog(this, "OK");
|
||||
if (value == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
targetDirectory = fileChooser.getSelectedFile();
|
||||
if (!targetDirectory.getName().toUpperCase().equals(THEC64SAVE))
|
||||
{
|
||||
String message = "<html>You have not selected a \"" + THEC64SAVE +
|
||||
"\" directory.<br> Are you sure you want to export to the selected directory?</html>";
|
||||
int choice = JOptionPane.showConfirmDialog(SwingUtilities.getAncestorOfClass(JDialog.class, this),
|
||||
message,
|
||||
"Folder name",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
if (choice == JOptionPane.NO_OPTION)
|
||||
{
|
||||
selectSavedStatesExportDirectory();
|
||||
}
|
||||
}
|
||||
configuredDir = targetDirectory.toPath().toString();
|
||||
FileManager.getConfiguredProperties().put(SAVEDSTATES_EXPORT_DIR_PROPERTY, configuredDir);
|
||||
getDirTextField().setText(configuredDir);
|
||||
}
|
||||
}
|
||||
|
||||
public File getTargetDirectory()
|
||||
{
|
||||
return targetDirectory;
|
||||
|
@ -309,10 +402,9 @@ public class SelectDirPanel extends JPanel
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void registerGBFileSelectedActionListener(ActionListener listener)
|
||||
{
|
||||
this.gbDbFileSelectedlistener = listener;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ public class BackupWorker extends SwingWorker<Void, String>
|
|||
publish("Backing up games directory...");
|
||||
backupManager.backupGames();
|
||||
publish("Done");
|
||||
publish("Backing up saves directory...");
|
||||
backupManager.backupSaves();
|
||||
publish("Done");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ public class RestoreDbPanel extends JPanel
|
|||
}
|
||||
private JLabel getInfoLabel() {
|
||||
if (infoLabel == null) {
|
||||
infoLabel = new JLabel("<html>Restoring a backup will overwrite the existing database and all covers, screens and game files. Custom views are also replaced.</html>");
|
||||
infoLabel = new JLabel("<html>Restoring a backup will overwrite the existing database and all covers, screens, games and saves files. Custom views are also replaced.</html>");
|
||||
infoLabel.setIcon(UIManager.getIcon("OptionPane.warningIcon"));
|
||||
}
|
||||
return infoLabel;
|
||||
|
|
|
@ -38,6 +38,9 @@ public class RestoreWorker extends SwingWorker<Void, String>
|
|||
publish("Restoring games directory...");
|
||||
restoreManager.restoreGames();
|
||||
publish("Done");
|
||||
publish("Restoring saves directory...");
|
||||
restoreManager.restoreSaves();
|
||||
publish("Done");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ public class ExportFileLoaderWorker extends SwingWorker<Void, String>
|
|||
{
|
||||
|
||||
private ExportManager exportManager;
|
||||
private ExportProgressDialog dialog;
|
||||
private ImportExportProgressDialog dialog;
|
||||
|
||||
public ExportFileLoaderWorker(ExportManager importManager, ExportProgressDialog dialog)
|
||||
public ExportFileLoaderWorker(ExportManager importManager, ImportExportProgressDialog dialog)
|
||||
{
|
||||
this.exportManager = importManager;
|
||||
this.dialog = dialog;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package se.lantz.gui.exports;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.io.File;
|
||||
|
||||
import se.lantz.gui.BaseDialog;
|
||||
|
||||
public class ExportSavedStatesDialog extends BaseDialog
|
||||
{
|
||||
ExportSavedStatesPanel panel;
|
||||
|
||||
public ExportSavedStatesDialog(Frame owner)
|
||||
{
|
||||
super(owner);
|
||||
addContent(getExportSavedStatesPanel());
|
||||
setTitle("Export saved states");
|
||||
this.setPreferredSize(new Dimension(435, 220));
|
||||
getOkButton().setText("Export");
|
||||
this.setResizable(false);
|
||||
}
|
||||
|
||||
private ExportSavedStatesPanel getExportSavedStatesPanel()
|
||||
{
|
||||
if (panel == null)
|
||||
{
|
||||
panel = new ExportSavedStatesPanel();
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
public File getTargetDirectory()
|
||||
{
|
||||
return getExportSavedStatesPanel().getTargetDirectory();
|
||||
}
|
||||
|
||||
public boolean isExportOverwrite()
|
||||
{
|
||||
return getExportSavedStatesPanel().isExportOverwrite();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
package se.lantz.gui.exports;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
|
||||
import se.lantz.gui.SelectDirPanel;
|
||||
import se.lantz.gui.SelectDirPanel.Mode;
|
||||
|
||||
public class ExportSavedStatesPanel extends JPanel
|
||||
{
|
||||
private JLabel infoLabel;
|
||||
private SelectDirPanel selectDirPanel;
|
||||
private JLabel choiceLabel;
|
||||
private JPanel choicePanel;
|
||||
private JRadioButton overwriteRadioButton;
|
||||
private JRadioButton keepRadioButton;
|
||||
private final ButtonGroup buttonGroup = new ButtonGroup();
|
||||
|
||||
public ExportSavedStatesPanel()
|
||||
{
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_infoLabel = new GridBagConstraints();
|
||||
gbc_infoLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_infoLabel.insets = new Insets(10, 10, 0, 0);
|
||||
gbc_infoLabel.gridx = 0;
|
||||
gbc_infoLabel.gridy = 0;
|
||||
add(getInfoLabel(), gbc_infoLabel);
|
||||
GridBagConstraints gbc_selectDirPanel = new GridBagConstraints();
|
||||
gbc_selectDirPanel.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_selectDirPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_selectDirPanel.gridx = 0;
|
||||
gbc_selectDirPanel.gridy = 1;
|
||||
add(getSelectDirPanel(), gbc_selectDirPanel);
|
||||
GridBagConstraints gbc_choiceLabel = new GridBagConstraints();
|
||||
gbc_choiceLabel.insets = new Insets(10, 0, 5, 0);
|
||||
gbc_choiceLabel.gridx = 0;
|
||||
gbc_choiceLabel.gridy = 2;
|
||||
add(getChoiceLabel(), gbc_choiceLabel);
|
||||
GridBagConstraints gbc_choicePanel = new GridBagConstraints();
|
||||
gbc_choicePanel.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_choicePanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_choicePanel.weighty = 1.0;
|
||||
gbc_choicePanel.weightx = 1.0;
|
||||
gbc_choicePanel.gridx = 0;
|
||||
gbc_choicePanel.gridy = 3;
|
||||
add(getChoicePanel(), gbc_choicePanel);
|
||||
}
|
||||
|
||||
private JLabel getInfoLabel()
|
||||
{
|
||||
if (infoLabel == null)
|
||||
{
|
||||
infoLabel = new JLabel("Select the \".THEC64SAVE\" folder in the root of your PCUAE USB stick:");
|
||||
}
|
||||
return infoLabel;
|
||||
}
|
||||
|
||||
private SelectDirPanel getSelectDirPanel()
|
||||
{
|
||||
if (selectDirPanel == null)
|
||||
{
|
||||
selectDirPanel = new SelectDirPanel(Mode.SAVEDSTATES_EXPORT);
|
||||
}
|
||||
return selectDirPanel;
|
||||
}
|
||||
|
||||
private JLabel getChoiceLabel()
|
||||
{
|
||||
if (choiceLabel == null)
|
||||
{
|
||||
choiceLabel = new JLabel("Select how to handle already available saved states in the export folder:");
|
||||
}
|
||||
return choiceLabel;
|
||||
}
|
||||
|
||||
private JPanel getChoicePanel()
|
||||
{
|
||||
if (choicePanel == null)
|
||||
{
|
||||
choicePanel = new JPanel();
|
||||
GridBagLayout gbl_choicePanel = new GridBagLayout();
|
||||
choicePanel.setLayout(gbl_choicePanel);
|
||||
GridBagConstraints gbc_overwriteRadioButton = new GridBagConstraints();
|
||||
gbc_overwriteRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_overwriteRadioButton.gridx = 0;
|
||||
gbc_overwriteRadioButton.gridy = 0;
|
||||
choicePanel.add(getOverwriteRadioButton(), gbc_overwriteRadioButton);
|
||||
GridBagConstraints gbc_keepRadioButton = new GridBagConstraints();
|
||||
gbc_keepRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_keepRadioButton.gridx = 0;
|
||||
gbc_keepRadioButton.gridy = 1;
|
||||
choicePanel.add(getKeepRadioButton(), gbc_keepRadioButton);
|
||||
}
|
||||
return choicePanel;
|
||||
}
|
||||
|
||||
private JRadioButton getOverwriteRadioButton()
|
||||
{
|
||||
if (overwriteRadioButton == null)
|
||||
{
|
||||
overwriteRadioButton = new JRadioButton("Overwrite");
|
||||
buttonGroup.add(overwriteRadioButton);
|
||||
overwriteRadioButton.setSelected(true);
|
||||
}
|
||||
return overwriteRadioButton;
|
||||
}
|
||||
|
||||
private JRadioButton getKeepRadioButton()
|
||||
{
|
||||
if (keepRadioButton == null)
|
||||
{
|
||||
keepRadioButton = new JRadioButton("Skip from export\r\n");
|
||||
buttonGroup.add(keepRadioButton);
|
||||
}
|
||||
return keepRadioButton;
|
||||
}
|
||||
|
||||
File getTargetDirectory()
|
||||
{
|
||||
return getSelectDirPanel().getTargetDirectory();
|
||||
}
|
||||
|
||||
boolean isExportOverwrite()
|
||||
{
|
||||
return getOverwriteRadioButton().isSelected();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package se.lantz.gui.exports;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import se.lantz.manager.SavedStatesManager;
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
|
||||
public class ExportSavedStatesWorker extends SwingWorker<Void, String>
|
||||
{
|
||||
|
||||
private SavedStatesManager savedStatesManager;
|
||||
private ImportExportProgressDialog dialog;
|
||||
|
||||
public ExportSavedStatesWorker(SavedStatesManager savedStatesManager, ImportExportProgressDialog dialog)
|
||||
{
|
||||
this.savedStatesManager = savedStatesManager;
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception
|
||||
{
|
||||
if (savedStatesManager.isExportOverwrite())
|
||||
{
|
||||
publish("Overwriting existing saved states in the export folder.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
publish("Skipping already existing saved states in the export folder.\n");
|
||||
}
|
||||
StringBuilder infoBuilder = new StringBuilder();
|
||||
savedStatesManager.exportSavedStates(infoBuilder);
|
||||
publish(infoBuilder.toString());
|
||||
publish("Copied " + savedStatesManager.getNumberOfFilesCopied() + " files.");
|
||||
publish("Done!");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(List<String> chunks)
|
||||
{
|
||||
for (String value : chunks)
|
||||
{
|
||||
dialog.updateProgress(value + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done()
|
||||
{
|
||||
try
|
||||
{
|
||||
get();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Error during export");
|
||||
}
|
||||
dialog.finish();
|
||||
}
|
||||
}
|
|
@ -11,9 +11,9 @@ public class ExportWorker extends SwingWorker<Void, String>
|
|||
{
|
||||
|
||||
private ExportManager exportManager;
|
||||
private ExportProgressDialog dialog;
|
||||
private ImportExportProgressDialog dialog;
|
||||
|
||||
public ExportWorker(ExportManager importManager, ExportProgressDialog dialog)
|
||||
public ExportWorker(ExportManager importManager, ImportExportProgressDialog dialog)
|
||||
{
|
||||
this.exportManager = importManager;
|
||||
this.dialog = dialog;
|
||||
|
|
|
@ -5,15 +5,18 @@ import java.awt.Frame;
|
|||
import javax.swing.JDialog;
|
||||
import javax.swing.WindowConstants;
|
||||
|
||||
public class ExportProgressDialog extends JDialog
|
||||
public class ImportExportProgressDialog extends JDialog
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ExportProgressPanel panel;
|
||||
private ImportExportProgressPanel panel;
|
||||
|
||||
public ExportProgressDialog(Frame frame)
|
||||
private final boolean isImport;
|
||||
|
||||
public ImportExportProgressDialog(Frame frame, String title, boolean isImport)
|
||||
{
|
||||
super(frame,"Export games", true);
|
||||
super(frame, title, true);
|
||||
this.isImport = isImport;
|
||||
this.add(getExportProgressPanel());
|
||||
setSize(900, 600);
|
||||
setLocationRelativeTo(frame);
|
||||
|
@ -28,14 +31,14 @@ public class ExportProgressDialog extends JDialog
|
|||
|
||||
public void finish()
|
||||
{
|
||||
getExportProgressPanel().finish();
|
||||
getExportProgressPanel().finish(isImport);
|
||||
}
|
||||
|
||||
public ExportProgressPanel getExportProgressPanel()
|
||||
public ImportExportProgressPanel getExportProgressPanel()
|
||||
{
|
||||
if (panel == null)
|
||||
{
|
||||
panel = new ExportProgressPanel();
|
||||
panel = new ImportExportProgressPanel();
|
||||
panel.getCloseButton().addActionListener(e -> setVisible(false));
|
||||
}
|
||||
return panel;
|
|
@ -10,14 +10,14 @@ import javax.swing.JProgressBar;
|
|||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
public class ExportProgressPanel extends JPanel
|
||||
public class ImportExportProgressPanel extends JPanel
|
||||
{
|
||||
private JProgressBar progressBar;
|
||||
private JTextArea textArea;
|
||||
private JScrollPane textScrollPane;
|
||||
private JButton closeButton;
|
||||
|
||||
public ExportProgressPanel()
|
||||
public ImportExportProgressPanel()
|
||||
{
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
|
@ -88,7 +88,7 @@ public class ExportProgressPanel extends JPanel
|
|||
getTextArea().append(infoText);
|
||||
}
|
||||
|
||||
public void finish()
|
||||
public void finish(boolean isImport)
|
||||
{
|
||||
getCloseButton().setEnabled(true);
|
||||
getProgressBar().setIndeterminate(false);
|
||||
|
@ -96,13 +96,21 @@ public class ExportProgressPanel extends JPanel
|
|||
//Check for errors
|
||||
String text = getTextArea().getText();
|
||||
int count = text.length() - text.replace("ERROR:", "").length();
|
||||
if (count > 0)
|
||||
if (isImport)
|
||||
{
|
||||
getTextArea().append("\nExport ended with " + count/6 + " errors. See pcusb.log for details.");
|
||||
getTextArea().append("\nImport ");
|
||||
}
|
||||
else
|
||||
{
|
||||
getTextArea().append("\nExport completed successfully.");
|
||||
getTextArea().append("\nExport ");
|
||||
}
|
||||
if (count > 0)
|
||||
{
|
||||
getTextArea().append("ended with " + count/6 + " errors. See pcusb.log for details.");
|
||||
}
|
||||
else
|
||||
{
|
||||
getTextArea().append("completed successfully.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,7 +70,6 @@ public class OutputDirPanel extends JPanel
|
|||
if (deleteCheckBox == null)
|
||||
{
|
||||
deleteCheckBox = new JCheckBox();
|
||||
deleteCheckBox.setSelected(true);
|
||||
updateDeleteCheckBoxText(true);
|
||||
}
|
||||
return deleteCheckBox;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.io.File;
|
||||
|
||||
import se.lantz.gui.BaseDialog;
|
||||
|
||||
public class ImportSavedStatesDialog extends BaseDialog
|
||||
{
|
||||
ImportSavedStatesPanel panel;
|
||||
|
||||
public ImportSavedStatesDialog(Frame owner)
|
||||
{
|
||||
super(owner);
|
||||
addContent(getImportSavedStatesPanel());
|
||||
setTitle("Import saved states");
|
||||
this.setPreferredSize(new Dimension(435, 280));
|
||||
getOkButton().setText("Import");
|
||||
this.setResizable(false);
|
||||
}
|
||||
|
||||
private ImportSavedStatesPanel getImportSavedStatesPanel()
|
||||
{
|
||||
if (panel == null)
|
||||
{
|
||||
panel = new ImportSavedStatesPanel();
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
public File getTargetDirectory()
|
||||
{
|
||||
return getImportSavedStatesPanel().getTargetDirectory();
|
||||
}
|
||||
|
||||
public boolean isImportOverwrite()
|
||||
{
|
||||
return getImportSavedStatesPanel().isImportOverwrite();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
|
||||
import se.lantz.gui.SelectDirPanel;
|
||||
import se.lantz.gui.SelectDirPanel.Mode;
|
||||
|
||||
public class ImportSavedStatesPanel extends JPanel
|
||||
{
|
||||
private JLabel infoLabel;
|
||||
private SelectDirPanel selectDirPanel;
|
||||
private JLabel choiceLabel;
|
||||
private JPanel choicePanel;
|
||||
private JRadioButton overwriteRadioButton;
|
||||
private JRadioButton keepRadioButton;
|
||||
private JLabel info2Label;
|
||||
private final ButtonGroup buttonGroup = new ButtonGroup();
|
||||
|
||||
public ImportSavedStatesPanel()
|
||||
{
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_infoLabel = new GridBagConstraints();
|
||||
gbc_infoLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_infoLabel.insets = new Insets(10, 10, 0, 0);
|
||||
gbc_infoLabel.gridx = 0;
|
||||
gbc_infoLabel.gridy = 0;
|
||||
add(getInfoLabel(), gbc_infoLabel);
|
||||
GridBagConstraints gbc_selectDirPanel = new GridBagConstraints();
|
||||
gbc_selectDirPanel.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_selectDirPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_selectDirPanel.gridx = 0;
|
||||
gbc_selectDirPanel.gridy = 1;
|
||||
add(getSelectDirPanel(), gbc_selectDirPanel);
|
||||
GridBagConstraints gbc_choiceLabel = new GridBagConstraints();
|
||||
gbc_choiceLabel.insets = new Insets(10, 0, 5, 0);
|
||||
gbc_choiceLabel.gridx = 0;
|
||||
gbc_choiceLabel.gridy = 2;
|
||||
add(getChoiceLabel(), gbc_choiceLabel);
|
||||
GridBagConstraints gbc_choicePanel = new GridBagConstraints();
|
||||
gbc_choicePanel.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_choicePanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_choicePanel.weighty = 1.0;
|
||||
gbc_choicePanel.weightx = 1.0;
|
||||
gbc_choicePanel.gridx = 0;
|
||||
gbc_choicePanel.gridy = 3;
|
||||
add(getChoicePanel(), gbc_choicePanel);
|
||||
GridBagConstraints gbc_info2Label = new GridBagConstraints();
|
||||
gbc_info2Label.insets = new Insets(0, 10, 20, 10);
|
||||
gbc_info2Label.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_info2Label.gridx = 0;
|
||||
gbc_info2Label.gridy = 4;
|
||||
add(getInfo2Label(), gbc_info2Label);
|
||||
}
|
||||
|
||||
private JLabel getInfoLabel()
|
||||
{
|
||||
if (infoLabel == null)
|
||||
{
|
||||
infoLabel = new JLabel("Select the \".THEC64SAVE\" folder in the root of your PCUAE USB stick:");
|
||||
}
|
||||
return infoLabel;
|
||||
}
|
||||
|
||||
private SelectDirPanel getSelectDirPanel()
|
||||
{
|
||||
if (selectDirPanel == null)
|
||||
{
|
||||
selectDirPanel = new SelectDirPanel(Mode.SAVEDSTATES_IMPORT);
|
||||
}
|
||||
return selectDirPanel;
|
||||
}
|
||||
|
||||
private JLabel getChoiceLabel()
|
||||
{
|
||||
if (choiceLabel == null)
|
||||
{
|
||||
choiceLabel = new JLabel("Select how to handle already available saved states in the \"saves\" folder:");
|
||||
}
|
||||
return choiceLabel;
|
||||
}
|
||||
|
||||
private JPanel getChoicePanel()
|
||||
{
|
||||
if (choicePanel == null)
|
||||
{
|
||||
choicePanel = new JPanel();
|
||||
GridBagLayout gbl_choicePanel = new GridBagLayout();
|
||||
choicePanel.setLayout(gbl_choicePanel);
|
||||
GridBagConstraints gbc_overwriteRadioButton = new GridBagConstraints();
|
||||
gbc_overwriteRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_overwriteRadioButton.gridx = 0;
|
||||
gbc_overwriteRadioButton.gridy = 0;
|
||||
choicePanel.add(getOverwriteRadioButton(), gbc_overwriteRadioButton);
|
||||
GridBagConstraints gbc_keepRadioButton = new GridBagConstraints();
|
||||
gbc_keepRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_keepRadioButton.gridx = 0;
|
||||
gbc_keepRadioButton.gridy = 1;
|
||||
choicePanel.add(getKeepRadioButton(), gbc_keepRadioButton);
|
||||
}
|
||||
return choicePanel;
|
||||
}
|
||||
|
||||
private JRadioButton getOverwriteRadioButton()
|
||||
{
|
||||
if (overwriteRadioButton == null)
|
||||
{
|
||||
overwriteRadioButton = new JRadioButton("Overwrite");
|
||||
buttonGroup.add(overwriteRadioButton);
|
||||
overwriteRadioButton.setSelected(true);
|
||||
}
|
||||
return overwriteRadioButton;
|
||||
}
|
||||
|
||||
private JRadioButton getKeepRadioButton()
|
||||
{
|
||||
if (keepRadioButton == null)
|
||||
{
|
||||
keepRadioButton = new JRadioButton("Skip from import");
|
||||
buttonGroup.add(keepRadioButton);
|
||||
}
|
||||
return keepRadioButton;
|
||||
}
|
||||
|
||||
private JLabel getInfo2Label()
|
||||
{
|
||||
if (info2Label == null)
|
||||
{
|
||||
info2Label =
|
||||
new JLabel("<html>Saved states available in the import folder that doesn't match any games in the database will still be copied to the game manager's \"saves\" folder. They will also be copied when exporting.</html>");
|
||||
}
|
||||
return info2Label;
|
||||
}
|
||||
|
||||
File getTargetDirectory()
|
||||
{
|
||||
return getSelectDirPanel().getTargetDirectory();
|
||||
}
|
||||
|
||||
boolean isImportOverwrite()
|
||||
{
|
||||
return getOverwriteRadioButton().isSelected();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import se.lantz.gui.exports.ImportExportProgressDialog;
|
||||
import se.lantz.manager.SavedStatesManager;
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
|
||||
public class ImportSavedStatesWorker extends SwingWorker<Void, String>
|
||||
{
|
||||
|
||||
private SavedStatesManager savedStatesManager;
|
||||
private ImportExportProgressDialog dialog;
|
||||
|
||||
public ImportSavedStatesWorker(SavedStatesManager savedStatesManager, ImportExportProgressDialog dialog)
|
||||
{
|
||||
this.savedStatesManager = savedStatesManager;
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception
|
||||
{
|
||||
if (savedStatesManager.isImportOverwrite())
|
||||
{
|
||||
publish("Overwriting existing saved states in the saves folder.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
publish("Skipping already existing saved states in the saves folder.\n");
|
||||
}
|
||||
StringBuilder infoBuilder = new StringBuilder();
|
||||
savedStatesManager.importSavedStates(infoBuilder);
|
||||
publish(infoBuilder.toString());
|
||||
publish("Copied " + savedStatesManager.getNumberOfFilesCopied() + " files.");
|
||||
publish("Done!");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(List<String> chunks)
|
||||
{
|
||||
for (String value : chunks)
|
||||
{
|
||||
dialog.updateProgress(value + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done()
|
||||
{
|
||||
try
|
||||
{
|
||||
get();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Error during import");
|
||||
}
|
||||
dialog.finish();
|
||||
}
|
||||
}
|
|
@ -49,4 +49,9 @@ public class BackupManager
|
|||
{
|
||||
FileManager.backupGames(currentFolderName);
|
||||
}
|
||||
|
||||
public void backupSaves()
|
||||
{
|
||||
FileManager.backupSaves(currentFolderName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,4 +44,9 @@ public class RestoreManager
|
|||
{
|
||||
FileManager.restoreGames(currentFolderName);
|
||||
}
|
||||
|
||||
public void restoreSaves()
|
||||
{
|
||||
FileManager.restoreSaves(currentFolderName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,406 @@
|
|||
package se.lantz.manager;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.SavedStatesModel;
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
import se.lantz.util.FileManager;
|
||||
|
||||
public class SavedStatesManager
|
||||
{
|
||||
public static final String SAVES = "./saves/";
|
||||
|
||||
private static final String MTA0 = "0.mta";
|
||||
private static final String MTA1 = "1.mta";
|
||||
private static final String MTA2 = "2.mta";
|
||||
private static final String MTA3 = "3.mta";
|
||||
|
||||
private static final String PNG0 = "0.png";
|
||||
private static final String PNG1 = "1.png";
|
||||
private static final String PNG2 = "2.png";
|
||||
private static final String PNG3 = "3.png";
|
||||
|
||||
public static final String VSZ0 = "0.vsz";
|
||||
public static final String VSZ1 = "1.vsz";
|
||||
public static final String VSZ2 = "2.vsz";
|
||||
public static final String VSZ3 = "3.vsz";
|
||||
|
||||
private SavedStatesModel savedStatesModel;
|
||||
private MainViewModel model;
|
||||
|
||||
private File exportDir;
|
||||
private File importDir;
|
||||
|
||||
private boolean exportOverwrite;
|
||||
private boolean importOverwrite;
|
||||
|
||||
private int noFilesCopied = 0;
|
||||
|
||||
public SavedStatesManager(MainViewModel model)
|
||||
{
|
||||
this.model = model;
|
||||
this.savedStatesModel = model.getSavedStatesModel();
|
||||
}
|
||||
|
||||
public void saveSavedStates()
|
||||
{
|
||||
//If the game has been renamed, make sure to rename the saves folder also
|
||||
if (model.getInfoModel().isTitleChanged())
|
||||
{
|
||||
String oldFileName = model.getInfoModel().getOldGamesFile();
|
||||
File oldSaveFolder = new File(SAVES + oldFileName);
|
||||
if (oldSaveFolder.exists())
|
||||
{
|
||||
//Rename old folder to new name
|
||||
oldSaveFolder.renameTo(new File(SAVES + model.getInfoModel().getGamesFile()));
|
||||
}
|
||||
}
|
||||
|
||||
String fileName = model.getInfoModel().getGamesFile();
|
||||
Path saveFolder = new File(SAVES + fileName).toPath();
|
||||
//Check which ones are available
|
||||
Path mta0Path = saveFolder.resolve(MTA0);
|
||||
Path vsz0Path = saveFolder.resolve(VSZ0);
|
||||
Path png0Path = saveFolder.resolve(PNG0);
|
||||
if (Files.exists(mta0Path) || savedStatesModel.getState1Path() != null)
|
||||
{
|
||||
storePlayTime(mta0Path, savedStatesModel.getState1time());
|
||||
copyVsfFile(vsz0Path, savedStatesModel.getState1Path());
|
||||
copyPngFile(png0Path, savedStatesModel.getState1PngImage());
|
||||
}
|
||||
Path mta1Path = saveFolder.resolve(MTA1);
|
||||
Path vsz1Path = saveFolder.resolve(VSZ1);
|
||||
Path png1Path = saveFolder.resolve(PNG1);
|
||||
if (Files.exists(mta1Path) || savedStatesModel.getState2Path() != null)
|
||||
{
|
||||
storePlayTime(mta1Path, savedStatesModel.getState2time());
|
||||
copyVsfFile(vsz1Path, savedStatesModel.getState2Path());
|
||||
copyPngFile(png1Path, savedStatesModel.getState2PngImage());
|
||||
}
|
||||
Path mta2Path = saveFolder.resolve(MTA2);
|
||||
Path vsz2Path = saveFolder.resolve(VSZ2);
|
||||
Path png2Path = saveFolder.resolve(PNG2);
|
||||
if (Files.exists(mta2Path) || savedStatesModel.getState3Path() != null)
|
||||
{
|
||||
storePlayTime(mta2Path, savedStatesModel.getState3time());
|
||||
copyVsfFile(vsz2Path, savedStatesModel.getState3Path());
|
||||
copyPngFile(png2Path, savedStatesModel.getState3PngImage());
|
||||
}
|
||||
Path mta3Path = saveFolder.resolve(MTA3);
|
||||
Path vsz3Path = saveFolder.resolve(VSZ3);
|
||||
Path png3Path = saveFolder.resolve(PNG3);
|
||||
if (Files.exists(mta3Path) || savedStatesModel.getState4Path() != null)
|
||||
{
|
||||
storePlayTime(mta3Path, savedStatesModel.getState4time());
|
||||
copyVsfFile(vsz3Path, savedStatesModel.getState4Path());
|
||||
copyPngFile(png3Path, savedStatesModel.getState4PngImage());
|
||||
}
|
||||
}
|
||||
|
||||
public void readSavedStates()
|
||||
{
|
||||
savedStatesModel.resetProperties();
|
||||
//Read from state directory, update model
|
||||
String fileName = model.getInfoModel().getGamesFile();
|
||||
System.out.println(fileName.toString());
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
//Check if folder is available
|
||||
Path saveFolder = new File(SAVES + fileName).toPath();
|
||||
if (Files.exists(saveFolder))
|
||||
{
|
||||
//Check which ones are available
|
||||
Path mta0Path = saveFolder.resolve(MTA0);
|
||||
if (Files.exists(mta0Path))
|
||||
{
|
||||
//Update model
|
||||
savedStatesModel.setState1File(saveFolder.resolve(VSZ0).toFile().getName());
|
||||
savedStatesModel.setState1PngFile(saveFolder.resolve(PNG0).toFile().getName());
|
||||
savedStatesModel.setState1time(readPlayTime(mta0Path));
|
||||
}
|
||||
Path mta1Path = saveFolder.resolve(MTA1);
|
||||
if (Files.exists(mta1Path))
|
||||
{
|
||||
//Update model
|
||||
savedStatesModel.setState2File(saveFolder.resolve(VSZ1).toFile().getName());
|
||||
savedStatesModel.setState2PngFile(saveFolder.resolve(PNG1).toFile().getName());
|
||||
savedStatesModel.setState2time(readPlayTime(mta1Path));
|
||||
}
|
||||
Path mta2Path = saveFolder.resolve(MTA2);
|
||||
if (Files.exists(mta2Path))
|
||||
{
|
||||
//Update model
|
||||
savedStatesModel.setState3File(saveFolder.resolve(VSZ2).toFile().getName());
|
||||
savedStatesModel.setState3PngFile(saveFolder.resolve(PNG2).toFile().getName());
|
||||
savedStatesModel.setState3time(readPlayTime(mta2Path));
|
||||
}
|
||||
Path mta3Path = saveFolder.resolve(MTA3);
|
||||
if (Files.exists(mta3Path))
|
||||
{
|
||||
//Update model
|
||||
savedStatesModel.setState4File(saveFolder.resolve(VSZ3).toFile().getName());
|
||||
savedStatesModel.setState4PngFile(saveFolder.resolve(PNG3).toFile().getName());
|
||||
savedStatesModel.setState4time(readPlayTime(mta3Path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String readPlayTime(Path mtaFilePath)
|
||||
{
|
||||
String returnValue = "";
|
||||
try
|
||||
{
|
||||
byte[] fileContent = Files.readAllBytes(mtaFilePath);
|
||||
|
||||
//First 4 bytes represents play time
|
||||
byte[] timeArray = new byte[] { fileContent[0], fileContent[1], fileContent[2], fileContent[3] };
|
||||
//The value seems to be in milliseconds
|
||||
int milliSeconds = ByteBuffer.wrap(timeArray).order(java.nio.ByteOrder.LITTLE_ENDIAN).getInt();
|
||||
System.out.println("24 bit value Little endian x= " + milliSeconds);
|
||||
returnValue = convertSecondToHHMMString(milliSeconds);// LocalTime.MIN.plusSeconds(seconds).toString();
|
||||
System.out.println("Converted string = " + returnValue);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not read play time from " + mtaFilePath);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private void storePlayTime(Path mtaFilePath, String playTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!mtaFilePath.toFile().exists())
|
||||
{
|
||||
FileUtils.copyInputStreamToFile(getClass().getResourceAsStream("/se/lantz/template.mta"), mtaFilePath.toFile());
|
||||
}
|
||||
|
||||
String[] timeparts = playTime.split(":");
|
||||
int millis =
|
||||
(Integer.parseInt(timeparts[0]) * 3600 + Integer.parseInt(timeparts[1]) * 60 + Integer.parseInt(timeparts[2])) *
|
||||
1000;
|
||||
byte[] fileContent = Files.readAllBytes(mtaFilePath);
|
||||
//Replace the first 4 bytes with the correct values
|
||||
ByteBuffer b = ByteBuffer.allocate(4);
|
||||
b.order(ByteOrder.LITTLE_ENDIAN);
|
||||
b.putInt(millis);
|
||||
byte[] result = b.array();
|
||||
fileContent[0] = result[0];
|
||||
fileContent[1] = result[1];
|
||||
fileContent[2] = result[2];
|
||||
fileContent[3] = result[3];
|
||||
|
||||
Files.write(mtaFilePath, fileContent);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not write play time to " + mtaFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
private String convertSecondToHHMMString(int secondtTime)
|
||||
{
|
||||
TimeZone tz = TimeZone.getTimeZone("UTC");
|
||||
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
|
||||
df.setTimeZone(tz);
|
||||
String time = df.format(new Date(secondtTime));
|
||||
return time;
|
||||
}
|
||||
|
||||
private void copyVsfFile(Path target, Path source)
|
||||
{
|
||||
if (source != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileManager.compressGzip(source, target);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not compress vsf file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyPngFile(Path target, BufferedImage image)
|
||||
{
|
||||
if (image != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ImageIO.write(image, "png", target.toFile());
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
ExceptionHandler.logException(e1, "Could not store screenshot");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setExportDirectory(File exportDir)
|
||||
{
|
||||
this.exportDir = exportDir;
|
||||
}
|
||||
|
||||
public void setExportOverwrite(boolean exportOverwrite)
|
||||
{
|
||||
this.exportOverwrite = exportOverwrite;
|
||||
}
|
||||
|
||||
public boolean isExportOverwrite()
|
||||
{
|
||||
return this.exportOverwrite;
|
||||
}
|
||||
|
||||
public void setImportDirectory(File importDir)
|
||||
{
|
||||
this.importDir = importDir;
|
||||
}
|
||||
|
||||
public void setImportOverwrite(boolean importOverwrite)
|
||||
{
|
||||
this.importOverwrite = importOverwrite;
|
||||
}
|
||||
|
||||
public boolean isImportOverwrite()
|
||||
{
|
||||
return this.importOverwrite;
|
||||
}
|
||||
|
||||
public void exportSavedStates(StringBuilder infoBuilder)
|
||||
{
|
||||
noFilesCopied = 0;
|
||||
File saveFolder = new File(SAVES);
|
||||
try (Stream<Path> stream = Files.walk(saveFolder.toPath().toAbsolutePath()))
|
||||
{
|
||||
stream.forEachOrdered(sourcePath -> {
|
||||
try
|
||||
{
|
||||
//Ignore first folder
|
||||
if (sourcePath.equals(saveFolder.toPath().toAbsolutePath()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!isValidSaveStatePath(sourcePath))
|
||||
{
|
||||
infoBuilder.append("Skipping " + sourcePath + " (not a valid save state file)\n");
|
||||
return;
|
||||
}
|
||||
Path destinationPath =
|
||||
exportDir.toPath().resolve(saveFolder.toPath().toAbsolutePath().relativize(sourcePath));
|
||||
//Ignore already existing directories: Files.copy() throws DirectoryNotEmptyException for them
|
||||
if (destinationPath.toFile().exists() && destinationPath.toFile().isDirectory())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!this.exportOverwrite && destinationPath.toFile().exists())
|
||||
{
|
||||
infoBuilder.append("Skipping " + sourcePath + " (already exists)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBuilder.append("Copying " + sourcePath + "\n");
|
||||
Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
if (!sourcePath.toFile().isDirectory())
|
||||
{
|
||||
noFilesCopied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
infoBuilder.append("Could not copy from " + sourcePath.toString() + "\n");
|
||||
ExceptionHandler.logException(e, "Could not copy from " + sourcePath.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
ExceptionHandler.handleException(e1, "Could not export saved states folder.");
|
||||
}
|
||||
}
|
||||
|
||||
public void importSavedStates(StringBuilder infoBuilder)
|
||||
{
|
||||
noFilesCopied = 0;
|
||||
File saveFolder = new File(SAVES);
|
||||
try (Stream<Path> stream = Files.walk(importDir.toPath().toAbsolutePath()))
|
||||
{
|
||||
stream.forEachOrdered(sourcePath -> {
|
||||
try
|
||||
{
|
||||
//Ignore first folder or any files that are not save state files
|
||||
if (sourcePath.equals(importDir.toPath().toAbsolutePath()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!isValidSaveStatePath(sourcePath))
|
||||
{
|
||||
infoBuilder.append("Skipping " + sourcePath + " (not a valid save state file)\n");
|
||||
return;
|
||||
}
|
||||
Path destinationPath =
|
||||
saveFolder.toPath().resolve(importDir.toPath().toAbsolutePath().relativize(sourcePath));
|
||||
//Ignore already existing directories: Files.copy() throws DirectoryNotEmptyException for them
|
||||
if (destinationPath.toFile().exists() && destinationPath.toFile().isDirectory())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!this.importOverwrite && destinationPath.toFile().exists())
|
||||
{
|
||||
infoBuilder.append("Skipping " + sourcePath + " (already exists)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBuilder.append("Copying " + sourcePath + "\n");
|
||||
Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
if (!sourcePath.toFile().isDirectory())
|
||||
{
|
||||
noFilesCopied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
infoBuilder.append("Could not copy from " + sourcePath.toString() + "\n");
|
||||
ExceptionHandler.logException(e, "Could not copy from " + sourcePath.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
ExceptionHandler.handleException(e1, "Could not import to saved folder.");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidSaveStatePath(Path path)
|
||||
{
|
||||
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.{mta,png,vsz}");
|
||||
return matcher.matches(path) || path.toFile().isDirectory();
|
||||
}
|
||||
|
||||
public int getNumberOfFilesCopied()
|
||||
{
|
||||
return noFilesCopied;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import se.lantz.db.DbConnector;
|
||||
import se.lantz.manager.ImportManager;
|
||||
import se.lantz.manager.SavedStatesManager;
|
||||
import se.lantz.model.data.GameDetails;
|
||||
import se.lantz.model.data.GameListData;
|
||||
import se.lantz.model.data.GameView;
|
||||
|
@ -59,8 +60,10 @@ public class MainViewModel extends AbstractModel
|
|||
private JoystickModel joy1Model = new JoystickModel(true);
|
||||
private JoystickModel joy2Model = new JoystickModel(false);
|
||||
private SystemModel systemModel = new SystemModel();
|
||||
private SavedStatesModel stateModel = new SavedStatesModel();
|
||||
|
||||
private FileManager fileManager = new FileManager(this);
|
||||
private SavedStatesManager stateManager;
|
||||
|
||||
private String currentGameId = "";
|
||||
private GameDetails currentGameDetails = null;
|
||||
|
@ -69,6 +72,11 @@ public class MainViewModel extends AbstractModel
|
|||
private GameListData selectedData;
|
||||
|
||||
Scraper scraper = new MobyGamesScraper();
|
||||
|
||||
public void setSavedStatesManager(SavedStatesManager savedStatesManager)
|
||||
{
|
||||
this.stateManager = savedStatesManager;
|
||||
}
|
||||
|
||||
public void initialize()
|
||||
{
|
||||
|
@ -99,6 +107,7 @@ public class MainViewModel extends AbstractModel
|
|||
joy1Model.disableChangeNotification(disable);
|
||||
joy2Model.disableChangeNotification(disable);
|
||||
systemModel.disableChangeNotification(disable);
|
||||
stateModel.disableChangeNotification(disable);
|
||||
}
|
||||
|
||||
protected void notifyChangeForAllModels()
|
||||
|
@ -107,6 +116,7 @@ public class MainViewModel extends AbstractModel
|
|||
joy1Model.notifyChange();
|
||||
joy2Model.notifyChange();
|
||||
systemModel.notifyChange();
|
||||
stateModel.notifyChange();
|
||||
}
|
||||
|
||||
private void setupGameViews()
|
||||
|
@ -239,6 +249,9 @@ public class MainViewModel extends AbstractModel
|
|||
{
|
||||
infoModel.setTitle("");
|
||||
}
|
||||
//Read available saved states
|
||||
stateManager.readSavedStates();
|
||||
|
||||
disableChangeNotification(false);
|
||||
notifyChangeForAllModels();
|
||||
//Do not reset unsaved for new entry
|
||||
|
@ -304,6 +317,11 @@ public class MainViewModel extends AbstractModel
|
|||
{
|
||||
return systemModel;
|
||||
}
|
||||
|
||||
public SavedStatesModel getSavedStatesModel()
|
||||
{
|
||||
return stateModel;
|
||||
}
|
||||
|
||||
public void reloadCurrentGameView()
|
||||
{
|
||||
|
@ -421,6 +439,7 @@ public class MainViewModel extends AbstractModel
|
|||
getJoy1Model().addPropertyChangeListener(saveChangeListener);
|
||||
getJoy2Model().addPropertyChangeListener(saveChangeListener);
|
||||
getSystemModel().addPropertyChangeListener(saveChangeListener);
|
||||
getSavedStatesModel().addPropertyChangeListener(saveChangeListener);
|
||||
}
|
||||
|
||||
public void addRequireFieldsListener(PropertyChangeListener requiredFieldsListener)
|
||||
|
@ -432,7 +451,7 @@ public class MainViewModel extends AbstractModel
|
|||
public boolean isDataChanged()
|
||||
{
|
||||
return infoModel.isDataChanged() || joy1Model.isDataChanged() || joy2Model.isDataChanged() ||
|
||||
systemModel.isDataChanged();
|
||||
systemModel.isDataChanged() || stateModel.isDataChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -442,6 +461,7 @@ public class MainViewModel extends AbstractModel
|
|||
joy1Model.resetDataChanged();
|
||||
joy2Model.resetDataChanged();
|
||||
systemModel.resetDataChanged();
|
||||
stateModel.resetDataChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -451,6 +471,7 @@ public class MainViewModel extends AbstractModel
|
|||
joy1Model.resetDataChangedAfterInit();
|
||||
joy2Model.resetDataChangedAfterInit();
|
||||
systemModel.resetDataChangedAfterInit();
|
||||
stateModel.resetDataChangedAfterInit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -559,6 +580,8 @@ public class MainViewModel extends AbstractModel
|
|||
gameListModel.notifyChange();
|
||||
|
||||
fileManager.saveFiles();
|
||||
stateManager.saveSavedStates();
|
||||
|
||||
//Reset and images that where added previously
|
||||
infoModel.resetImagesAndOldFileNames();
|
||||
//Reset all models
|
||||
|
@ -566,6 +589,7 @@ public class MainViewModel extends AbstractModel
|
|||
joy1Model.resetDataChanged();
|
||||
joy2Model.resetDataChanged();
|
||||
systemModel.resetDataChanged();
|
||||
stateModel.resetDataChanged();
|
||||
|
||||
//Update db title once done
|
||||
infoModel.setTitleFromDb(infoModel.getTitle());
|
||||
|
@ -796,11 +820,16 @@ public class MainViewModel extends AbstractModel
|
|||
|
||||
public void runGameInVice()
|
||||
{
|
||||
fileManager.runVice(true);
|
||||
fileManager.runGameInVice();
|
||||
}
|
||||
|
||||
public void runVice()
|
||||
{
|
||||
fileManager.runVice(false);
|
||||
fileManager.runViceWithoutGame();
|
||||
}
|
||||
|
||||
public void runSnapshotInVice(SavedStatesModel.SAVESTATE saveState)
|
||||
{
|
||||
fileManager.runSnapshotInVice(saveState);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SavedStatesModel extends AbstractModel
|
||||
{
|
||||
public static enum SAVESTATE {Save0, Save1, Save2, Save3};
|
||||
private String state1PngFile = "";
|
||||
private String state2PngFile = "";
|
||||
private String state3PngFile = "";
|
||||
private String state4PngFile = "";
|
||||
|
||||
private BufferedImage state1PngImage;
|
||||
private BufferedImage state2PngImage;
|
||||
private BufferedImage state3PngImage;
|
||||
private BufferedImage state4PngImage;
|
||||
|
||||
private Path state1Path;
|
||||
private Path state2Path;
|
||||
private Path state3Path;
|
||||
private Path state4Path;
|
||||
|
||||
private String state1File;
|
||||
private String state2File;
|
||||
private String state3File;
|
||||
private String state4File;
|
||||
|
||||
private String state1time = "00:00:00";
|
||||
private String state2time = "00:00:00";
|
||||
private String state3time = "00:00:00";
|
||||
private String state4time = "00:00:00";
|
||||
|
||||
public String getState1PngFile()
|
||||
{
|
||||
return state1PngFile;
|
||||
}
|
||||
public void setState1PngFile(String state1PngFile)
|
||||
{
|
||||
String old = getState1PngFile();
|
||||
this.state1PngFile = state1PngFile;
|
||||
if (!Objects.equals(old, state1PngFile))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getState2PngFile()
|
||||
{
|
||||
return state2PngFile;
|
||||
}
|
||||
public void setState2PngFile(String state2PngFile)
|
||||
{
|
||||
String old = getState2PngFile();
|
||||
this.state2PngFile = state2PngFile;
|
||||
if (!Objects.equals(old, state2PngFile))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState3PngFile()
|
||||
{
|
||||
return state3PngFile;
|
||||
}
|
||||
public void setState3PngFile(String state3PngFile)
|
||||
{
|
||||
String old = getState3PngFile();
|
||||
this.state3PngFile = state3PngFile;
|
||||
if (!Objects.equals(old, state3PngFile))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState4PngFile()
|
||||
{
|
||||
return state4PngFile;
|
||||
}
|
||||
public void setState4PngFile(String state4PngFile)
|
||||
{
|
||||
String old = getState4PngFile();
|
||||
this.state4PngFile = state4PngFile;
|
||||
if (!Objects.equals(old, state4PngFile))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getState1PngImage()
|
||||
{
|
||||
return state1PngImage;
|
||||
}
|
||||
public void setState1PngImage(BufferedImage state1PngImage)
|
||||
{
|
||||
BufferedImage old = getState1PngImage();
|
||||
this.state1PngImage = state1PngImage;
|
||||
if (!Objects.equals(old, state1PngImage))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public BufferedImage getState2PngImage()
|
||||
{
|
||||
return state2PngImage;
|
||||
}
|
||||
public void setState2PngImage(BufferedImage state2PngImage)
|
||||
{
|
||||
BufferedImage old = getState2PngImage();
|
||||
this.state2PngImage = state2PngImage;
|
||||
if (!Objects.equals(old, state2PngImage))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public BufferedImage getState3PngImage()
|
||||
{
|
||||
return state3PngImage;
|
||||
}
|
||||
public void setState3PngImage(BufferedImage state3PngImage)
|
||||
{
|
||||
BufferedImage old = getState3PngImage();
|
||||
this.state3PngImage = state3PngImage;
|
||||
if (!Objects.equals(old, state3PngImage))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public BufferedImage getState4PngImage()
|
||||
{
|
||||
return state4PngImage;
|
||||
}
|
||||
public void setState4PngImage(BufferedImage state4PngImage)
|
||||
{
|
||||
BufferedImage old = getState4PngImage();
|
||||
this.state4PngImage = state4PngImage;
|
||||
if (!Objects.equals(old, state4PngImage))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public Path getState1Path()
|
||||
{
|
||||
return state1Path;
|
||||
}
|
||||
public void setState1Path(Path state1Path)
|
||||
{
|
||||
Path old = getState1Path();
|
||||
this.state1Path = state1Path;
|
||||
if (!Objects.equals(old, state1Path))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public Path getState2Path()
|
||||
{
|
||||
return state2Path;
|
||||
}
|
||||
public void setState2Path(Path state2Path)
|
||||
{
|
||||
Path old = getState2Path();
|
||||
this.state2Path = state2Path;
|
||||
if (!Objects.equals(old, state2Path))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public Path getState3Path()
|
||||
{
|
||||
return state3Path;
|
||||
}
|
||||
public void setState3Path(Path state3Path)
|
||||
{
|
||||
Path old = getState3Path();
|
||||
this.state3Path = state3Path;
|
||||
if (!Objects.equals(old, state3Path))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public Path getState4Path()
|
||||
{
|
||||
return state4Path;
|
||||
}
|
||||
public void setState4Path(Path state4Path)
|
||||
{
|
||||
Path old = getState4Path();
|
||||
this.state4Path = state4Path;
|
||||
if (!Objects.equals(old, state4Path))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState1time()
|
||||
{
|
||||
return state1time;
|
||||
}
|
||||
public void setState1time(String state1time)
|
||||
{
|
||||
String old = getState1time();
|
||||
this.state1time = validatePlayTime(state1time);
|
||||
if (!Objects.equals(old, state1time))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState2time()
|
||||
{
|
||||
return state2time;
|
||||
}
|
||||
public void setState2time(String state2time)
|
||||
{
|
||||
String old = getState2time();
|
||||
this.state2time = validatePlayTime(state2time);
|
||||
if (!Objects.equals(old, state2time))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState3time()
|
||||
{
|
||||
return state3time;
|
||||
}
|
||||
public void setState3time(String state3time)
|
||||
{
|
||||
String old = getState3time();
|
||||
this.state3time = validatePlayTime(state3time);
|
||||
if (!Objects.equals(old, state3time))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState4time()
|
||||
{
|
||||
return state4time;
|
||||
}
|
||||
public void setState4time(String state4time)
|
||||
{
|
||||
String old = getState4time();
|
||||
this.state4time = validatePlayTime(state4time);
|
||||
if (!Objects.equals(old, state4time))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getState1File()
|
||||
{
|
||||
return state1File;
|
||||
}
|
||||
public void setState1File(String state1File)
|
||||
{
|
||||
String old = getState1File();
|
||||
this.state1File = state1File;
|
||||
if (!Objects.equals(old, state1File))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState2File()
|
||||
{
|
||||
return state2File;
|
||||
}
|
||||
public void setState2File(String state2File)
|
||||
{
|
||||
String old = getState2File();
|
||||
this.state2File = state2File;
|
||||
if (!Objects.equals(old, state2File))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState3File()
|
||||
{
|
||||
return state3File;
|
||||
}
|
||||
public void setState3File(String state3File)
|
||||
{
|
||||
String old = getState3File();
|
||||
this.state3File = state3File;
|
||||
if (!Objects.equals(old, state3File))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public String getState4File()
|
||||
{
|
||||
return state4File;
|
||||
}
|
||||
public void setState4File(String state4File)
|
||||
{
|
||||
String old = getState4File();
|
||||
this.state4File = state4File;
|
||||
if (!Objects.equals(old, state4File))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
public void resetProperties()
|
||||
{
|
||||
state1PngFile = "";
|
||||
state2PngFile = "";
|
||||
state3PngFile = "";
|
||||
state4PngFile = "";
|
||||
state1PngImage = null;
|
||||
state2PngImage = null;
|
||||
state3PngImage = null;
|
||||
state4PngImage = null;
|
||||
state1Path = null;
|
||||
state2Path = null;
|
||||
state3Path = null;
|
||||
state4Path = null;
|
||||
state1time = "00:00:00";
|
||||
state2time = "00:00:00";
|
||||
state3time = "00:00:00";
|
||||
state4time = "00:00:00";
|
||||
state1File = "";
|
||||
state2File = "";
|
||||
state3File = "";
|
||||
state4File = "";
|
||||
}
|
||||
|
||||
public void notifyChange()
|
||||
{
|
||||
super.notifyChange();
|
||||
}
|
||||
|
||||
private String validatePlayTime(String playTime)
|
||||
{
|
||||
String[] timeparts = playTime.split(":");
|
||||
//Validate hours and minutes
|
||||
if (Integer.parseInt(timeparts[1]) > 59)
|
||||
{
|
||||
timeparts[1] = "00";
|
||||
}
|
||||
if (Integer.parseInt(timeparts[2]) > 59)
|
||||
{
|
||||
timeparts[2] = "00";
|
||||
}
|
||||
return timeparts[0] + ":" + timeparts[1] + ":" + timeparts[2];
|
||||
}
|
||||
}
|
|
@ -8,6 +8,9 @@ import java.io.IOException;
|
|||
import java.io.PrintStream;
|
||||
import java.io.Reader;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import se.lantz.util.FileDrop.TransferableObject;
|
||||
|
||||
/**
|
||||
|
@ -221,7 +224,12 @@ public class FileDrop
|
|||
final boolean recursive,
|
||||
final Listener listener)
|
||||
{
|
||||
|
||||
|
||||
if (c instanceof javax.swing.JLabel)
|
||||
{
|
||||
((JComponent)c).setBorder(new EmptyBorder(2, 2, 2, 2));
|
||||
}
|
||||
|
||||
if (supportsDnD())
|
||||
{ // Make a drop listener
|
||||
dropListener = new java.awt.dnd.DropTargetListener()
|
||||
|
|
|
@ -43,8 +43,11 @@ import com.github.junrar.Archive;
|
|||
import com.github.junrar.rarfile.FileHeader;
|
||||
|
||||
import se.lantz.db.DbConnector;
|
||||
import se.lantz.manager.SavedStatesManager;
|
||||
import se.lantz.model.InfoModel;
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.SavedStatesModel;
|
||||
import se.lantz.model.SavedStatesModel.SAVESTATE;
|
||||
import se.lantz.model.SystemModel;
|
||||
import se.lantz.model.data.GameDetails;
|
||||
|
||||
|
@ -58,6 +61,7 @@ public class FileManager
|
|||
private static final String GAMES = "./games/";
|
||||
private static final String SCREENS = "./screens/";
|
||||
private static final String COVERS = "./covers/";
|
||||
private static final String SAVES = "./saves/";
|
||||
private static final String BACKUP = "./backup/";
|
||||
|
||||
private static final Path TEMP_PATH = Paths.get("./temp");
|
||||
|
@ -68,6 +72,7 @@ public class FileManager
|
|||
private MainViewModel model;
|
||||
private InfoModel infoModel;
|
||||
private SystemModel systemModel;
|
||||
private SavedStatesModel savedStatesModel;
|
||||
private static ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private static List<String> validFileEndingList =
|
||||
|
@ -92,6 +97,7 @@ public class FileManager
|
|||
{
|
||||
this.infoModel = model.getInfoModel();
|
||||
this.systemModel = model.getSystemModel();
|
||||
this.savedStatesModel = model.getSavedStatesModel();
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
|
@ -136,11 +142,12 @@ public class FileManager
|
|||
if (cover.getWidth() != 122 || cover.getHeight() != 175)
|
||||
{
|
||||
Image scaledCoverImage = cover.getScaledInstance(122, 175, Image.SCALE_SMOOTH);
|
||||
imageToSave =
|
||||
new BufferedImage(scaledCoverImage.getWidth(null), scaledCoverImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
|
||||
imageToSave = new BufferedImage(scaledCoverImage.getWidth(null),
|
||||
scaledCoverImage.getHeight(null),
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics g = imageToSave.createGraphics();
|
||||
g.drawImage(scaledCoverImage, 0, 0, null);
|
||||
g.dispose();
|
||||
g.dispose();
|
||||
}
|
||||
File outputfile = new File(COVERS + coverFileName);
|
||||
ImageIO.write(imageToSave, "png", outputfile);
|
||||
|
@ -481,9 +488,91 @@ public class FileManager
|
|||
return description.replaceAll("-", " ");
|
||||
}
|
||||
|
||||
public void runVice(boolean appendGame)
|
||||
public void runGameInVice()
|
||||
{
|
||||
String gamePathString = "";
|
||||
//Use path if available, otherwise the available game in /games.
|
||||
Path gamePath = infoModel.getGamesPath();
|
||||
if (gamePath != null)
|
||||
{
|
||||
gamePathString = gamePath.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
gamePathString = GAMES + infoModel.getGamesFile();
|
||||
}
|
||||
runVice(true, gamePathString);
|
||||
}
|
||||
|
||||
public void runViceWithoutGame()
|
||||
{
|
||||
runVice(false, "");
|
||||
}
|
||||
|
||||
public void runSnapshotInVice(SAVESTATE saveState)
|
||||
{
|
||||
String gamePathString = "";
|
||||
Path vsfPath;
|
||||
switch (saveState)
|
||||
{
|
||||
case Save0:
|
||||
{
|
||||
//Use path if available, otherwise the available game in /games.
|
||||
vsfPath = savedStatesModel.getState1Path();
|
||||
if (vsfPath != null)
|
||||
{
|
||||
gamePathString = vsfPath.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
gamePathString = SavedStatesManager.SAVES + infoModel.getGamesFile() + "/" + savedStatesModel.getState1File();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Save1:
|
||||
//Use path if available, otherwise the available game in /games.
|
||||
vsfPath = savedStatesModel.getState2Path();
|
||||
if (vsfPath != null)
|
||||
{
|
||||
gamePathString = vsfPath.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
gamePathString = SavedStatesManager.SAVES + infoModel.getGamesFile() + "/" + savedStatesModel.getState2File();
|
||||
}
|
||||
break;
|
||||
case Save2:
|
||||
//Use path if available, otherwise the available game in /games.
|
||||
vsfPath = savedStatesModel.getState3Path();
|
||||
if (vsfPath != null)
|
||||
{
|
||||
gamePathString = vsfPath.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
gamePathString = SavedStatesManager.SAVES + infoModel.getGamesFile() + "/" + savedStatesModel.getState3File();
|
||||
}
|
||||
break;
|
||||
case Save3:
|
||||
//Use path if available, otherwise the available game in /games.
|
||||
vsfPath = savedStatesModel.getState4Path();
|
||||
if (vsfPath != null)
|
||||
{
|
||||
gamePathString = vsfPath.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
gamePathString = SavedStatesManager.SAVES + infoModel.getGamesFile() + "/" + savedStatesModel.getState4File();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
runVice(true, gamePathString);
|
||||
}
|
||||
|
||||
private void runVice(boolean appendGame, String gamePath)
|
||||
{
|
||||
String gameFile = GAMES + infoModel.getGamesFile();
|
||||
StringBuilder command = new StringBuilder();
|
||||
if (systemModel.isC64())
|
||||
{
|
||||
|
@ -547,19 +636,10 @@ public class FileManager
|
|||
command.append("-ntsc ");
|
||||
}
|
||||
|
||||
if (appendGame)
|
||||
//Append game to autostart (not saved snapshots)
|
||||
if (appendGame && !gamePath.contains(".vsz"))
|
||||
{
|
||||
|
||||
//Append game file
|
||||
Path gamePath = infoModel.getGamesPath();
|
||||
if (gamePath != null)
|
||||
{
|
||||
appendCorrectFlagForGameFile(gamePath.toString(), command);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendCorrectFlagForGameFile(gameFile, command);
|
||||
}
|
||||
appendCorrectFlagForGameFile(gamePath, command);
|
||||
}
|
||||
|
||||
//Append truedrive
|
||||
|
@ -598,6 +678,13 @@ public class FileManager
|
|||
}
|
||||
}
|
||||
|
||||
//Used for saved snapshots, must be at the end of the commands
|
||||
if (appendGame && gamePath.contains(".vsz"))
|
||||
{
|
||||
command.append(" ");
|
||||
command.append(gamePath);
|
||||
}
|
||||
|
||||
//Launch Vice
|
||||
try
|
||||
{
|
||||
|
@ -806,6 +893,21 @@ public class FileManager
|
|||
}
|
||||
}
|
||||
|
||||
public static void backupSaves(String targetFolderName)
|
||||
{
|
||||
File outputFolder = new File(BACKUP + "/" + targetFolderName + "/");
|
||||
try
|
||||
{
|
||||
Files.createDirectories(outputFolder.toPath());
|
||||
Path games = new File(SAVES).toPath();
|
||||
copyDirectory(games.toString(), outputFolder.toPath().resolve("saves").toString());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not create backup of games.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyDirectory(String sourceDirectoryLocation, String destinationDirectoryLocation)
|
||||
throws IOException
|
||||
{
|
||||
|
@ -844,6 +946,18 @@ public class FileManager
|
|||
}
|
||||
}
|
||||
|
||||
private static void deleteSavesDirContent(File dir)
|
||||
{
|
||||
try
|
||||
{
|
||||
Files.walk(dir.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not delete saves folder");
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteFilesForGame(GameDetails details)
|
||||
{
|
||||
if (!details.getCover().isEmpty())
|
||||
|
@ -866,6 +980,7 @@ public class FileManager
|
|||
File gameFile = new File(GAMES + details.getGame());
|
||||
gameFile.delete();
|
||||
}
|
||||
//TODO: Shall we delete saved states also?? Or should the saved states be kept?
|
||||
}
|
||||
|
||||
public static void restoreDb(String backupFolderName)
|
||||
|
@ -903,9 +1018,9 @@ public class FileManager
|
|||
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/");
|
||||
try
|
||||
{
|
||||
File coversDir = new File(SCREENS);
|
||||
deleteDirContent(coversDir, true);
|
||||
copyDirectory(backupFolder.toPath().resolve("screens").toString(), coversDir.toPath().toString());
|
||||
File screensDir = new File(SCREENS);
|
||||
deleteDirContent(screensDir, true);
|
||||
copyDirectory(backupFolder.toPath().resolve("screens").toString(), screensDir.toPath().toString());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -918,9 +1033,24 @@ public class FileManager
|
|||
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/");
|
||||
try
|
||||
{
|
||||
File coversDir = new File(GAMES);
|
||||
deleteDirContent(coversDir, true);
|
||||
copyDirectory(backupFolder.toPath().resolve("games").toString(), coversDir.toPath().toString());
|
||||
File gamesDir = new File(GAMES);
|
||||
deleteDirContent(gamesDir, true);
|
||||
copyDirectory(backupFolder.toPath().resolve("games").toString(), gamesDir.toPath().toString());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not restore backup of games.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void restoreSaves(String backupFolderName)
|
||||
{
|
||||
File backupFolder = new File(BACKUP + "/" + backupFolderName + "/");
|
||||
try
|
||||
{
|
||||
File savesDir = new File(SAVES);
|
||||
deleteSavesDirContent(savesDir);
|
||||
copyDirectory(backupFolder.toPath().resolve("saves").toString(), savesDir.toPath().toString());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Loading…
Reference in New Issue