diff --git a/src/main/java/se/lantz/PCUAEManager.java b/src/main/java/se/lantz/PCUAEManager.java index 2bab5a3..cc6e607 100644 --- a/src/main/java/se/lantz/PCUAEManager.java +++ b/src/main/java/se/lantz/PCUAEManager.java @@ -69,8 +69,8 @@ public class PCUAEManager int width = gd.getDisplayMode().getWidth(); int height = gd.getDisplayMode().getHeight(); - mainWindow.setSize(Math.min(width, 1500), Math.min(height - 40, 825)); - mainWindow.setMinimumSize(new Dimension(Math.min(width, 1300), Math.min(height - 40, 700))); + mainWindow.setSize(Math.min(width, 1500), Math.min(height - 40, 850)); + mainWindow.setMinimumSize(new Dimension(Math.min(width, 1300), Math.min(height - 40, 725))); mainWindow.setLocationRelativeTo(null); mainWindow.initialize(); mainWindow.setVisible(true); diff --git a/src/main/java/se/lantz/db/DbConnector.java b/src/main/java/se/lantz/db/DbConnector.java index cd05e78..30d85a7 100644 --- a/src/main/java/se/lantz/db/DbConnector.java +++ b/src/main/java/se/lantz/db/DbConnector.java @@ -33,7 +33,7 @@ import se.lantz.util.GameListDataComparator; public class DbConnector { - public static final String DB_NAME = "pcusb.db"; + public static String DB_FILE = ""; private static final String COMMA = "\",\""; // @J- private static final String GAMEINFO_SQL = @@ -78,7 +78,7 @@ public class DbConnector Map duplicateMap = new HashMap<>(); List addedRowsList = new ArrayList<>(); - public DbConnector() + public DbConnector(List dbFolders) { columnList.add(DbConstants.TITLE); columnList.add(DbConstants.YEAR); @@ -105,17 +105,27 @@ public class DbConnector columnList.add(DbConstants.DISK_4); columnList.add(DbConstants.DISK_5); columnList.add(DbConstants.DISK_6); - //Check if database file exists, if not create an empty db. - File dbFile = new File("./" + DB_NAME); - if (!dbFile.exists()) + + for (String dbFolder : dbFolders) { - createNewDb(); - logger.debug("Database missing, new db created."); + setCurrentDbFolder(dbFolder); + //Check if databases file exists, if not create an empty db. + File dbFile = new File("./" + DB_FILE); + if (!dbFile.exists()) + { + createNewDb(); + logger.debug("Database {} missing, new db created.", dbFolder); + } + //To be backwards compatible with 1.0 db, update if missing + addLanguageAndDuplicateColumnsIfMissing(); + //To be backwards compatible with 2.8.2 db, update if missing + addDiskColumnsIfMissing(); } - //To be backwards compatible with 1.0 db, update if missing - addLanguageAndDuplicateColumnsIfMissing(); - //To be backwards compatible with 2.8.2 db, update if missing - addDiskColumnsIfMissing(); + } + + public static void setCurrentDbFolder(String dbFolder) + { + DB_FILE = "./databases/" + dbFolder + "/pcusb.db"; } private void createNewDb() @@ -294,7 +304,7 @@ public class DbConnector try { // db parameters - String url = "jdbc:sqlite:" + DB_NAME; + String url = "jdbc:sqlite:" + DB_FILE; // create a connection to the database connection = DriverManager.getConnection(url); diff --git a/src/main/java/se/lantz/gui/DraggableTabbedPane.java b/src/main/java/se/lantz/gui/DraggableTabbedPane.java new file mode 100644 index 0000000..b6e0a3d --- /dev/null +++ b/src/main/java/se/lantz/gui/DraggableTabbedPane.java @@ -0,0 +1,254 @@ +package se.lantz.gui; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.awt.image.BufferedImage; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; + +public class DraggableTabbedPane extends JTabbedPane +{ + + private boolean dragging = false; + private Image tabImage = null; + private Point currentMouseLocation = null; + private int draggedTabIndex = 0; + + private Rectangle draggedTabBounds = null; + private int previouslySelectedIndex; + + private ActionListener draggedTabListener = null; + private ActionListener tabStructureChangedListener = null; + + public DraggableTabbedPane() + { + super(); + + addMouseMotionListener(new MouseMotionAdapter() + { + + public void mouseDragged(MouseEvent e) + { + + if (!dragging) + { + // Gets the tab index based on the mouse position + int tabNumber = getUI().tabForCoordinate(DraggableTabbedPane.this, e.getX(), e.getY()); + + if (tabNumber >= 0 && tabNumber < (getTabCount() - 1)) + { + draggedTabIndex = tabNumber; + Rectangle bounds = getUI().getTabBounds(DraggableTabbedPane.this, tabNumber); + + draggedTabBounds = bounds; + // Paint the tabbed pane to a buffer + Image totalImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics totalGraphics = totalImage.getGraphics(); + totalGraphics.setClip(bounds); + // Don't be double buffered when painting to a static image. + setDoubleBuffered(false); + paintComponent(totalGraphics); + + // Paint just the dragged tab to the buffer + tabImage = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_ARGB); + Graphics graphics = tabImage.getGraphics(); + graphics.drawImage(totalImage, + 0, + 0, + bounds.width, + bounds.height, + bounds.x, + bounds.y, + bounds.x + bounds.width, + bounds.y + bounds.height, + DraggableTabbedPane.this); + + dragging = true; + repaint(); + } + } + else + { + currentMouseLocation = e.getPoint(); + + // Need to repaint + repaint(); + } + + super.mouseDragged(e); + } + }); + + addMouseListener(new MouseAdapter() + { + @Override + public void mouseReleased(MouseEvent e) + { + if (dragging) + { + int tabNumber = -1; + + Rectangle lastTabBounds = getUI().getTabBounds(DraggableTabbedPane.this, getTabCount() - 2); + + int draggedTabXposToCheck = e.getX() + draggedTabBounds.width / 2; + + //Dragging left of first tab always puts the tab first + if (e.getX() <= 0) + { + tabNumber = 0; + } + //Dragging right of next-to-last tab always puts the tab last + else if (lastTabBounds.x + lastTabBounds.width / 2 < draggedTabXposToCheck) + { + //Add in last position (before "+") + tabNumber = getTabCount() - 2; + } + else + { + + tabNumber = getUI().tabForCoordinate(DraggableTabbedPane.this, draggedTabXposToCheck, 10); + + Rectangle tabBounds = getUI().getTabBounds(DraggableTabbedPane.this, tabNumber); + int halfTabPosition = tabBounds.x + tabBounds.width / 2; + + //Dragging right + if (e.getX() > draggedTabBounds.x) + { + if (draggedTabXposToCheck < halfTabPosition) + { + //Do not move the tab + tabNumber--; + } + } + //Dragging left + else + { + if (draggedTabXposToCheck > halfTabPosition) + { + //Do not move the tab + tabNumber++; + } + } + } + + if (tabNumber == draggedTabIndex) + { + //Do nothing + } + else if (tabNumber >= 0 && tabNumber < (getTabCount() - 1)) + { + Component comp = getComponentAt(draggedTabIndex); + String title = getTitleAt(draggedTabIndex); + removeTabAt(draggedTabIndex); + insertTab(title, null, comp, null, tabNumber); + notifyTabDraggedListener(tabNumber); + notifyTabStructureChangedListener(); + setSelectedIndex(tabNumber); + } + } + + dragging = false; + tabImage = null; + // Need to repaint + repaint(); + } + + @Override + public void mouseClicked(MouseEvent e) + { + if (SwingUtilities.isRightMouseButton(e)) + { + + int tabNumber = getUI().tabForCoordinate(DraggableTabbedPane.this, e.getX(), 10); + + if (tabNumber > -1 && (tabNumber < getTabCount() - 1)) + { + JPopupMenu menu = new JPopupMenu(); + JMenuItem renameTabItem = new JMenuItem("Rename database"); + JMenuItem deleteTabItem = new JMenuItem("Delete database"); + menu.add(renameTabItem); + menu.add(deleteTabItem); + menu.show(DraggableTabbedPane.this, e.getX(), e.getY()); + } + } + } + }); + } + + public void addTabDraggedListener(ActionListener listener) + { + draggedTabListener = listener; + } + + public void addTabStructureChangedListener(ActionListener listener) + { + tabStructureChangedListener = listener; + } + + private void notifyTabDraggedListener(int tabNumber) + { + if (draggedTabListener != null) + { + draggedTabListener.actionPerformed(new ActionEvent(this, tabNumber, "inserted")); + } + } + + private void notifyTabStructureChangedListener() + { + if (tabStructureChangedListener != null) + { + tabStructureChangedListener.actionPerformed(new ActionEvent(this, 0, "structure changed")); + } + } + + public boolean isDragging() + { + return dragging; + } + + public int getPreviouslySelectedIndex() + { + return previouslySelectedIndex; + } + + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + + // Are we dragging? + if (dragging && currentMouseLocation != null && tabImage != null) + { + // Draw the dragged tab + g.drawImage(tabImage, currentMouseLocation.x, 0, this);//currentMouseLocation.y, this); + } + } + + public static void main(String[] args) + { + JFrame test = new JFrame("Tab test"); + test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + test.setSize(800, 800); + + DraggableTabbedPane tabs = new DraggableTabbedPane(); + tabs.addTab("One", new JButton("One")); + tabs.addTab("Two", new JButton("Two")); + tabs.addTab("Three", new JButton("Three")); + tabs.addTab("+", new JButton("+")); + + test.add(tabs); + test.setVisible(true); + } +} \ No newline at end of file diff --git a/src/main/java/se/lantz/gui/MainPanel.java b/src/main/java/se/lantz/gui/MainPanel.java index 1f20b9c..0906c5b 100644 --- a/src/main/java/se/lantz/gui/MainPanel.java +++ b/src/main/java/se/lantz/gui/MainPanel.java @@ -1,17 +1,13 @@ package se.lantz.gui; import java.awt.BorderLayout; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; +import java.util.ArrayList; import java.util.List; -import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSplitPane; -import javax.swing.KeyStroke; -import javax.swing.ToolTipManager; import se.lantz.model.MainViewModel; import se.lantz.model.data.GameListData; @@ -20,21 +16,94 @@ public class MainPanel extends JPanel { private JSplitPane splitPane; private ListPanel listPanel; + private DraggableTabbedPane tabbedPane; private GameDetailsBackgroundPanel gameDetailsBackgroundPanel; private final MainViewModel uiModel; + private int previouslySelectedIndex = 0; + private boolean ignoreTabChange = false; + public MainPanel(final MainViewModel uiModel) { this.uiModel = uiModel; setLayout(new BorderLayout(0, 0)); - add(getSplitPane(), BorderLayout.CENTER); + add(getTabbedPane(), BorderLayout.CENTER); uiModel.addSaveChangeListener(e -> { listPanel.checkSaveChangeStatus(); }); - uiModel.addRequireFieldsListener(e -> showRequiredFieldsDialog((List) e.getNewValue())); + uiModel.addRequiredFieldsListener(e -> showRequiredFieldsDialog((List) e.getNewValue())); + } + + private DraggableTabbedPane getTabbedPane() + { + if (tabbedPane == null) + { + tabbedPane = new DraggableTabbedPane(); + + for (int i = 0; i < uiModel.getAvailableDatabases().size(); i++) + { + if (i == 0) + { + tabbedPane.addTab(uiModel.getAvailableDatabases().get(i), getNewContentPanel(getSplitPane())); + } + else + { + tabbedPane.addTab(uiModel.getAvailableDatabases().get(i), getNewContentPanel(null)); + } + } + tabbedPane.addTab(" + ", getNewContentPanel(null)); + + //Update previous selected index once a tab is dragged to a new position + tabbedPane.addTabDraggedListener(e -> previouslySelectedIndex = e.getID()); + //Update preferences when the tab structure changes (renamed, deleted, re-arranged) + tabbedPane.addTabStructureChangedListener(e -> updateTabOrderPreferences()); + + tabbedPane.addChangeListener(e -> { + if (!tabbedPane.isDragging()) + { + if (tabbedPane.getSelectedIndex() == uiModel.getAvailableDatabases().size()) + { + ignoreTabChange = true; + tabbedPane.setSelectedIndex(previouslySelectedIndex); + ignoreTabChange = false; + String name = JOptionPane.showInputDialog(this, "Write a new name!"); + //Create a new empty one! + return; + } + else if (ignoreTabChange) + { + //Do nothing + return; + } + + MainWindow.getInstance().setWaitCursor(true); + int selectedIndex = tabbedPane.getSelectedIndex(); + + ((JPanel) tabbedPane.getComponentAt(previouslySelectedIndex)).removeAll(); + ((JPanel) tabbedPane.getComponentAt(selectedIndex)).add(getSplitPane(), BorderLayout.CENTER); + previouslySelectedIndex = tabbedPane.getSelectedIndex(); + + uiModel.setCurrentDatabase(tabbedPane.getTitleAt(selectedIndex)); + MainWindow.getInstance().setWaitCursor(false); + invalidate(); + repaint(); + } + }); + } + return tabbedPane; + } + + private void updateTabOrderPreferences() + { + List tabTitles = new ArrayList<>(); + for (int i = 0; i < tabbedPane.getTabCount() - 1; i++) + { + tabTitles.add(tabbedPane.getTitleAt(i)); + } + uiModel.updateDbTabPreferences(String.join(",", tabTitles)); } private JSplitPane getSplitPane() @@ -49,6 +118,16 @@ public class MainPanel extends JPanel return splitPane; } + private JPanel getNewContentPanel(JComponent content) + { + JPanel panel = new JPanel(new BorderLayout()); + if (content != null) + { + panel.add(content, BorderLayout.CENTER); + } + return panel; + } + public ListPanel getListPanel() { if (listPanel == null) @@ -138,8 +217,8 @@ public class MainPanel extends JPanel uiModel.deleteGames(selectedGameListData); } else - { - uiModel.deleteCurrentGame(); + { + uiModel.deleteCurrentGame(); } //Reload the current view reloadCurrentGameView(); @@ -246,17 +325,17 @@ public class MainPanel extends JPanel { getListPanel().toggleFavorite10(); } - + public void setViewTag(String viewTag) { getListPanel().setViewTag(viewTag); } - + public boolean isSingleGameSelected() { return getListPanel().isSingleGameSelected(); } - + public boolean isNoGameSelected() { return getListPanel().isNoGameSelected(); @@ -279,12 +358,12 @@ public class MainPanel extends JPanel { getListPanel().reloadCurrentGameView(); } - + public void updateSavedStatesTabTitle() { getGameDetailsBackgroundPanel().updateSavedStatesTabTitle(); } - + public void setSelectedGameInGameList(String gameId) { getListPanel().setSelectedGameInGameList(gameId); diff --git a/src/main/java/se/lantz/gui/SaveStatePanel.java b/src/main/java/se/lantz/gui/SaveStatePanel.java index a5b5778..3ae3bbc 100644 --- a/src/main/java/se/lantz/gui/SaveStatePanel.java +++ b/src/main/java/se/lantz/gui/SaveStatePanel.java @@ -314,7 +314,7 @@ public class SaveStatePanel extends JPanel String fileName = SavedStatesManager.getGameFolderName(model.getInfoModel().getGamesFile(), model.getInfoModel().getTitle()); logger.debug(fileName.toString()); - Path saveFolderPath = new File("./saves/" + fileName).toPath(); + Path saveFolderPath = new File(FileManager.SAVES + fileName).toPath(); File imagefile = saveFolderPath.resolve(filename).toFile(); try { diff --git a/src/main/java/se/lantz/gui/ScreenshotsPanel.java b/src/main/java/se/lantz/gui/ScreenshotsPanel.java index 0ca60e6..ab6e791 100644 --- a/src/main/java/se/lantz/gui/ScreenshotsPanel.java +++ b/src/main/java/se/lantz/gui/ScreenshotsPanel.java @@ -273,7 +273,7 @@ public class ScreenshotsPanel extends JPanel { if (!filename.isEmpty()) { - File imagefile = new File("./covers/" + filename); + File imagefile = new File(FileManager.COVERS + filename); try { BufferedImage image = ImageIO.read(imagefile); @@ -297,7 +297,7 @@ public class ScreenshotsPanel extends JPanel BufferedImage image = null; if (!filename.isEmpty()) { - File imagefile = new File("./screens/" + filename); + File imagefile = new File(FileManager.SCREENS + filename); try { image = ImageIO.read(imagefile); diff --git a/src/main/java/se/lantz/manager/SavedStatesManager.java b/src/main/java/se/lantz/manager/SavedStatesManager.java index d6f2171..71216c4 100644 --- a/src/main/java/se/lantz/manager/SavedStatesManager.java +++ b/src/main/java/se/lantz/manager/SavedStatesManager.java @@ -42,8 +42,6 @@ public class SavedStatesManager { private static final Logger logger = LoggerFactory.getLogger(SavedStatesManager.class); - 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"; @@ -111,18 +109,18 @@ public class SavedStatesManager //If the game has been renamed, make sure to rename the saves folder also String oldFileName = model.getInfoModel().getOldGamesFile(); String newFileName = model.getInfoModel().getGamesFile(); - File oldSaveFolder = new File(SAVES + getGameFolderName(oldFileName, model.getInfoModel().getTitle())); + File oldSaveFolder = new File(FileManager.SAVES + getGameFolderName(oldFileName, model.getInfoModel().getTitle())); if (!oldFileName.equals(newFileName) && oldSaveFolder.exists()) { //Rename old folder to new name - oldSaveFolder.renameTo(new File(SAVES + + oldSaveFolder.renameTo(new File(FileManager.SAVES + getGameFolderName(model.getInfoModel().getGamesFile(), model.getInfoModel().getTitle()))); } String fileName = model.getInfoModel().getGamesFile(); String gameFolderName = getGameFolderName(fileName, model.getInfoModel().getTitle()); - Path saveFolder = new File(SAVES + gameFolderName).toPath(); + Path saveFolder = new File(FileManager.SAVES + gameFolderName).toPath(); int numberofSaves = 0; //Check which ones are available Path mta0Path = saveFolder.resolve(MTA0); @@ -178,7 +176,7 @@ public class SavedStatesManager { fileName = fileName.trim(); //Check if folder is available - Path saveFolder = new File(SAVES + fileName).toPath(); + Path saveFolder = new File(FileManager.SAVES + fileName).toPath(); if (Files.exists(saveFolder)) { //Check which ones are available @@ -349,7 +347,7 @@ public class SavedStatesManager private void deleteSavedState(SAVESTATE state) { String fileName = getGameFolderName(model.getInfoModel().getGamesFile(), model.getInfoModel().getTitle()); - Path saveFolder = new File(SAVES + fileName).toPath(); + Path saveFolder = new File(FileManager.SAVES + fileName).toPath(); try { switch (state) @@ -399,7 +397,7 @@ public class SavedStatesManager public void exportSavedStates(PublishWorker worker) { noFilesCopied = 0; - File saveFolder = new File(SAVES); + File saveFolder = new File(FileManager.SAVES); try (Stream stream = Files.walk(saveFolder.toPath().toAbsolutePath())) { stream.forEachOrdered(sourcePath -> { @@ -452,7 +450,7 @@ public class SavedStatesManager public void importSavedStates(PublishWorker worker) { noFilesCopied = 0; - File saveFolder = new File(SAVES); + File saveFolder = new File(FileManager.SAVES); try (Stream stream = Files.walk(importDir.toPath().toAbsolutePath())) { stream.forEachOrdered(sourcePath -> { @@ -568,7 +566,7 @@ public class SavedStatesManager { savedStatesMap.clear(); //Read all files in the saves folder - File saveFolder = new File(SAVES); + File saveFolder = new File(FileManager.SAVES); try (Stream stream = Files.walk(saveFolder.toPath().toAbsolutePath(), 1)) { stream.forEachOrdered(sourcePath -> { @@ -634,7 +632,7 @@ public class SavedStatesManager if (!fileName.isEmpty() && fileName.contains(".vsf")) { //Check if folder is available - Path saveFolder = new File(SAVES + getGameFolderName(fileName, model.getInfoModel().getTitle())).toPath(); + Path saveFolder = new File(FileManager.SAVES + getGameFolderName(fileName, model.getInfoModel().getTitle())).toPath(); if (Files.exists(saveFolder)) { //Check which ones are available @@ -654,7 +652,7 @@ public class SavedStatesManager String gamesFile = model.getInfoModel().getGamesFile(); Path gameFilePath = new File(FileManager.GAMES + gamesFile).toPath(); Path firstSavedStatePath = - new File(SAVES + getGameFolderName(gamesFile, model.getInfoModel().getTitle())).toPath().resolve(VSZ0); + new File(FileManager.SAVES + getGameFolderName(gamesFile, model.getInfoModel().getTitle())).toPath().resolve(VSZ0); Path tempFilePath = new File(FileManager.GAMES + "temp.gz").toPath(); try @@ -709,7 +707,7 @@ public class SavedStatesManager public void convertToCarousel152Version() { - File saveFolder = new File(SAVES); + File saveFolder = new File(FileManager.SAVES); try (Stream stream = Files.walk(saveFolder.toPath().toAbsolutePath(), 1)) { stream.forEachOrdered(sourcePath -> { @@ -798,7 +796,7 @@ public class SavedStatesManager { //1. look through all folders and try to find a game in the db that matches the file name. //2. for all that matches, get the title and copy the existing folder to a folder named as the title - File saveFolder = new File(SAVES); + File saveFolder = new File(FileManager.SAVES); try (Stream stream = Files.walk(saveFolder.toPath().toAbsolutePath(), 1)) { List allGamesDetailsList = this.model.getDbConnector().fetchAllGamesForDbValdation(); @@ -872,7 +870,7 @@ public class SavedStatesManager public int checkFor132SavedStates() { - File saveFolder = new File(SAVES); + File saveFolder = new File(FileManager.SAVES); long returnValue = 0; try (Stream stream = Files.walk(saveFolder.toPath().toAbsolutePath(), 1)) { @@ -902,7 +900,7 @@ public class SavedStatesManager { //1. look through all folders and try to find a game in the db that matches the file name. //2. for all that matches, get the title and check so that no folder exists already - File saveFolder = new File(SAVES); + File saveFolder = new File(FileManager.SAVES); try (Stream stream = Files.walk(saveFolder.toPath().toAbsolutePath(), 1)) { List allGamesDetailsList = this.model.getDbConnector().fetchAllGamesForDbValdation(); diff --git a/src/main/java/se/lantz/model/MainViewModel.java b/src/main/java/se/lantz/model/MainViewModel.java index a5aecdb..bb2a19b 100644 --- a/src/main/java/se/lantz/model/MainViewModel.java +++ b/src/main/java/se/lantz/model/MainViewModel.java @@ -8,10 +8,18 @@ import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.swing.DefaultComboBoxModel; import javax.swing.SwingUtilities; @@ -28,11 +36,14 @@ import se.lantz.model.data.GameListData; import se.lantz.model.data.GameView; import se.lantz.scraper.MobyGamesScraper; import se.lantz.scraper.Scraper; +import se.lantz.util.ExceptionHandler; import se.lantz.util.FileManager; import se.lantz.util.TextComponentSupport; public class MainViewModel extends AbstractModel { + public static final String DB_TAB_ORDER = "dbTabOrder"; + private static final Logger logger = LoggerFactory.getLogger(MainViewModel.class); DbConnector dbConnector; @@ -81,10 +92,51 @@ public class MainViewModel extends AbstractModel Scraper scraper = new MobyGamesScraper(); private int numberOfFavoritesViews = 10; - + private boolean notifyGameListChange = true; private boolean notifyGameSelected = true; + private List availableDatabases = new ArrayList<>(); + private String selectedDatabase = "Main"; + + public MainViewModel() + { + //Read available databases and preferences for them + try (Stream stream = Files.list(Paths.get("./databases"))) + { + availableDatabases = stream.filter(file -> Files.isDirectory(file)).map(Path::getFileName).map(Path::toString) + .collect(Collectors.toList()); + } + catch (IOException ex) + { + ExceptionHandler.handleException(ex, "Could not read databases"); + } + + if (availableDatabases.size() > 0) + { + //Read preferences for tab order + Properties configuredProperties = FileManager.getConfiguredProperties(); + String tabOrder = (String) configuredProperties.get(DB_TAB_ORDER); + if (tabOrder != null) + { + List preferencesOrder = Arrays.asList(tabOrder.split("\\s*,\\s*")); + + Collections.sort(availableDatabases, + Comparator.comparing(item -> preferencesOrder.indexOf(item))); + } + + selectedDatabase = availableDatabases.get(0); + FileManager.setCurrentDbFolder(selectedDatabase); + DbConnector.setCurrentDbFolder(selectedDatabase); + } + } + + public void updateDbTabPreferences(String prefValue) + { + Properties configuredProperties = FileManager.getConfiguredProperties(); + configuredProperties.put(DB_TAB_ORDER, prefValue); + } + public void setSavedStatesManager(SavedStatesManager savedStatesManager) { this.stateManager = savedStatesManager; @@ -98,7 +150,9 @@ public class MainViewModel extends AbstractModel public void initialize() { logger.debug("Creating DBConnector..."); - dbConnector = new DbConnector(); + //Pass the selected db here + dbConnector = new DbConnector(availableDatabases); + DbConnector.setCurrentDbFolder(selectedDatabase); logger.debug("...done."); setupGameViews(); @@ -237,7 +291,7 @@ public class MainViewModel extends AbstractModel gameViewModel.setSelectedItem(gameViewModel.getElementAt(gameViewModel.getSize() - 1)); } //Do with invokeLater since it's used when selecting a game also - SwingUtilities.invokeLater(() -> notifyGameSelected = true); + SwingUtilities.invokeLater(() -> notifyGameSelected = true); //Finish by selecting all games view again gameViewModel.setSelectedItem(allGameView); notifyGameListChange = true; @@ -635,7 +689,7 @@ public class MainViewModel extends AbstractModel getSavedStatesModel().addPropertyChangeListener(saveChangeListener); } - public void addRequireFieldsListener(PropertyChangeListener requiredFieldsListener) + public void addRequiredFieldsListener(PropertyChangeListener requiredFieldsListener) { this.requiredFieldsListener = requiredFieldsListener; } @@ -1275,4 +1329,19 @@ public class MainViewModel extends AbstractModel { return this.currentGameDetails; } + + public List getAvailableDatabases() + { + return availableDatabases; + } + + public void setCurrentDatabase(String database) + { + selectedDatabase = database; + //Update all + FileManager.setCurrentDbFolder(selectedDatabase); + DbConnector.setCurrentDbFolder(selectedDatabase); + stateManager.readSavedStatesAndUpdateMap(); + reloadGameViews(); + } } diff --git a/src/main/java/se/lantz/util/FileManager.java b/src/main/java/se/lantz/util/FileManager.java index 8c76797..3facfaf 100644 --- a/src/main/java/se/lantz/util/FileManager.java +++ b/src/main/java/se/lantz/util/FileManager.java @@ -69,12 +69,13 @@ public class FileManager public static BufferedImage infoSlotC64Cover; public static BufferedImage infoSlotVic20Cover; - public 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/"; - public static final String DISKS = "./extradisks/"; + private static String currentDbPath = "./"; + public static String GAMES = "./games/"; + public static String SCREENS = "./screens/"; + public static String COVERS = "./covers/"; + public static String SAVES = "./saves/"; + private static String BACKUP = "./backup/"; + public static String DISKS = "./extradisks/"; private static final Path TEMP_PATH = Paths.get("./temp"); private static final Logger logger = LoggerFactory.getLogger(FileManager.class); @@ -130,6 +131,17 @@ public class FileManager { dbconnector = ref; } + + public static void setCurrentDbFolder(String dbFolder) + { + currentDbPath = "./databases/" + dbFolder + "/"; + GAMES = currentDbPath + "games/"; + SCREENS = currentDbPath + "screens/"; + COVERS = currentDbPath + "covers/"; + SAVES = currentDbPath + "saves/"; + BACKUP = currentDbPath + "backup/"; + DISKS = currentDbPath + "extradisks/"; + } public static InputStream getMissingC64GameFile() throws URISyntaxException { @@ -958,7 +970,7 @@ public class FileManager } else { - gamePathString = SavedStatesManager.SAVES + + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + savedStatesModel.getState1File(); } @@ -973,7 +985,7 @@ public class FileManager } else { - gamePathString = SavedStatesManager.SAVES + + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + savedStatesModel.getState2File(); } @@ -987,7 +999,7 @@ public class FileManager } else { - gamePathString = SavedStatesManager.SAVES + + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + savedStatesModel.getState3File(); } @@ -1001,7 +1013,7 @@ public class FileManager } else { - gamePathString = SavedStatesManager.SAVES + + gamePathString = SAVES + SavedStatesManager.getGameFolderName(infoModel.getGamesFile(), infoModel.getTitle()) + "/" + savedStatesModel.getState4File(); } @@ -1384,9 +1396,9 @@ public class FileManager File outputFolder = new File(BACKUP + "/" + targetFolderName + "/"); try { - File dbFile = new File("./" + DbConnector.DB_NAME); + File dbFile = new File("./" + DbConnector.DB_FILE); Files.createDirectories(outputFolder.toPath()); - Path targetFile = outputFolder.toPath().resolve(DbConnector.DB_NAME); + Path targetFile = outputFolder.toPath().resolve(DbConnector.DB_FILE); Files.copy(dbFile.toPath(), targetFile); } catch (IOException e) @@ -1574,8 +1586,8 @@ public class FileManager File backupFolder = new File(BACKUP + "/" + backupFolderName + "/"); try { - Path backupFile = backupFolder.toPath().resolve(DbConnector.DB_NAME); - Path dbFile = new File("./" + DbConnector.DB_NAME).toPath(); + Path backupFile = backupFolder.toPath().resolve(DbConnector.DB_FILE); + Path dbFile = new File("./" + DbConnector.DB_FILE).toPath(); Files.copy(backupFile, dbFile, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e)