|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/test/java" output="target/test-classes" including="**/*.java"/>
|
||||
<classpathentry kind="src" path="src/test/resources" output="target/test-classes" excluding="**/*.java"/>
|
||||
<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
|
||||
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="var" path="M2_REPO/org/xerial/sqlite-jdbc/3.32.3.2/sqlite-jdbc-3.32.3.2.jar" sourcepath="M2_REPO/org/xerial/sqlite-jdbc/3.32.3.2/sqlite-jdbc-3.32.3.2-sources.jar"/>
|
||||
<classpathentry kind="var" path="M2_REPO/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar" sourcepath="M2_REPO/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3-sources.jar"/>
|
||||
<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar" sourcepath="M2_REPO/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30-sources.jar"/>
|
||||
<classpathentry kind="var" path="M2_REPO/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar" sourcepath="M2_REPO/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3-sources.jar"/>
|
||||
<classpathentry kind="var" path="M2_REPO/org/jsoup/jsoup/1.11.3/jsoup-1.11.3.jar" sourcepath="M2_REPO/org/jsoup/jsoup/1.11.3/jsoup-1.11.3-sources.jar"/>
|
||||
</classpath>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>PCUGameManager</name>
|
||||
<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
|
||||
<projects/>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,123 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>se.lantz</groupId>
|
||||
<artifactId>PCUGameManager</artifactId>
|
||||
<version>0.0.9</version>
|
||||
<name>PCUGameManager</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.32.3.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.30</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.11.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<verbose>true</verbose>
|
||||
<fork>true</fork>
|
||||
<executable><!-- path-to-javac -->
|
||||
</executable>
|
||||
<compilerVersion>1.8.0</compilerVersion>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>
|
||||
se.lantz.PCUGameManager
|
||||
</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.akathist.maven.plugins.launch4j</groupId>
|
||||
<artifactId>launch4j-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>l4j-gui</id>
|
||||
<phase>package</phase>
|
||||
<goals><goal>launch4j</goal></goals>
|
||||
<configuration>
|
||||
<headerType>gui</headerType>
|
||||
<outfile>target/PcuGameManager.exe</outfile>
|
||||
<jar>target/PCUGameManager-${project.version}-jar-with-dependencies.jar</jar>
|
||||
<errTitle>PcuGameManager</errTitle>
|
||||
<chdir>.</chdir>
|
||||
<singleInstance>
|
||||
<mutexName>PcuGameManager</mutexName>
|
||||
</singleInstance>
|
||||
<classPath>
|
||||
<mainClass>se.lantz.PCUGameManager</mainClass>
|
||||
<!-- <addDependencies>true</addDependencies> -->
|
||||
</classPath>
|
||||
<jre>
|
||||
<minVersion>1.8</minVersion>
|
||||
<path>./JRE</path>
|
||||
</jre>
|
||||
<splash>
|
||||
<file>target/classes/PCUGameManager.bmp</file>
|
||||
<timeout>30</timeout>
|
||||
</splash>
|
||||
<icon>target/classes/Icon.ico</icon>
|
||||
<versionInfo>
|
||||
<fileVersion>0.0.0.1</fileVersion>
|
||||
<txtFileVersion>txt file version?</txtFileVersion>
|
||||
<fileDescription>a description</fileDescription>
|
||||
<copyright>my copyright</copyright>
|
||||
<productVersion>0.0.0.1</productVersion>
|
||||
<txtProductVersion>txt product version</txtProductVersion>
|
||||
<productName>PcuGameManager</productName>
|
||||
<internalName>pcu</internalName>
|
||||
<originalFilename>PcuGameManager.exe</originalFilename>
|
||||
</versionInfo>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,44 @@
|
|||
package se.lantz;
|
||||
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
|
||||
import se.lantz.gui.MainWindow;
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
import se.lantz.util.TopLevelExceptionHandler;
|
||||
|
||||
public class PCUGameManager
|
||||
{
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Set Exceptionhandler
|
||||
Thread.setDefaultUncaughtExceptionHandler(new TopLevelExceptionHandler());
|
||||
// Set System L&F
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
}
|
||||
catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Startup failure");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
|
||||
MainWindow mainWindow = MainWindow.getInstance();
|
||||
mainWindow.setSize(1500, 950);
|
||||
mainWindow.setMinimumSize(new Dimension(1400, 950));
|
||||
mainWindow.setVisible(true);
|
||||
mainWindow.setLocationRelativeTo(null);
|
||||
mainWindow.initialize();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,677 @@
|
|||
package se.lantz.db;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.model.ImportManager;
|
||||
import se.lantz.model.data.GameDetails;
|
||||
import se.lantz.model.data.GameListData;
|
||||
import se.lantz.model.data.GameView;
|
||||
import se.lantz.model.data.ViewFilter;
|
||||
import se.lantz.util.DbConstants;
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
|
||||
public class DbConnector
|
||||
{
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DbConnector.class);
|
||||
private List<String> columnList = new ArrayList<>();
|
||||
|
||||
public DbConnector()
|
||||
{
|
||||
columnList.add(DbConstants.TITLE);
|
||||
columnList.add(DbConstants.YEAR);
|
||||
columnList.add(DbConstants.AUTHOR);
|
||||
columnList.add(DbConstants.COMPOSER);
|
||||
columnList.add(DbConstants.GENRE);
|
||||
columnList.add(DbConstants.DESC);
|
||||
columnList.add(DbConstants.GAME);
|
||||
columnList.add(DbConstants.COVER);
|
||||
columnList.add(DbConstants.SCREEN1);
|
||||
columnList.add(DbConstants.SCREEN2);
|
||||
columnList.add(DbConstants.JOY1);
|
||||
columnList.add(DbConstants.JOY2);
|
||||
columnList.add(DbConstants.SYSTEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a sample database
|
||||
*
|
||||
* @param fileName the database file name
|
||||
*/
|
||||
public Connection connect()
|
||||
{
|
||||
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
// db parameters
|
||||
String url = "jdbc:sqlite:pcusb.db";
|
||||
// create a connection to the database
|
||||
connection = DriverManager.getConnection(url);
|
||||
|
||||
logger.debug("Connection to SQLite has been established.");
|
||||
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not connect to db.");
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
public List<GameListData> fetchAllGames()
|
||||
{
|
||||
List<GameListData> returnList = new ArrayList<>();
|
||||
String sql = "SELECT title, rowid FROM gameinfo ORDER BY title ASC";
|
||||
try (Connection conn = this.connect(); Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(sql))
|
||||
{
|
||||
// loop through the result set
|
||||
while (rs.next())
|
||||
{
|
||||
GameListData data = new GameListData(rs.getString("Title"), Integer.toString(rs.getInt("rowid")));
|
||||
returnList.add(data);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not fetch all games.");
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public List<GameListData> fetchGamesByView(GameView view)
|
||||
{
|
||||
List<GameListData> returnList = new ArrayList<>();
|
||||
|
||||
//Construct SQL
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT title, rowid FROM gameinfo ");
|
||||
sqlBuilder.append(view.getSqlQuery());
|
||||
sqlBuilder.append(" ORDER BY title ASC");
|
||||
|
||||
logger.debug("Generated View SQL: " + sqlBuilder.toString());
|
||||
try (Connection conn = this.connect(); Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(sqlBuilder.toString()))
|
||||
{
|
||||
// loop through the result set
|
||||
while (rs.next())
|
||||
{
|
||||
GameListData data = new GameListData(rs.getString("Title"), Integer.toString(rs.getInt("rowid")));
|
||||
returnList.add(data);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not fetch games by view = " + view.getName());
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public List<GameView> loadGameViews()
|
||||
{
|
||||
List<GameView> viewList = new ArrayList<>();
|
||||
|
||||
String selectSql = "SELECT * FROM gameview";
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(selectSql))
|
||||
{
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
while (rs.next())
|
||||
{
|
||||
GameView gameView = new GameView(rs.getInt("viewId"));
|
||||
gameView.setName(rs.getString("name"));
|
||||
gameView.setMatchAll(rs.getBoolean("matchAll"));
|
||||
//Fetch all filters
|
||||
List<ViewFilter> viewFilters = new ArrayList<>();
|
||||
|
||||
String filterSql = "SELECT * FROM viewfilter WHERE gameview = " + gameView.getGameViewId();
|
||||
try (PreparedStatement filterstmt = conn.prepareStatement(filterSql))
|
||||
{
|
||||
ResultSet filterRs = filterstmt.executeQuery();
|
||||
while (filterRs.next())
|
||||
{
|
||||
viewFilters.add(new ViewFilter(filterRs.getString("field"),
|
||||
filterRs.getString("operator"),
|
||||
filterRs.getString("fieldData")));
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not load view filters for GameView = " + gameView.getName());
|
||||
}
|
||||
gameView.setViewFilters(viewFilters);
|
||||
viewList.add(gameView);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not load game views.");
|
||||
}
|
||||
return viewList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new db entry for a GameView with gameViewId == 0, or updates an existing entry with the new data.
|
||||
*
|
||||
* @param view The GameView to save in the db.
|
||||
*/
|
||||
public void saveGameView(GameView view)
|
||||
{
|
||||
if (view.getGameViewId() < 0)
|
||||
{
|
||||
logger.debug("Will not do anything with all games view");
|
||||
return;
|
||||
}
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("");
|
||||
if (view.getGameViewId() > 0)
|
||||
{
|
||||
sqlBuilder.append("UPDATE gameview SET name = '");
|
||||
sqlBuilder.append(view.getName());
|
||||
sqlBuilder.append("', matchAll = ");
|
||||
sqlBuilder.append(view.isMatchAll());
|
||||
sqlBuilder.append(" WHERE viewId = ");
|
||||
sqlBuilder.append(view.getGameViewId());
|
||||
sqlBuilder.append(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlBuilder.append("INSERT INTO gameview (name, matchAll) VALUES (\"");
|
||||
sqlBuilder.append(view.getName());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(view.isMatchAll());
|
||||
sqlBuilder.append(");");
|
||||
}
|
||||
String gameViewsql = sqlBuilder.toString();
|
||||
logger.debug("gameViewsql:\n{}", gameViewsql);
|
||||
|
||||
String deleteViewFiltersql = "DELETE FROM viewfilter WHERE gameview = ?";
|
||||
logger.debug("deleteViewFiltersql:\n{}", deleteViewFiltersql);
|
||||
|
||||
StringBuilder insertFilterBuilder = new StringBuilder();
|
||||
insertFilterBuilder.append("INSERT INTO viewfilter (gameview,field,operator,fielddata) VALUES ");
|
||||
int filterIndex = 0;
|
||||
for (ViewFilter filter : view.getViewFilters())
|
||||
{
|
||||
filterIndex++;
|
||||
insertFilterBuilder.append("(");
|
||||
insertFilterBuilder.append(" ? ");
|
||||
insertFilterBuilder.append(",\"");
|
||||
insertFilterBuilder.append(filter.getField());
|
||||
insertFilterBuilder.append("\",\"");
|
||||
insertFilterBuilder.append(filter.getOperator());
|
||||
insertFilterBuilder.append("\",\"");
|
||||
insertFilterBuilder.append(filter.getFilterData());
|
||||
insertFilterBuilder.append("\")");
|
||||
if (filterIndex < view.getViewFilters().size())
|
||||
{
|
||||
insertFilterBuilder.append(",");
|
||||
}
|
||||
}
|
||||
String insertSql = insertFilterBuilder.toString();
|
||||
logger.debug("insertSql:\n{}", insertSql);
|
||||
|
||||
try (Connection conn = this.connect(); PreparedStatement gameViewstmt = conn.prepareStatement(gameViewsql);
|
||||
PreparedStatement deleteFromViewFilterspl = conn.prepareStatement(deleteViewFiltersql);
|
||||
PreparedStatement insertViewFilterstmnt = conn.prepareStatement(insertSql))
|
||||
{
|
||||
gameViewstmt.executeUpdate();
|
||||
int viewId = view.getGameViewId();
|
||||
if (viewId == 0)
|
||||
{
|
||||
ResultSet result = gameViewstmt.getGeneratedKeys();
|
||||
if (result.next())
|
||||
{
|
||||
view.setGameViewId(result.getInt(1));
|
||||
viewId = view.getGameViewId();
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("Unexpected result of insert");
|
||||
return;
|
||||
}
|
||||
}
|
||||
deleteFromViewFilterspl.setInt(1, viewId);
|
||||
deleteFromViewFilterspl.executeUpdate();
|
||||
|
||||
if (!view.getViewFilters().isEmpty())
|
||||
{
|
||||
for (int i = 1; i <= filterIndex; i++)
|
||||
{
|
||||
insertViewFilterstmnt.setInt(i, viewId);
|
||||
}
|
||||
insertViewFilterstmnt.executeUpdate();
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not save game view.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public StringBuilder importRowsInGameInfoTable(List<String> rowValues, ImportManager.Options option)
|
||||
{
|
||||
StringBuilder returnBuilder = new StringBuilder();
|
||||
switch (option)
|
||||
{
|
||||
case SKIP:
|
||||
skipExistingAndInsertMissingIntoGameInfoTable(rowValues, returnBuilder);
|
||||
break;
|
||||
|
||||
case OVERWRITE:
|
||||
overwriteExistingAndInsertMissingIntoGameInfoTable(rowValues, returnBuilder);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return returnBuilder;
|
||||
}
|
||||
|
||||
private void overwriteExistingAndInsertMissingIntoGameInfoTable(List<String> rowValues, StringBuilder infoBuilder)
|
||||
{
|
||||
List<String> existingRowValues = new ArrayList<>();
|
||||
List<String> newRowValues = new ArrayList<>();
|
||||
//Check which are already available and sort them out of rowValues
|
||||
for (String rowValue : rowValues)
|
||||
{
|
||||
String[] splittedRowValue = rowValue.split("\",\"");
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT COUNT(*) FROM gameinfo WHERE title = ");
|
||||
sqlBuilder.append(splittedRowValue[0]);
|
||||
sqlBuilder.append("\";");
|
||||
String sql = sqlBuilder.toString();
|
||||
infoBuilder.append("Checking game: ");
|
||||
infoBuilder.append(splittedRowValue[0].substring(1));
|
||||
infoBuilder.append("\n");
|
||||
logger.debug("Checking game: {}", sql);
|
||||
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
rs.next();
|
||||
if (rs.getInt(1) == 0)
|
||||
{
|
||||
infoBuilder.append("Not available, adding to db\n");
|
||||
logger.debug("Game: {} is not available, adding to db", splittedRowValue[0]);
|
||||
newRowValues.add(rowValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBuilder.append("Already available, overwriting\n");
|
||||
logger.debug("Game: {} is already available, overwriting.", splittedRowValue[0]);
|
||||
existingRowValues.add(rowValue);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
infoBuilder.append("Could not insert games in db.\n");
|
||||
ExceptionHandler.handleException(e, "Could not insert games in db.");
|
||||
}
|
||||
}
|
||||
|
||||
if (existingRowValues.size() > 0)
|
||||
{
|
||||
updateAllInGameInfoTable(existingRowValues);
|
||||
}
|
||||
|
||||
if (newRowValues.size() > 0)
|
||||
{
|
||||
insertAllIntoGameInfoTable(newRowValues, infoBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
private void skipExistingAndInsertMissingIntoGameInfoTable(List<String> rowValues, StringBuilder infoBuilder)
|
||||
{
|
||||
List<String> newRowValues = new ArrayList<>();
|
||||
//Check which are already available and sort them out of rowValues
|
||||
for (String rowValue : rowValues)
|
||||
{
|
||||
String[] splittedRowValue = rowValue.split("\",\"");
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT COUNT(*) FROM gameinfo WHERE title = ");
|
||||
sqlBuilder.append(splittedRowValue[0]);
|
||||
sqlBuilder.append("\";");
|
||||
String sql = sqlBuilder.toString();
|
||||
infoBuilder.append("Checking game: ");
|
||||
infoBuilder.append(splittedRowValue[0].substring(1));
|
||||
infoBuilder.append("\n");
|
||||
logger.debug("Checking game: {}", sql);
|
||||
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
rs.next();
|
||||
if (rs.getInt(1) == 0)
|
||||
{
|
||||
infoBuilder.append("Not available adding to db\n");
|
||||
logger.debug("Game: {} is not available, adding to db", splittedRowValue[0]);
|
||||
newRowValues.add(rowValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBuilder.append("Already available, skipping\n");
|
||||
logger.debug("Game: {} is already available, skipping.", splittedRowValue[0]);
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
infoBuilder.append("Could not insert games in db.\n");
|
||||
ExceptionHandler.handleException(e, "Could not insert games in db.");
|
||||
}
|
||||
}
|
||||
|
||||
if (newRowValues.size() > 0)
|
||||
{
|
||||
insertAllIntoGameInfoTable(newRowValues, infoBuilder);
|
||||
}
|
||||
//Replace content of rowValues with the ones that was added. Only look at these in the next step of the import
|
||||
rowValues.clear();
|
||||
rowValues.addAll(newRowValues);
|
||||
}
|
||||
|
||||
private void insertAllIntoGameInfoTable(List<String> rowValues, StringBuilder infoBuilder)
|
||||
{
|
||||
infoBuilder.append("Adding ");
|
||||
infoBuilder.append(rowValues.size());
|
||||
infoBuilder.append(" games to the db\n");
|
||||
|
||||
StringBuilder st = new StringBuilder();
|
||||
st.append("INSERT INTO gameinfo (");
|
||||
for (String column : columnList)
|
||||
{
|
||||
st.append(column);
|
||||
st.append(",");
|
||||
}
|
||||
st.delete(st.length() - 1, st.length());
|
||||
st.append(") VALUES (");
|
||||
|
||||
for (String rowData : rowValues)
|
||||
{
|
||||
st.append(rowData);
|
||||
st.append("),(");
|
||||
}
|
||||
st.delete(st.length() - 3, st.length());
|
||||
st.append(");");
|
||||
String sql = st.toString();
|
||||
logger.debug("Generated INSERT String:\n{}", sql);
|
||||
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
int value = pstmt.executeUpdate();
|
||||
logger.debug("Executed successfully, value = {}", value);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
infoBuilder.append("Could not insert games in db.\n");
|
||||
ExceptionHandler.handleException(e, "Could not insert games in db.");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAllInGameInfoTable(List<String> rowValues)
|
||||
{
|
||||
for (String rowValue : rowValues)
|
||||
{
|
||||
List<String> splittedRowValueList = Arrays.asList(rowValue.split("\",\""));
|
||||
String title = splittedRowValueList.get(0);
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("UPDATE gameinfo SET ");
|
||||
for (int i = 1; i < columnList.size(); i++)
|
||||
{
|
||||
sqlBuilder.append(columnList.get(i));
|
||||
sqlBuilder.append(" = ");
|
||||
if (i > 1)
|
||||
{
|
||||
sqlBuilder.append("\"");
|
||||
}
|
||||
|
||||
sqlBuilder.append(splittedRowValueList.get(i));
|
||||
if (i < columnList.size() - 1)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
sqlBuilder.append(",");
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlBuilder.append("\",");
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlBuilder.append(" WHERE title = ");
|
||||
sqlBuilder.append(title);
|
||||
sqlBuilder.append("\";");
|
||||
String sql = sqlBuilder.toString();
|
||||
logger.debug("Generated UPDATE String:\n{}", sql);
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
int value = pstmt.executeUpdate();
|
||||
logger.debug("Executed successfully, value = {}", value);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not insert games in db.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns GameDetails for the currently selected game
|
||||
*
|
||||
* @param gameId The id of the current game
|
||||
* @return A GameDetails object.
|
||||
*/
|
||||
public GameDetails getGameDetails(String gameId)
|
||||
{
|
||||
String sql = "SELECT * FROM gameinfo WHERE rowid = " + gameId;
|
||||
logger.debug("Generated SELECT String:\n{}", sql);
|
||||
GameDetails returnValue = new GameDetails();
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
returnValue.setTitle(rs.getString(DbConstants.TITLE));
|
||||
returnValue.setYear(rs.getInt(DbConstants.YEAR));
|
||||
returnValue.setAuthor(rs.getString(DbConstants.AUTHOR));
|
||||
returnValue.setComposer(rs.getString(DbConstants.COMPOSER));
|
||||
returnValue.setGenre(rs.getString(DbConstants.GENRE));
|
||||
returnValue.setDescription(rs.getString(DbConstants.DESC));
|
||||
returnValue.setGame(rs.getString(DbConstants.GAME));
|
||||
returnValue.setCover(rs.getString(DbConstants.COVER));
|
||||
returnValue.setScreen1(rs.getString(DbConstants.SCREEN1));
|
||||
returnValue.setScreen2(rs.getString(DbConstants.SCREEN2));
|
||||
returnValue.setJoy1(rs.getString(DbConstants.JOY1));
|
||||
returnValue.setJoy2(rs.getString(DbConstants.JOY2));
|
||||
returnValue.setSystem(rs.getString(DbConstants.SYSTEM));
|
||||
logger.debug("SELECT Executed successfully");
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not fetch game details.");
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public boolean isGameInDb(String title)
|
||||
{
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT COUNT(*) FROM gameinfo WHERE title LIKE \"");
|
||||
sqlBuilder.append(title);
|
||||
sqlBuilder.append("\";");
|
||||
String sql = sqlBuilder.toString();
|
||||
logger.debug("Checking if game is in db already: {}", sql);
|
||||
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
rs.next();
|
||||
return rs.getInt(1) > 0;
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not check for duplicate in db.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int createNewGame(GameDetails details)
|
||||
{
|
||||
int rowId = 0;
|
||||
StringBuilder st = new StringBuilder();
|
||||
st.append("INSERT INTO gameinfo (");
|
||||
for (String column : columnList)
|
||||
{
|
||||
st.append(column);
|
||||
st.append(",");
|
||||
}
|
||||
st.delete(st.length() - 1, st.length());
|
||||
st.append(") VALUES (\"");
|
||||
|
||||
st.append(details.getTitle());
|
||||
st.append("\",");
|
||||
st.append(details.getYear());
|
||||
st.append(",\"");
|
||||
st.append(details.getAuthor());
|
||||
st.append("\",\"");
|
||||
st.append(details.getComposer());
|
||||
st.append("\",\"");
|
||||
st.append(details.getGenre());
|
||||
st.append("\",\"");
|
||||
st.append(details.getDescription());
|
||||
st.append("\",\"");
|
||||
st.append(details.getGame());
|
||||
st.append("\",\"");
|
||||
st.append(details.getCover());
|
||||
st.append("\",\"");
|
||||
st.append(details.getScreen1());
|
||||
st.append("\",\"");
|
||||
st.append(details.getScreen2());
|
||||
st.append("\",\"");
|
||||
st.append(details.getJoy1());
|
||||
st.append("\",\"");
|
||||
st.append(details.getJoy2());
|
||||
st.append("\",\"");
|
||||
st.append(details.getSystem());
|
||||
st.append("\");");
|
||||
|
||||
String sql = st.toString();
|
||||
logger.debug("Generated INSERT String:\n{}", sql);
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
int value = pstmt.executeUpdate();
|
||||
ResultSet result = pstmt.getGeneratedKeys();
|
||||
if (result.next())
|
||||
{
|
||||
rowId = result.getInt(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.error("Unexpected result of insert");
|
||||
return -1;
|
||||
}
|
||||
logger.debug("Executed successfully, value = {}", value);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not insert games in db.");
|
||||
}
|
||||
return rowId;
|
||||
}
|
||||
|
||||
public void saveGame(String rowId, GameDetails details)
|
||||
{
|
||||
columnList.add(DbConstants.TITLE);
|
||||
columnList.add(DbConstants.YEAR);
|
||||
columnList.add(DbConstants.AUTHOR);
|
||||
columnList.add(DbConstants.COMPOSER);
|
||||
columnList.add(DbConstants.GENRE);
|
||||
columnList.add(DbConstants.DESC);
|
||||
columnList.add(DbConstants.GAME);
|
||||
columnList.add(DbConstants.COVER);
|
||||
columnList.add(DbConstants.SCREEN1);
|
||||
columnList.add(DbConstants.SCREEN2);
|
||||
columnList.add(DbConstants.JOY1);
|
||||
columnList.add(DbConstants.JOY2);
|
||||
columnList.add(DbConstants.SYSTEM);
|
||||
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("UPDATE gameinfo SET ");
|
||||
|
||||
sqlBuilder.append(DbConstants.TITLE);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getTitle());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.YEAR);
|
||||
sqlBuilder.append("=");
|
||||
sqlBuilder.append(details.getYear());
|
||||
sqlBuilder.append(",");
|
||||
sqlBuilder.append(DbConstants.AUTHOR);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getAuthor());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.COMPOSER);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getComposer());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.GENRE);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getGenre());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.DESC);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getDescription());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.GAME);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getGame());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.COVER);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getCover());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.SCREEN1);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getScreen1());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.SCREEN2);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getScreen2());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.JOY1);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getJoy1());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.JOY2);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getJoy2());
|
||||
sqlBuilder.append("\",");
|
||||
sqlBuilder.append(DbConstants.SYSTEM);
|
||||
sqlBuilder.append("=\"");
|
||||
sqlBuilder.append(details.getSystem());
|
||||
sqlBuilder.append("\" WHERE rowId = ");
|
||||
sqlBuilder.append(rowId);
|
||||
sqlBuilder.append(";");
|
||||
|
||||
String sql = sqlBuilder.toString();
|
||||
logger.debug("Generated UPDATE String:\n{}", sql);
|
||||
try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql))
|
||||
{
|
||||
int value = pstmt.executeUpdate();
|
||||
logger.debug("Executed successfully, value = {}", value);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not insert games in db.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
public class BaseDialog extends JDialog
|
||||
{
|
||||
private JPanel backgroundPanel;
|
||||
private JPanel buttonPanel;
|
||||
private JButton okButton;
|
||||
private JButton cancelButton;
|
||||
|
||||
KeyStroke escKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
|
||||
|
||||
Action escAction = new AbstractAction()
|
||||
{
|
||||
private static final long serialVersionUID = 1756396251349970052L;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
okPressed = false;
|
||||
setVisible(false);
|
||||
}
|
||||
};
|
||||
private boolean okPressed = false;
|
||||
|
||||
public BaseDialog(Frame owner)
|
||||
{
|
||||
super(owner, true);
|
||||
this.setIconImage(new ImageIcon(getClass().getResource("/se/lantz/FrameIcon.png")).getImage());
|
||||
getContentPane().add(getBackgroundPanel(), BorderLayout.CENTER);
|
||||
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
//Register esc as closing the window
|
||||
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escKeyStroke, "closeDialog");
|
||||
getRootPane().getActionMap().put("closeDialog", escAction);
|
||||
}
|
||||
|
||||
protected void addContent(JPanel panel)
|
||||
{
|
||||
getBackgroundPanel().add(panel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private JPanel getBackgroundPanel()
|
||||
{
|
||||
if (backgroundPanel == null)
|
||||
{
|
||||
backgroundPanel = new JPanel();
|
||||
backgroundPanel.setLayout(new BorderLayout(0, 0));
|
||||
backgroundPanel.add(getButtonPanel(), BorderLayout.SOUTH);
|
||||
}
|
||||
return backgroundPanel;
|
||||
}
|
||||
|
||||
private JPanel getButtonPanel()
|
||||
{
|
||||
if (buttonPanel == null)
|
||||
{
|
||||
buttonPanel = new JPanel();
|
||||
GridBagLayout gbl_buttonPanel = new GridBagLayout();
|
||||
gbl_buttonPanel.columnWidths = new int[] { 0, 0, 0 };
|
||||
gbl_buttonPanel.rowHeights = new int[] { 0, 0 };
|
||||
gbl_buttonPanel.columnWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
|
||||
gbl_buttonPanel.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
|
||||
buttonPanel.setLayout(gbl_buttonPanel);
|
||||
GridBagConstraints gbc_okButton = new GridBagConstraints();
|
||||
gbc_okButton.anchor = GridBagConstraints.EAST;
|
||||
gbc_okButton.weightx = 0.5;
|
||||
gbc_okButton.insets = new Insets(5, 5, 5, 5);
|
||||
gbc_okButton.gridx = 0;
|
||||
gbc_okButton.gridy = 0;
|
||||
buttonPanel.add(getOkButton(), gbc_okButton);
|
||||
GridBagConstraints gbc_cancelButton = new GridBagConstraints();
|
||||
gbc_cancelButton.weightx = 0.5;
|
||||
gbc_cancelButton.insets = new Insets(5, 5, 5, 5);
|
||||
gbc_cancelButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_cancelButton.gridx = 1;
|
||||
gbc_cancelButton.gridy = 0;
|
||||
buttonPanel.add(getCancelButton(), gbc_cancelButton);
|
||||
}
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
protected JButton getOkButton()
|
||||
{
|
||||
if (okButton == null)
|
||||
{
|
||||
okButton = new JButton("OK");
|
||||
okButton.addActionListener(e -> {
|
||||
okPressed = true;
|
||||
setVisible(false);
|
||||
});
|
||||
okButton.setPreferredSize(getCancelButton().getPreferredSize());
|
||||
}
|
||||
return okButton;
|
||||
}
|
||||
|
||||
protected JButton getCancelButton()
|
||||
{
|
||||
if (cancelButton == null)
|
||||
{
|
||||
cancelButton = new JButton("Cancel");
|
||||
cancelButton.addActionListener(e -> {
|
||||
okPressed = false;
|
||||
setVisible(false);
|
||||
});
|
||||
}
|
||||
return cancelButton;
|
||||
}
|
||||
|
||||
public boolean showDialog()
|
||||
{
|
||||
this.setVisible(true);
|
||||
return okPressed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import se.lantz.model.MainViewModel;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
import java.beans.Beans;
|
||||
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
public class CombinedJoystickPanel extends JPanel
|
||||
{
|
||||
private JoystickPanel port1Panel;
|
||||
private JoystickPanel port2Panel;
|
||||
private MainViewModel model;
|
||||
|
||||
public CombinedJoystickPanel(MainViewModel model)
|
||||
{
|
||||
setBorder(new TitledBorder(null, "Joystick configuration", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
this.model = model;
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_port1Panel = new GridBagConstraints();
|
||||
gbc_port1Panel.weighty = 1.0;
|
||||
gbc_port1Panel.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_port1Panel.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_port1Panel.gridx = 0;
|
||||
gbc_port1Panel.gridy = 0;
|
||||
add(getPort1Panel(), gbc_port1Panel);
|
||||
GridBagConstraints gbc_port2Panel = new GridBagConstraints();
|
||||
gbc_port2Panel.weighty = 1.0;
|
||||
gbc_port2Panel.weightx = 1.0;
|
||||
gbc_port2Panel.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_port2Panel.gridx = 1;
|
||||
gbc_port2Panel.gridy = 0;
|
||||
add(getPort2Panel(), gbc_port2Panel);
|
||||
}
|
||||
|
||||
private JoystickPanel getPort1Panel()
|
||||
{
|
||||
if (port1Panel == null)
|
||||
{
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
port1Panel = new JoystickPanel(1, model.getJoy1Model());
|
||||
}
|
||||
else
|
||||
{
|
||||
port1Panel = new JoystickPanel(1, null);
|
||||
}
|
||||
}
|
||||
return port1Panel;
|
||||
}
|
||||
|
||||
private JoystickPanel getPort2Panel()
|
||||
{
|
||||
if (port2Panel == null)
|
||||
{
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
port2Panel = new JoystickPanel(2, model.getJoy2Model());
|
||||
}
|
||||
else
|
||||
{
|
||||
port2Panel = new JoystickPanel(2, null);
|
||||
}
|
||||
}
|
||||
return port2Panel;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
public class DisplayShiftComboBox extends JComboBox<String>
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 8793039092191107043L;
|
||||
|
||||
public DisplayShiftComboBox()
|
||||
{
|
||||
setup64Items();
|
||||
setSelectedItem("0");
|
||||
}
|
||||
|
||||
void setup64Items()
|
||||
{
|
||||
String selected = null;
|
||||
if (getSelectedItem() != null && !getSelectedItem().equals("-16"))
|
||||
{
|
||||
selected = getSelectedItem().toString();
|
||||
}
|
||||
this.removeAllItems();
|
||||
for (int i = -15; i < 18; i++)
|
||||
{
|
||||
this.addItem(Integer.toString(i));
|
||||
}
|
||||
if (selected != null)
|
||||
{
|
||||
setSelectedItem(selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSelectedItem("0");
|
||||
}
|
||||
}
|
||||
|
||||
void setupVic20Items()
|
||||
{
|
||||
String selected = null;
|
||||
if (getSelectedItem() != null && !getSelectedItem().equals("17"))
|
||||
{
|
||||
selected = getSelectedItem().toString();
|
||||
}
|
||||
this.removeAllItems();
|
||||
for (int i = -16; i < 17; i++)
|
||||
{
|
||||
this.addItem(Integer.toString(i));
|
||||
}
|
||||
if (selected != null)
|
||||
{
|
||||
setSelectedItem(selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSelectedItem("0");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.Toolkit;
|
||||
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.DocumentFilter;
|
||||
|
||||
public class DocumentSizeFilter extends DocumentFilter
|
||||
{
|
||||
int maxCharacters;
|
||||
boolean DEBUG = false;
|
||||
|
||||
public DocumentSizeFilter(int maxChars)
|
||||
{
|
||||
maxCharacters = maxChars;
|
||||
}
|
||||
|
||||
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a) throws BadLocationException
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println("in DocumentSizeFilter's insertString method");
|
||||
}
|
||||
|
||||
//This rejects the entire insertion if it would make
|
||||
//the contents too long. Another option would be
|
||||
//to truncate the inserted string so the contents
|
||||
//would be exactly maxCharacters in length.
|
||||
if ((fb.getDocument().getLength() + str.length()) <= maxCharacters)
|
||||
super.insertString(fb, offs, str, a);
|
||||
else
|
||||
Toolkit.getDefaultToolkit().beep();
|
||||
}
|
||||
|
||||
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a) throws BadLocationException
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println("in DocumentSizeFilter's replace method");
|
||||
}
|
||||
//This rejects the entire replacement if it would make
|
||||
//the contents too long. Another option would be
|
||||
//to truncate the replacement string so the contents
|
||||
//would be exactly maxCharacters in length.
|
||||
if ((fb.getDocument().getLength() + str.length() - length) <= maxCharacters)
|
||||
super.replace(fb, offs, length, str, a);
|
||||
else
|
||||
Toolkit.getDefaultToolkit().beep();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.beans.Beans;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.data.GameListData;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
public class GameDetailsBackgroundPanel extends JPanel
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(GameDetailsBackgroundPanel.class);
|
||||
private MainViewModel model;
|
||||
private JPanel settingsPanel;
|
||||
private InfoPanel infoPanel;
|
||||
private CombinedJoystickPanel joystickPanel;
|
||||
private SystemPanel systemPanel;
|
||||
private JPanel buttonPanel;
|
||||
private JButton saveButton;
|
||||
|
||||
public GameDetailsBackgroundPanel(MainViewModel model)
|
||||
{
|
||||
this.model = model;
|
||||
this.setMinimumSize(new Dimension(1250, 800));
|
||||
setLayout(new BorderLayout(0, 0));
|
||||
add(getSettingsPanel(), BorderLayout.CENTER);
|
||||
add(getInfoPanel(), BorderLayout.NORTH);
|
||||
add(getButtonPanel(), BorderLayout.SOUTH);
|
||||
|
||||
}
|
||||
|
||||
void focusTitleField()
|
||||
{
|
||||
getInfoPanel().focusTitleField();
|
||||
}
|
||||
|
||||
void updateSelectedGame(GameListData data)
|
||||
{
|
||||
if (data != null)
|
||||
{
|
||||
model.readGameDetails(data);
|
||||
}
|
||||
}
|
||||
|
||||
private JPanel getSettingsPanel()
|
||||
{
|
||||
if (settingsPanel == null)
|
||||
{
|
||||
settingsPanel = new JPanel();
|
||||
GridBagLayout gbl_settingsPanel = new GridBagLayout();
|
||||
settingsPanel.setLayout(gbl_settingsPanel);
|
||||
GridBagConstraints gbc_systemPanel = new GridBagConstraints();
|
||||
gbc_systemPanel.weightx = 1.0;
|
||||
gbc_systemPanel.weighty = 1.0;
|
||||
gbc_systemPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_systemPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_systemPanel.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_systemPanel.gridx = 1;
|
||||
gbc_systemPanel.gridy = 0;
|
||||
settingsPanel.add(getSystemPanel(), gbc_systemPanel);
|
||||
GridBagConstraints gbc_joystickPanel = new GridBagConstraints();
|
||||
gbc_joystickPanel.insets = new Insets(0, 10, 0, 0);
|
||||
gbc_joystickPanel.weighty = 1.0;
|
||||
gbc_joystickPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_joystickPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_joystickPanel.gridx = 0;
|
||||
gbc_joystickPanel.gridy = 0;
|
||||
settingsPanel.add(getCombinedJoystickPanel(), gbc_joystickPanel);
|
||||
}
|
||||
return settingsPanel;
|
||||
}
|
||||
|
||||
private InfoPanel getInfoPanel()
|
||||
{
|
||||
if (infoPanel == null)
|
||||
{
|
||||
infoPanel = new InfoPanel(model.getInfoModel());
|
||||
}
|
||||
return infoPanel;
|
||||
}
|
||||
|
||||
private CombinedJoystickPanel getCombinedJoystickPanel()
|
||||
{
|
||||
if (joystickPanel == null)
|
||||
{
|
||||
joystickPanel = new CombinedJoystickPanel(model);
|
||||
}
|
||||
return joystickPanel;
|
||||
}
|
||||
|
||||
private SystemPanel getSystemPanel()
|
||||
{
|
||||
if (systemPanel == null)
|
||||
{
|
||||
systemPanel = new SystemPanel();
|
||||
systemPanel
|
||||
.setBorder(new TitledBorder(null, "System Settings", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
}
|
||||
return systemPanel;
|
||||
}
|
||||
|
||||
private JPanel getButtonPanel()
|
||||
{
|
||||
if (buttonPanel == null)
|
||||
{
|
||||
buttonPanel = new JPanel();
|
||||
GridBagLayout gbl_buttonPanel = new GridBagLayout();
|
||||
gbl_buttonPanel.columnWidths = new int[] { 0, 0 };
|
||||
gbl_buttonPanel.rowHeights = new int[] { 0, 0 };
|
||||
gbl_buttonPanel.columnWeights = new double[] { 0.0, Double.MIN_VALUE };
|
||||
gbl_buttonPanel.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
|
||||
buttonPanel.setLayout(gbl_buttonPanel);
|
||||
GridBagConstraints gbc_saveButton = new GridBagConstraints();
|
||||
gbc_saveButton.weighty = 1.0;
|
||||
gbc_saveButton.weightx = 1.0;
|
||||
gbc_saveButton.anchor = GridBagConstraints.SOUTHEAST;
|
||||
gbc_saveButton.insets = new Insets(5, 5, 5, 6);
|
||||
gbc_saveButton.gridx = 0;
|
||||
gbc_saveButton.gridy = 0;
|
||||
buttonPanel.add(getSaveButton(), gbc_saveButton);
|
||||
}
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private JButton getSaveButton()
|
||||
{
|
||||
if (saveButton == null)
|
||||
{
|
||||
model.addSaveChangeListener(e -> {
|
||||
logger.debug("SaveButton isDataChanged = {}", model.isDataChanged());
|
||||
saveButton.setEnabled(model.isDataChanged());
|
||||
});
|
||||
saveButton = new JButton("Save");
|
||||
saveButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
model.saveData();
|
||||
}
|
||||
});
|
||||
}
|
||||
return saveButton;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
public class GenreComboBox extends JComboBox<String>
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 8793039092191107043L;
|
||||
|
||||
Map<String, String> valueMap = new HashMap<>();
|
||||
|
||||
public GenreComboBox()
|
||||
{
|
||||
setupItems();
|
||||
}
|
||||
|
||||
private void setupItems()
|
||||
{
|
||||
this.addItem("Adventure");
|
||||
this.addItem("Driving");
|
||||
this.addItem("Maze");
|
||||
this.addItem("Platform");
|
||||
this.addItem("Programming");
|
||||
this.addItem("Puzzle");
|
||||
this.addItem("Shoot'em up");
|
||||
this.addItem("Simulation");
|
||||
this.addItem("Sport");
|
||||
|
||||
valueMap.put("", "----");
|
||||
valueMap.put("adventure", "Adventure");
|
||||
valueMap.put("driving", "Driving");
|
||||
valueMap.put("maze", "Maze");
|
||||
valueMap.put("platform", "Platform");
|
||||
valueMap.put("programming", "Programming");
|
||||
valueMap.put("puzzle", "Puzzle");
|
||||
valueMap.put("shoot", "Shoot'em up");
|
||||
valueMap.put("simulation", "Simulation");
|
||||
valueMap.put("sport", "Sport");
|
||||
}
|
||||
|
||||
public void setSelectedGenre(String genre)
|
||||
{
|
||||
String item = valueMap.get(genre);
|
||||
if (item != null)
|
||||
{
|
||||
this.setSelectedItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.addItem(genre);
|
||||
this.setSelectedItem(genre);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSelectedGenre()
|
||||
{
|
||||
for (Entry<String, String> entry : valueMap.entrySet())
|
||||
{
|
||||
if (Objects.equals(getSelectedItem(), entry.getValue()))
|
||||
{
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return getSelectedItem().toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,428 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.beans.Beans;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.text.DefaultStyledDocument;
|
||||
|
||||
import se.lantz.model.InfoModel;
|
||||
|
||||
public class InfoPanel extends JPanel
|
||||
{
|
||||
private InfoModel model;
|
||||
private JPanel textPanel;
|
||||
private JPanel settingsPanel;
|
||||
private JLabel titleLabel;
|
||||
private JTextField titleField;
|
||||
private JLabel authorLabel;
|
||||
private JTextField authorField;
|
||||
private JLabel composerLabel;
|
||||
private JTextField composerField;
|
||||
private JLabel yearLabel;
|
||||
private JTextField yearField;
|
||||
private JLabel genreLabel;
|
||||
private GenreComboBox genreComboBox;
|
||||
private JLabel descriptionLabel;
|
||||
private JScrollPane descriptionScrollPane;
|
||||
private JTextArea descriptionTextArea;
|
||||
private ScreenshotsPanel screensPanel;
|
||||
private JLabel charCountLabel;
|
||||
|
||||
public InfoPanel(InfoModel model)
|
||||
{
|
||||
this.model = model;
|
||||
this.setPreferredSize(new Dimension(729, 330));
|
||||
GridBagLayout gbl_this = new GridBagLayout();
|
||||
this.setLayout(gbl_this);
|
||||
GridBagConstraints gbc_titleLabel = new GridBagConstraints();
|
||||
gbc_titleLabel.gridwidth = 2;
|
||||
gbc_titleLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_titleLabel.insets = new Insets(10, 10, 0, 5);
|
||||
gbc_titleLabel.gridx = 0;
|
||||
gbc_titleLabel.gridy = 0;
|
||||
this.add(getTitleLabel(), gbc_titleLabel);
|
||||
GridBagConstraints gbc_titleField = new GridBagConstraints();
|
||||
gbc_titleField.gridwidth = 2;
|
||||
gbc_titleField.insets = new Insets(0, 10, 5, 5);
|
||||
gbc_titleField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_titleField.gridx = 0;
|
||||
gbc_titleField.gridy = 1;
|
||||
this.add(getTitleField(), gbc_titleField);
|
||||
GridBagConstraints gbc_yearField = new GridBagConstraints();
|
||||
gbc_yearField.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_yearField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_yearField.gridx = 2;
|
||||
gbc_yearField.gridy = 1;
|
||||
this.add(getYearField(), gbc_yearField);
|
||||
GridBagConstraints gbc_authorLabel = new GridBagConstraints();
|
||||
gbc_authorLabel.gridwidth = 2;
|
||||
gbc_authorLabel.insets = new Insets(0, 10, 0, 5);
|
||||
gbc_authorLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_authorLabel.gridx = 0;
|
||||
gbc_authorLabel.gridy = 2;
|
||||
this.add(getAuthorLabel(), gbc_authorLabel);
|
||||
GridBagConstraints gbc_genreLabel = new GridBagConstraints();
|
||||
gbc_genreLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_genreLabel.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_genreLabel.gridx = 2;
|
||||
gbc_genreLabel.gridy = 2;
|
||||
this.add(getGenreLabel(), gbc_genreLabel);
|
||||
GridBagConstraints gbc_authorField = new GridBagConstraints();
|
||||
gbc_authorField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_authorField.anchor = GridBagConstraints.WEST;
|
||||
gbc_authorField.gridwidth = 2;
|
||||
gbc_authorField.insets = new Insets(0, 10, 5, 100);
|
||||
gbc_authorField.gridx = 0;
|
||||
gbc_authorField.gridy = 3;
|
||||
this.add(getAuthorField(), gbc_authorField);
|
||||
GridBagConstraints gbc_composerLabel = new GridBagConstraints();
|
||||
gbc_composerLabel.gridwidth = 2;
|
||||
gbc_composerLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_composerLabel.insets = new Insets(0, 10, 0, 5);
|
||||
gbc_composerLabel.gridx = 0;
|
||||
gbc_composerLabel.gridy = 4;
|
||||
this.add(getComposerLabel(), gbc_composerLabel);
|
||||
GridBagConstraints gbc_composerField = new GridBagConstraints();
|
||||
gbc_composerField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_composerField.anchor = GridBagConstraints.WEST;
|
||||
gbc_composerField.gridwidth = 2;
|
||||
gbc_composerField.insets = new Insets(0, 10, 5, 100);
|
||||
gbc_composerField.gridx = 0;
|
||||
gbc_composerField.gridy = 5;
|
||||
this.add(getComposerField(), gbc_composerField);
|
||||
GridBagConstraints gbc_yearLabel = new GridBagConstraints();
|
||||
gbc_yearLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_yearLabel.insets = new Insets(10, 0, 0, 5);
|
||||
gbc_yearLabel.gridx = 2;
|
||||
gbc_yearLabel.gridy = 0;
|
||||
this.add(getYearLabel(), gbc_yearLabel);
|
||||
GridBagConstraints gbc_genreComboBox = new GridBagConstraints();
|
||||
gbc_genreComboBox.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_genreComboBox.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_genreComboBox.gridx = 2;
|
||||
gbc_genreComboBox.gridy = 3;
|
||||
this.add(getGenreComboBox(), gbc_genreComboBox);
|
||||
GridBagConstraints gbc_descriptionLabel = new GridBagConstraints();
|
||||
gbc_descriptionLabel.gridwidth = 2;
|
||||
gbc_descriptionLabel.insets = new Insets(0, 10, 0, 5);
|
||||
gbc_descriptionLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_descriptionLabel.gridx = 0;
|
||||
gbc_descriptionLabel.gridy = 6;
|
||||
this.add(getDescriptionLabel(), gbc_descriptionLabel);
|
||||
GridBagConstraints gbc_descriptionScrollPane = new GridBagConstraints();
|
||||
gbc_descriptionScrollPane.anchor = GridBagConstraints.NORTH;
|
||||
gbc_descriptionScrollPane.gridwidth = 2;
|
||||
gbc_descriptionScrollPane.insets = new Insets(0, 10, 0, 5);
|
||||
gbc_descriptionScrollPane.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_descriptionScrollPane.gridx = 0;
|
||||
gbc_descriptionScrollPane.gridy = 7;
|
||||
this.add(getDescriptionScrollPane(), gbc_descriptionScrollPane);
|
||||
GridBagConstraints gbc_screensPanel = new GridBagConstraints();
|
||||
gbc_screensPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_screensPanel.weighty = 1.0;
|
||||
gbc_screensPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_screensPanel.weightx = 1.0;
|
||||
gbc_screensPanel.insets = new Insets(0, 10, 0, 0);
|
||||
gbc_screensPanel.gridheight = 9;
|
||||
gbc_screensPanel.gridx = 3;
|
||||
gbc_screensPanel.gridy = 0;
|
||||
this.add(getScreensPanel(), gbc_screensPanel);
|
||||
GridBagConstraints gbc_charCountLabel = new GridBagConstraints();
|
||||
gbc_charCountLabel.gridwidth = 2;
|
||||
gbc_charCountLabel.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_charCountLabel.insets = new Insets(5, 10, 0, 5);
|
||||
gbc_charCountLabel.gridx = 0;
|
||||
gbc_charCountLabel.gridy = 8;
|
||||
add(getCharCountLabel(), gbc_charCountLabel);
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
model.addPropertyChangeListener((e) -> modelChanged());
|
||||
}
|
||||
}
|
||||
|
||||
// private void initFont()
|
||||
// {
|
||||
// try {
|
||||
// c64Font = Font.createFont(Font.TRUETYPE_FONT, getClass().getResource("/se/lantz/C64_Pro-STYLE.ttf").openStream());
|
||||
// GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
// genv.registerFont(c64Font);
|
||||
// // makesure to derive the size
|
||||
// c64Font = c64Font.deriveFont(12f);
|
||||
// } catch (FontFormatException | IOException e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
private void modelChanged()
|
||||
{
|
||||
// Read from model
|
||||
getTitleField().setText(model.getTitle());
|
||||
getDescriptionTextArea().setText(model.getDescription());
|
||||
getYearField().setText(Integer.toString(model.getYear()));
|
||||
getGenreComboBox().setSelectedGenre(model.getGenre());
|
||||
getAuthorField().setText(model.getAuthor());
|
||||
getComposerField().setText(model.getComposer());
|
||||
}
|
||||
|
||||
private JPanel getSettingsPanel()
|
||||
{
|
||||
if (settingsPanel == null)
|
||||
{
|
||||
settingsPanel = new JPanel();
|
||||
settingsPanel.setLayout(new BorderLayout(0, 0));
|
||||
}
|
||||
return settingsPanel;
|
||||
}
|
||||
|
||||
private JLabel getTitleLabel()
|
||||
{
|
||||
if (titleLabel == null)
|
||||
{
|
||||
titleLabel = new JLabel("Game title");
|
||||
}
|
||||
return titleLabel;
|
||||
}
|
||||
|
||||
private JTextField getTitleField()
|
||||
{
|
||||
if (titleField == null)
|
||||
{
|
||||
titleField = new JTextField();
|
||||
titleField.setColumns(10);
|
||||
titleField.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
JTextField textField = (JTextField) e.getSource();
|
||||
model.setTitle(textField.getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
return titleField;
|
||||
}
|
||||
|
||||
private JLabel getAuthorLabel()
|
||||
{
|
||||
if (authorLabel == null)
|
||||
{
|
||||
authorLabel = new JLabel("Author");
|
||||
authorLabel.setPreferredSize(new Dimension(145, 14));
|
||||
}
|
||||
return authorLabel;
|
||||
}
|
||||
|
||||
private JTextField getAuthorField()
|
||||
{
|
||||
if (authorField == null)
|
||||
{
|
||||
authorField = new JTextField();
|
||||
authorField.setPreferredSize(new Dimension(300, 20));
|
||||
authorField.setColumns(10);
|
||||
authorField.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
JTextField textField = (JTextField) e.getSource();
|
||||
model.setAuthor(textField.getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
return authorField;
|
||||
}
|
||||
|
||||
private JLabel getComposerLabel()
|
||||
{
|
||||
if (composerLabel == null)
|
||||
{
|
||||
composerLabel = new JLabel("Composer");
|
||||
composerLabel.setPreferredSize(new Dimension(140, 14));
|
||||
}
|
||||
return composerLabel;
|
||||
}
|
||||
|
||||
private JTextField getComposerField()
|
||||
{
|
||||
if (composerField == null)
|
||||
{
|
||||
composerField = new JTextField();
|
||||
composerField.setPreferredSize(new Dimension(200, 20));
|
||||
composerField.setColumns(10);
|
||||
composerField.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
JTextField textField = (JTextField) e.getSource();
|
||||
model.setComposer(textField.getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
return composerField;
|
||||
}
|
||||
|
||||
private JLabel getYearLabel()
|
||||
{
|
||||
if (yearLabel == null)
|
||||
{
|
||||
yearLabel = new JLabel("Year");
|
||||
}
|
||||
return yearLabel;
|
||||
}
|
||||
|
||||
private JTextField getYearField()
|
||||
{
|
||||
if (yearField == null)
|
||||
{
|
||||
yearField = new JTextField();
|
||||
yearField.setColumns(10);
|
||||
yearField.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
JTextField textField = (JTextField) e.getSource();
|
||||
model.setYear(Integer.parseInt(textField.getText()));
|
||||
}
|
||||
});
|
||||
}
|
||||
return yearField;
|
||||
}
|
||||
|
||||
private JLabel getGenreLabel()
|
||||
{
|
||||
if (genreLabel == null)
|
||||
{
|
||||
genreLabel = new JLabel("Genre");
|
||||
}
|
||||
return genreLabel;
|
||||
}
|
||||
|
||||
private GenreComboBox getGenreComboBox()
|
||||
{
|
||||
if (genreComboBox == null)
|
||||
{
|
||||
genreComboBox = new GenreComboBox();
|
||||
genreComboBox.addActionListener((e) -> model.setGenre((String)genreComboBox.getSelectedGenre()));
|
||||
}
|
||||
return genreComboBox;
|
||||
}
|
||||
|
||||
private JLabel getDescriptionLabel()
|
||||
{
|
||||
if (descriptionLabel == null)
|
||||
{
|
||||
descriptionLabel = new JLabel("Description");
|
||||
}
|
||||
return descriptionLabel;
|
||||
}
|
||||
|
||||
private JScrollPane getDescriptionScrollPane()
|
||||
{
|
||||
if (descriptionScrollPane == null)
|
||||
{
|
||||
descriptionScrollPane = new JScrollPane();
|
||||
descriptionScrollPane.setPreferredSize(new Dimension(290, 150));
|
||||
descriptionScrollPane.setViewportView(getDescriptionTextArea());
|
||||
}
|
||||
return descriptionScrollPane;
|
||||
}
|
||||
|
||||
private JTextArea getDescriptionTextArea()
|
||||
{
|
||||
if (descriptionTextArea == null)
|
||||
{
|
||||
descriptionTextArea = new JTextArea();
|
||||
descriptionTextArea.setFont(getTitleField().getFont());
|
||||
descriptionTextArea.setWrapStyleWord(true);
|
||||
descriptionTextArea.setLineWrap(true);
|
||||
|
||||
DefaultStyledDocument doc = new DefaultStyledDocument();
|
||||
doc.addDocumentListener(new DocumentListener()
|
||||
{
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e)
|
||||
{
|
||||
updateDescriptionCharCount(e.getDocument().getLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e)
|
||||
{
|
||||
updateDescriptionCharCount(e.getDocument().getLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e)
|
||||
{
|
||||
updateDescriptionCharCount(e.getDocument().getLength());
|
||||
}
|
||||
});
|
||||
descriptionTextArea.setDocument(doc);
|
||||
getCharCountLabel()
|
||||
.setToolTipText("<html>The Carousel description screen can only show a limited number of characters.<br>Consider limiting the text to 512 characters at the most.</html>");
|
||||
|
||||
updateDescriptionCharCount(doc.getLength());
|
||||
|
||||
descriptionTextArea.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
JTextArea textField = (JTextArea) e.getSource();
|
||||
model.setDescription(textField.getText());
|
||||
}
|
||||
});
|
||||
}
|
||||
return descriptionTextArea;
|
||||
}
|
||||
|
||||
private ScreenshotsPanel getScreensPanel()
|
||||
{
|
||||
if (screensPanel == null)
|
||||
{
|
||||
screensPanel = new ScreenshotsPanel(this.model);
|
||||
}
|
||||
return screensPanel;
|
||||
}
|
||||
|
||||
private JLabel getCharCountLabel()
|
||||
{
|
||||
if (charCountLabel == null)
|
||||
{
|
||||
charCountLabel = new JLabel("0");
|
||||
}
|
||||
return charCountLabel;
|
||||
}
|
||||
|
||||
private void updateDescriptionCharCount(int length)
|
||||
{
|
||||
if (length > 512)
|
||||
{
|
||||
getCharCountLabel().setIcon(UIManager.getIcon("OptionPane.warningIcon"));
|
||||
}
|
||||
else
|
||||
{
|
||||
getCharCountLabel().setIcon(null);
|
||||
}
|
||||
getCharCountLabel().setText(length + " characters (recommended max: 512)");
|
||||
}
|
||||
|
||||
void focusTitleField()
|
||||
{
|
||||
getTitleField().requestFocus();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import se.lantz.model.JoystickModel;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
import java.beans.Beans;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
public class JoystickBottomPanel extends JPanel
|
||||
{
|
||||
private KeySelectionComboBox aComboBox;
|
||||
private KeySelectionComboBox bComboBox;
|
||||
private KeySelectionComboBox cComboBox;
|
||||
private JLabel menuLabel;
|
||||
private JoystickModel model;
|
||||
|
||||
public JoystickBottomPanel(JoystickModel model)
|
||||
{
|
||||
this.model = model;
|
||||
this.setPreferredSize(new Dimension(300, 50));
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_aComboBox = new GridBagConstraints();
|
||||
gbc_aComboBox.anchor = GridBagConstraints.NORTH;
|
||||
gbc_aComboBox.weighty = 1.0;
|
||||
gbc_aComboBox.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_aComboBox.gridx = 0;
|
||||
gbc_aComboBox.gridy = 0;
|
||||
add(getAComboBox(), gbc_aComboBox);
|
||||
GridBagConstraints gbc_bComboBox = new GridBagConstraints();
|
||||
gbc_bComboBox.anchor = GridBagConstraints.NORTH;
|
||||
gbc_bComboBox.weighty = 1.0;
|
||||
gbc_bComboBox.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_bComboBox.gridx = 1;
|
||||
gbc_bComboBox.gridy = 0;
|
||||
add(getBComboBox(), gbc_bComboBox);
|
||||
GridBagConstraints gbc_cComboBox = new GridBagConstraints();
|
||||
gbc_cComboBox.anchor = GridBagConstraints.NORTH;
|
||||
gbc_cComboBox.weighty = 1.0;
|
||||
gbc_cComboBox.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_cComboBox.gridx = 2;
|
||||
gbc_cComboBox.gridy = 0;
|
||||
add(getCComboBox(), gbc_cComboBox);
|
||||
GridBagConstraints gbc_menuLabel = new GridBagConstraints();
|
||||
gbc_menuLabel.weighty = 1.0;
|
||||
gbc_menuLabel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_menuLabel.insets = new Insets(3, 15, 0, 5);
|
||||
gbc_menuLabel.gridx = 3;
|
||||
gbc_menuLabel.gridy = 0;
|
||||
add(getMenuLabel(), gbc_menuLabel);
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
model.addPropertyChangeListener((e) -> modelChanged());
|
||||
}
|
||||
}
|
||||
|
||||
private void modelChanged()
|
||||
{
|
||||
getAComboBox().setSelectedCode(model.getA());
|
||||
getBComboBox().setSelectedCode(model.getB());
|
||||
getCComboBox().setSelectedCode(model.getC());
|
||||
System.out.println("modelChanged in JoystickBottomPanel");
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getAComboBox()
|
||||
{
|
||||
if (aComboBox == null)
|
||||
{
|
||||
aComboBox = new KeySelectionComboBox();
|
||||
aComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setA(aComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return aComboBox;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getBComboBox()
|
||||
{
|
||||
if (bComboBox == null)
|
||||
{
|
||||
bComboBox = new KeySelectionComboBox();
|
||||
bComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setB(bComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return bComboBox;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getCComboBox()
|
||||
{
|
||||
if (cComboBox == null)
|
||||
{
|
||||
cComboBox = new KeySelectionComboBox();
|
||||
cComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setC(cComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return cComboBox;
|
||||
}
|
||||
|
||||
private JLabel getMenuLabel()
|
||||
{
|
||||
if (menuLabel == null)
|
||||
{
|
||||
menuLabel = new JLabel("Menu");
|
||||
}
|
||||
return menuLabel;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.beans.Beans;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import se.lantz.model.JoystickModel;
|
||||
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class JoystickPanel extends JPanel
|
||||
{
|
||||
private JCheckBox primaryJoyCheckBox;
|
||||
private JoystickStickPanel joystickStickPanel;
|
||||
private KeySelectionComboBox leftFireComboBox;
|
||||
private JLabel imageLabel;
|
||||
private KeySelectionComboBox rightFireComboBox;
|
||||
private KeySelectionComboBox tlComboBox;
|
||||
private KeySelectionComboBox trComboBox;
|
||||
private JoystickBottomPanel joystickBottomPanel;
|
||||
private int portnumber;
|
||||
private JLabel configLabel;
|
||||
private JTextField configTextField;
|
||||
|
||||
private JoystickModel model;
|
||||
|
||||
public JoystickPanel(int portnumber, JoystickModel model)
|
||||
{
|
||||
this.portnumber = portnumber;
|
||||
this.model = model;
|
||||
this.setPreferredSize(new Dimension(455, 510));
|
||||
this.setMinimumSize(new Dimension(455, 510));
|
||||
setBorder(new TitledBorder(null, "Port " + portnumber, TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
gridBagLayout.columnWeights = new double[] { 0.0, 1.0, 0.0 };
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_primaryJoyCheckBox = new GridBagConstraints();
|
||||
gbc_primaryJoyCheckBox.weightx = 1.0;
|
||||
gbc_primaryJoyCheckBox.gridwidth = 3;
|
||||
gbc_primaryJoyCheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_primaryJoyCheckBox.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_primaryJoyCheckBox.gridx = 0;
|
||||
gbc_primaryJoyCheckBox.gridy = 0;
|
||||
add(getPrimaryJoyCheckBox(), gbc_primaryJoyCheckBox);
|
||||
GridBagConstraints gbc_joystickStickPanel = new GridBagConstraints();
|
||||
gbc_joystickStickPanel.weightx = 1.0;
|
||||
gbc_joystickStickPanel.gridwidth = 3;
|
||||
gbc_joystickStickPanel.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_joystickStickPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_joystickStickPanel.gridx = 0;
|
||||
gbc_joystickStickPanel.gridy = 1;
|
||||
add(getJoystickStickPanel(), gbc_joystickStickPanel);
|
||||
GridBagConstraints gbc_leftFireComboBox = new GridBagConstraints();
|
||||
gbc_leftFireComboBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_leftFireComboBox.insets = new Insets(90, 10, 5, 5);
|
||||
gbc_leftFireComboBox.gridx = 0;
|
||||
gbc_leftFireComboBox.gridy = 2;
|
||||
add(getLeftFireComboBox(), gbc_leftFireComboBox);
|
||||
GridBagConstraints gbc_imageLabel = new GridBagConstraints();
|
||||
gbc_imageLabel.gridheight = 3;
|
||||
gbc_imageLabel.weightx = 1.0;
|
||||
gbc_imageLabel.fill = GridBagConstraints.BOTH;
|
||||
gbc_imageLabel.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_imageLabel.gridx = 1;
|
||||
gbc_imageLabel.gridy = 2;
|
||||
add(getImageLabel(), gbc_imageLabel);
|
||||
GridBagConstraints gbc_rightFireComboBox = new GridBagConstraints();
|
||||
gbc_rightFireComboBox.anchor = GridBagConstraints.EAST;
|
||||
gbc_rightFireComboBox.insets = new Insets(90, 0, 5, 10);
|
||||
gbc_rightFireComboBox.gridx = 2;
|
||||
gbc_rightFireComboBox.gridy = 2;
|
||||
add(getRightFireComboBox(), gbc_rightFireComboBox);
|
||||
GridBagConstraints gbc_tlComboBox = new GridBagConstraints();
|
||||
gbc_tlComboBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_tlComboBox.insets = new Insets(30, 10, 5, 5);
|
||||
gbc_tlComboBox.gridx = 0;
|
||||
gbc_tlComboBox.gridy = 3;
|
||||
add(getTlComboBox(), gbc_tlComboBox);
|
||||
GridBagConstraints gbc_trComboBox = new GridBagConstraints();
|
||||
gbc_trComboBox.anchor = GridBagConstraints.EAST;
|
||||
gbc_trComboBox.insets = new Insets(30, 0, 5, 10);
|
||||
gbc_trComboBox.gridx = 2;
|
||||
gbc_trComboBox.gridy = 3;
|
||||
add(getTrComboBox(), gbc_trComboBox);
|
||||
GridBagConstraints gbc_joystickBottomPanel = new GridBagConstraints();
|
||||
gbc_joystickBottomPanel.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_joystickBottomPanel.gridwidth = 3;
|
||||
gbc_joystickBottomPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_joystickBottomPanel.gridx = 0;
|
||||
gbc_joystickBottomPanel.gridy = 5;
|
||||
add(getJoystickBottomPanel(), gbc_joystickBottomPanel);
|
||||
GridBagConstraints gbc_configLabel = new GridBagConstraints();
|
||||
gbc_configLabel.anchor = GridBagConstraints.EAST;
|
||||
gbc_configLabel.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_configLabel.gridx = 0;
|
||||
gbc_configLabel.gridy = 6;
|
||||
add(getConfigLabel(), gbc_configLabel);
|
||||
GridBagConstraints gbc_configTextField = new GridBagConstraints();
|
||||
gbc_configTextField.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_configTextField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_configTextField.gridx = 1;
|
||||
gbc_configTextField.gridy = 6;
|
||||
add(getConfigTextField(), gbc_configTextField);
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
model.addPropertyChangeListener((e) -> modelChanged());
|
||||
}
|
||||
}
|
||||
|
||||
private void modelChanged()
|
||||
{
|
||||
// Read from model
|
||||
getPrimaryJoyCheckBox().setSelected(model.isPrimary());
|
||||
getLeftFireComboBox().setSelectedCode(model.getLeftFire());
|
||||
getRightFireComboBox().setSelectedCode(model.getRightFire());
|
||||
getTlComboBox().setSelectedCode(model.getTl());
|
||||
getTrComboBox().setSelectedCode(model.getTr());
|
||||
|
||||
getConfigTextField().setText(model.getConfigString());
|
||||
System.out.println("modelChanged in JoystickStickPanel");
|
||||
}
|
||||
|
||||
private JCheckBox getPrimaryJoyCheckBox()
|
||||
{
|
||||
if (primaryJoyCheckBox == null)
|
||||
{
|
||||
String text = "Use port " + portnumber + " as Primary joystick";
|
||||
if (portnumber == 2)
|
||||
{
|
||||
text = text + " (Default setting, only change if required by game)";
|
||||
}
|
||||
primaryJoyCheckBox = new JCheckBox(text);
|
||||
primaryJoyCheckBox.addItemListener((e) -> model.setPrimary(primaryJoyCheckBox.isSelected()));
|
||||
}
|
||||
return primaryJoyCheckBox;
|
||||
}
|
||||
|
||||
private JoystickStickPanel getJoystickStickPanel()
|
||||
{
|
||||
if (joystickStickPanel == null)
|
||||
{
|
||||
joystickStickPanel = new JoystickStickPanel(model);
|
||||
}
|
||||
return joystickStickPanel;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getLeftFireComboBox()
|
||||
{
|
||||
if (leftFireComboBox == null)
|
||||
{
|
||||
leftFireComboBox = new KeySelectionComboBox();
|
||||
leftFireComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setLeftFire(leftFireComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return leftFireComboBox;
|
||||
}
|
||||
|
||||
private JLabel getImageLabel()
|
||||
{
|
||||
if (imageLabel == null)
|
||||
{
|
||||
imageLabel = new JLabel();
|
||||
imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
ImageIcon joyImage = new ImageIcon(getClass().getResource("/se/lantz/joystick2.png"));
|
||||
imageLabel.setIcon(joyImage);
|
||||
}
|
||||
return imageLabel;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getRightFireComboBox()
|
||||
{
|
||||
if (rightFireComboBox == null)
|
||||
{
|
||||
rightFireComboBox = new KeySelectionComboBox();
|
||||
rightFireComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setRightFire(rightFireComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return rightFireComboBox;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getTlComboBox()
|
||||
{
|
||||
if (tlComboBox == null)
|
||||
{
|
||||
tlComboBox = new KeySelectionComboBox();
|
||||
tlComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setTl(tlComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return tlComboBox;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getTrComboBox()
|
||||
{
|
||||
if (trComboBox == null)
|
||||
{
|
||||
trComboBox = new KeySelectionComboBox();
|
||||
trComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setTr(trComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return trComboBox;
|
||||
}
|
||||
|
||||
private JoystickBottomPanel getJoystickBottomPanel()
|
||||
{
|
||||
if (joystickBottomPanel == null)
|
||||
{
|
||||
joystickBottomPanel = new JoystickBottomPanel(model);
|
||||
}
|
||||
return joystickBottomPanel;
|
||||
}
|
||||
|
||||
private JLabel getConfigLabel()
|
||||
{
|
||||
if (configLabel == null)
|
||||
{
|
||||
configLabel = new JLabel("Config:");
|
||||
}
|
||||
return configLabel;
|
||||
}
|
||||
|
||||
private JTextField getConfigTextField()
|
||||
{
|
||||
if (configTextField == null)
|
||||
{
|
||||
configTextField = new JTextField();
|
||||
configTextField.setColumns(10);
|
||||
configTextField.addFocusListener(new FocusListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent arg0)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent arg0)
|
||||
{
|
||||
try
|
||||
{
|
||||
model.setConfigString(configTextField.getText());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
configTextField.setText(model.getConfigString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return configTextField;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import se.lantz.model.JoystickModel;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.beans.Beans;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
public class JoystickStickPanel extends JPanel
|
||||
{
|
||||
private KeySelectionComboBox upComboBox;
|
||||
private KeySelectionComboBox leftComboBox;
|
||||
private KeySelectionComboBox rightComboBox;
|
||||
private KeySelectionComboBox downComboBox;
|
||||
private JoystickModel model;
|
||||
|
||||
public JoystickStickPanel(JoystickModel model)
|
||||
{
|
||||
this.model = model;
|
||||
this.setPreferredSize(new Dimension(420, 160));
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_upComboBox = new GridBagConstraints();
|
||||
gbc_upComboBox.insets = new Insets(0, 10, 5, 10);
|
||||
gbc_upComboBox.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_upComboBox.gridx = 1;
|
||||
gbc_upComboBox.gridy = 0;
|
||||
add(getUpComboBox(), gbc_upComboBox);
|
||||
GridBagConstraints gbc_leftComboBox = new GridBagConstraints();
|
||||
gbc_leftComboBox.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_leftComboBox.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_leftComboBox.gridx = 0;
|
||||
gbc_leftComboBox.gridy = 1;
|
||||
add(getLeftComboBox(), gbc_leftComboBox);
|
||||
GridBagConstraints gbc_rightComboBox = new GridBagConstraints();
|
||||
gbc_rightComboBox.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_rightComboBox.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_rightComboBox.gridx = 2;
|
||||
gbc_rightComboBox.gridy = 1;
|
||||
add(getRightComboBox(), gbc_rightComboBox);
|
||||
GridBagConstraints gbc_downComboBox = new GridBagConstraints();
|
||||
gbc_downComboBox.insets = new Insets(0, 10, 0, 10);
|
||||
gbc_downComboBox.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_downComboBox.gridx = 1;
|
||||
gbc_downComboBox.gridy = 2;
|
||||
add(getDownComboBox(), gbc_downComboBox);
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
model.addPropertyChangeListener((e) -> modelChanged());
|
||||
}
|
||||
}
|
||||
|
||||
private void modelChanged()
|
||||
{
|
||||
getUpComboBox().setSelectedCode(model.getUp());
|
||||
getDownComboBox().setSelectedCode(model.getDown());
|
||||
getLeftComboBox().setSelectedCode(model.getLeft());
|
||||
getRightComboBox().setSelectedCode(model.getRight());
|
||||
System.out.println("modelChanged in JoystickStickPanel");
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getUpComboBox()
|
||||
{
|
||||
if (upComboBox == null)
|
||||
{
|
||||
upComboBox = new KeySelectionComboBox();
|
||||
upComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setUp(upComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return upComboBox;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getLeftComboBox()
|
||||
{
|
||||
if (leftComboBox == null)
|
||||
{
|
||||
leftComboBox = new KeySelectionComboBox();
|
||||
leftComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setLeft(leftComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return leftComboBox;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getRightComboBox()
|
||||
{
|
||||
if (rightComboBox == null)
|
||||
{
|
||||
rightComboBox = new KeySelectionComboBox();
|
||||
rightComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setRight(rightComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return rightComboBox;
|
||||
}
|
||||
|
||||
private KeySelectionComboBox getDownComboBox()
|
||||
{
|
||||
if (downComboBox == null)
|
||||
{
|
||||
downComboBox = new KeySelectionComboBox();
|
||||
downComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setDown(downComboBox.getSelectedCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
return downComboBox;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
|
||||
public class KeySelectionComboBox extends JComboBox<String>
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 5027151055966823980L;
|
||||
|
||||
Map<String, String> codeMap = new HashMap<>();
|
||||
|
||||
public KeySelectionComboBox()
|
||||
{
|
||||
super();
|
||||
setupItemsAndCodes();
|
||||
}
|
||||
|
||||
private void setupItemsAndCodes()
|
||||
{
|
||||
this.addItem("----");
|
||||
this.addItem("Up");
|
||||
this.addItem("Down");
|
||||
this.addItem("Left");
|
||||
this.addItem("Right");
|
||||
this.addItem("Fire");
|
||||
this.addItem("F1");
|
||||
this.addItem("F2");
|
||||
this.addItem("F3");
|
||||
this.addItem("F4");
|
||||
this.addItem("F5");
|
||||
this.addItem("F6");
|
||||
this.addItem("F7");
|
||||
this.addItem("F8");
|
||||
this.addItem("A");
|
||||
this.addItem("B");
|
||||
this.addItem("C");
|
||||
this.addItem("D");
|
||||
this.addItem("E");
|
||||
this.addItem("F");
|
||||
this.addItem("G");
|
||||
this.addItem("H");
|
||||
this.addItem("I");
|
||||
this.addItem("J");
|
||||
this.addItem("K");
|
||||
this.addItem("L");
|
||||
this.addItem("M");
|
||||
this.addItem("N");
|
||||
this.addItem("O");
|
||||
this.addItem("P");
|
||||
this.addItem("Q");
|
||||
this.addItem("R");
|
||||
this.addItem("S");
|
||||
this.addItem("T");
|
||||
this.addItem("U");
|
||||
this.addItem("V");
|
||||
this.addItem("W");
|
||||
this.addItem("X");
|
||||
this.addItem("Y");
|
||||
this.addItem("Z");
|
||||
this.addItem("1");
|
||||
this.addItem("2");
|
||||
this.addItem("3");
|
||||
this.addItem("4");
|
||||
this.addItem("5");
|
||||
this.addItem("6");
|
||||
this.addItem("7");
|
||||
this.addItem("8");
|
||||
this.addItem("9");
|
||||
this.addItem("0");
|
||||
this.addItem("ARROW LEFT");
|
||||
this.addItem("ARROW UP");
|
||||
this.addItem("THEC64");
|
||||
this.addItem(", (Comma)");
|
||||
this.addItem("CTRL");
|
||||
this.addItem("Cursor Up");
|
||||
this.addItem("Cursor Down");
|
||||
this.addItem("Cursor Left");
|
||||
this.addItem("Cursor Right");
|
||||
this.addItem("INST/DEL");
|
||||
this.addItem("RETURN");
|
||||
this.addItem("CLR/HOME");
|
||||
this.addItem("RUN/STOP");
|
||||
this.addItem("RESTORE");
|
||||
this.addItem("Left SHIFT");
|
||||
this.addItem("Right SHIFT");
|
||||
this.addItem("SHIFT LOCK");
|
||||
this.addItem("SPACE");
|
||||
this.addItem("£ (Pound)");
|
||||
// Codes not matching the text
|
||||
codeMap.put("", "----");
|
||||
codeMap.put("JU", "Up");
|
||||
codeMap.put("JD", "Down");
|
||||
codeMap.put("JL", "Left");
|
||||
codeMap.put("JR", "Right");
|
||||
codeMap.put("JF", "Fire");
|
||||
codeMap.put("AL", "ARROW LEFT");
|
||||
codeMap.put("AU", "ARROW UP");
|
||||
codeMap.put("CM", "THEC64");
|
||||
codeMap.put("CO", ", (Comma)");
|
||||
codeMap.put("CT", "CTRL");
|
||||
codeMap.put("CU", "Cursor Up");
|
||||
codeMap.put("CD", "Cursor Down");
|
||||
codeMap.put("CL", "Cursor Left");
|
||||
codeMap.put("CR", "Cursor Right");
|
||||
codeMap.put("DL", "INST/DEL");
|
||||
codeMap.put("EN", "RETURN");
|
||||
codeMap.put("HM", "CLR/HOME");
|
||||
codeMap.put("RS", "RUN/STOP");
|
||||
codeMap.put("RE", "RESTORE");
|
||||
codeMap.put("SL", "Left SHIFT");
|
||||
codeMap.put("SR", "Right SHIFT");
|
||||
codeMap.put("SS", "SHIFT LOCK");
|
||||
codeMap.put("SP", "SPACE");
|
||||
codeMap.put("PO", "£ (Pound)");
|
||||
}
|
||||
|
||||
public void setSelectedCode(String code)
|
||||
{
|
||||
String item = codeMap.get(code);
|
||||
if (item != null)
|
||||
{
|
||||
this.setSelectedItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setSelectedItem(code);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSelectedCode()
|
||||
{
|
||||
for (Entry<String, String> entry : codeMap.entrySet())
|
||||
{
|
||||
if (Objects.equals(getSelectedItem(), entry.getValue()))
|
||||
{
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return getSelectedItem().toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,328 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.ListSelectionModel;
|
||||
|
||||
import se.lantz.gui.gameview.GameViewManager;
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.data.GameListData;
|
||||
import se.lantz.model.data.GameView;
|
||||
|
||||
public class MainPanel extends JPanel
|
||||
{
|
||||
private JSplitPane splitPane;
|
||||
private JPanel listPanel;
|
||||
private JScrollPane listScrollPane;
|
||||
private JList<GameListData> list;
|
||||
private GameDetailsBackgroundPanel gameDetailsBackgroundPanel;
|
||||
|
||||
private final MainViewModel uiModel;
|
||||
private JPanel listViewPanel;
|
||||
private JButton listViewEditButton;
|
||||
private JComboBox<GameView> listViewComboBox;
|
||||
private JPanel viewInfoPanel;
|
||||
private JLabel viewInfoLabel;
|
||||
|
||||
private GameViewManager gameViewManager;
|
||||
|
||||
public MainPanel(final MainViewModel uiModel)
|
||||
{
|
||||
this.uiModel = uiModel;
|
||||
setLayout(new BorderLayout(0, 0));
|
||||
add(getSplitPane(), BorderLayout.CENTER);
|
||||
gameViewManager = new GameViewManager(getListViewComboBox(), uiModel);
|
||||
|
||||
uiModel.addSaveChangeListener(e -> {
|
||||
getListViewComboBox().setEnabled(!uiModel.isDataChanged());
|
||||
getListViewEditButton().setEnabled(!uiModel.isDataChanged());
|
||||
});
|
||||
|
||||
uiModel.addDuplicateGameListener(e -> showDuplicateDialog(e.getNewValue().toString()));
|
||||
uiModel.addRequireFieldsListener(e -> showRequiredFieldsDialog((List<String>)e.getNewValue()));
|
||||
}
|
||||
|
||||
private JSplitPane getSplitPane()
|
||||
{
|
||||
if (splitPane == null)
|
||||
{
|
||||
splitPane = new JSplitPane();
|
||||
splitPane.setLeftComponent(getListPanel());
|
||||
splitPane.setRightComponent(getGameDetailsBackgroundPanel());
|
||||
splitPane.setResizeWeight(1.0);
|
||||
}
|
||||
return splitPane;
|
||||
}
|
||||
|
||||
private JPanel getListPanel()
|
||||
{
|
||||
if (listPanel == null)
|
||||
{
|
||||
listPanel = new JPanel();
|
||||
GridBagLayout gbl_listPanel = new GridBagLayout();
|
||||
listPanel.setLayout(gbl_listPanel);
|
||||
GridBagConstraints gbc_listViewPanel = new GridBagConstraints();
|
||||
gbc_listViewPanel.weightx = 1.0;
|
||||
gbc_listViewPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_listViewPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_listViewPanel.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_listViewPanel.gridx = 0;
|
||||
gbc_listViewPanel.gridy = 0;
|
||||
listPanel.add(getListViewPanel(), gbc_listViewPanel);
|
||||
GridBagConstraints gbc_listScrollPane = new GridBagConstraints();
|
||||
gbc_listScrollPane.weighty = 1.0;
|
||||
gbc_listScrollPane.weightx = 1.0;
|
||||
gbc_listScrollPane.fill = GridBagConstraints.BOTH;
|
||||
gbc_listScrollPane.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_listScrollPane.gridx = 0;
|
||||
gbc_listScrollPane.gridy = 1;
|
||||
listPanel.add(getListScrollPane(), gbc_listScrollPane);
|
||||
GridBagConstraints gbc_viewInfoPanel = new GridBagConstraints();
|
||||
gbc_viewInfoPanel.weightx = 1.0;
|
||||
gbc_viewInfoPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_viewInfoPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_viewInfoPanel.gridx = 0;
|
||||
gbc_viewInfoPanel.gridy = 2;
|
||||
listPanel.add(getViewInfoPanel(), gbc_viewInfoPanel);
|
||||
}
|
||||
return listPanel;
|
||||
}
|
||||
|
||||
private JScrollPane getListScrollPane()
|
||||
{
|
||||
if (listScrollPane == null)
|
||||
{
|
||||
listScrollPane = new JScrollPane(getList());
|
||||
listScrollPane.setMinimumSize(new Dimension(100, 23));
|
||||
}
|
||||
return listScrollPane;
|
||||
}
|
||||
|
||||
private JList<GameListData> getList()
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
//Override setSelectionInterval to only allow changing game if no changes needs saving
|
||||
list = new JList<GameListData>()
|
||||
{
|
||||
@Override
|
||||
public void setSelectionInterval(int anchor, int lead)
|
||||
{
|
||||
if (!uiModel.isDataChanged())
|
||||
{
|
||||
super.setSelectionInterval(anchor, lead);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Just ignore
|
||||
int value = showUnsavedChangesDialog();
|
||||
if (value == JOptionPane.YES_OPTION)
|
||||
{
|
||||
if (uiModel.saveData())
|
||||
{
|
||||
super.setSelectionInterval(anchor, lead);
|
||||
getGameDetailsBackgroundPanel().updateSelectedGame(list.getSelectedValue());
|
||||
}
|
||||
}
|
||||
else if (value == JOptionPane.NO_OPTION)
|
||||
{
|
||||
super.setSelectionInterval(anchor, lead);
|
||||
getGameDetailsBackgroundPanel().updateSelectedGame(list.getSelectedValue());
|
||||
uiModel.removeNewGameListData();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Set focus from list so that it is not possible to change game with keyboard
|
||||
getViewInfoPanel().requestFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
|
||||
list.addListSelectionListener((e) -> {
|
||||
if (e.getValueIsAdjusting() == false)
|
||||
{
|
||||
getGameDetailsBackgroundPanel().updateSelectedGame(list.getSelectedValue());
|
||||
}
|
||||
});
|
||||
list.setModel(uiModel.getGameListModel());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
int showUnsavedChangesDialog()
|
||||
{
|
||||
return JOptionPane.showConfirmDialog(MainPanel.this,
|
||||
"Do you want to save changes for " + list.getSelectedValue() + "?",
|
||||
"Unsaved Changes",
|
||||
JOptionPane.YES_NO_CANCEL_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
}
|
||||
|
||||
private void showDuplicateDialog(String title)
|
||||
{
|
||||
JOptionPane.showMessageDialog(MainPanel.this,
|
||||
"A game already exists with the name \"" + title + "\". Give it another name.",
|
||||
"Game exists",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
//Request focus to the title field
|
||||
getGameDetailsBackgroundPanel().focusTitleField();
|
||||
}
|
||||
|
||||
private void showRequiredFieldsDialog(List<String> missingFields)
|
||||
{
|
||||
StringBuilder messageBuilder = new StringBuilder();
|
||||
messageBuilder.append("The following information needs to be added before saving:\n");
|
||||
for (String field : missingFields)
|
||||
{
|
||||
messageBuilder.append(" ");
|
||||
messageBuilder.append(field);
|
||||
messageBuilder.append("\n");
|
||||
}
|
||||
JOptionPane
|
||||
.showMessageDialog(MainPanel.this, messageBuilder, "Missing game information", JOptionPane.INFORMATION_MESSAGE);
|
||||
//Request focus to the title field
|
||||
getGameDetailsBackgroundPanel().focusTitleField();
|
||||
}
|
||||
|
||||
private GameDetailsBackgroundPanel getGameDetailsBackgroundPanel()
|
||||
{
|
||||
if (gameDetailsBackgroundPanel == null)
|
||||
{
|
||||
gameDetailsBackgroundPanel = new GameDetailsBackgroundPanel(uiModel);
|
||||
}
|
||||
return gameDetailsBackgroundPanel;
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
uiModel.initialize();
|
||||
}
|
||||
|
||||
private JPanel getListViewPanel()
|
||||
{
|
||||
if (listViewPanel == null)
|
||||
{
|
||||
listViewPanel = new JPanel();
|
||||
GridBagLayout gbl_listViewPanel = new GridBagLayout();
|
||||
gbl_listViewPanel.columnWidths = new int[] { 0, 0, 0 };
|
||||
gbl_listViewPanel.rowHeights = new int[] { 0, 0 };
|
||||
gbl_listViewPanel.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
|
||||
gbl_listViewPanel.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
|
||||
listViewPanel.setLayout(gbl_listViewPanel);
|
||||
GridBagConstraints gbc_listViewEditButton = new GridBagConstraints();
|
||||
gbc_listViewEditButton.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_listViewEditButton.insets = new Insets(9, 5, 5, 0);
|
||||
gbc_listViewEditButton.gridx = 0;
|
||||
gbc_listViewEditButton.gridy = 0;
|
||||
listViewPanel.add(getListViewEditButton(), gbc_listViewEditButton);
|
||||
GridBagConstraints gbc_listViewComboBox = new GridBagConstraints();
|
||||
gbc_listViewComboBox.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_listViewComboBox.weightx = 1.0;
|
||||
gbc_listViewComboBox.insets = new Insets(10, 5, 5, 5);
|
||||
gbc_listViewComboBox.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_listViewComboBox.gridx = 1;
|
||||
gbc_listViewComboBox.gridy = 0;
|
||||
listViewPanel.add(getListViewComboBox(), gbc_listViewComboBox);
|
||||
}
|
||||
return listViewPanel;
|
||||
}
|
||||
|
||||
private JButton getListViewEditButton()
|
||||
{
|
||||
if (listViewEditButton == null)
|
||||
{
|
||||
listViewEditButton = new JButton("...");
|
||||
listViewEditButton.setMargin(new Insets(1, 1, 1, 1));
|
||||
|
||||
listViewEditButton.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
JMenuItem addItem = new JMenuItem("Add view...");
|
||||
addItem.addActionListener(e -> gameViewManager.openViewEditDialog(new GameView(0)));
|
||||
menu.add(addItem);
|
||||
if (((GameView) getListViewComboBox().getSelectedItem()).getGameViewId() > 0)
|
||||
{
|
||||
JMenuItem editItem = new JMenuItem("Edit view...");
|
||||
editItem.addActionListener(e -> gameViewManager
|
||||
.openViewEditDialog((GameView) getListViewComboBox().getSelectedItem()));
|
||||
menu.add(editItem);
|
||||
}
|
||||
|
||||
menu.show(listViewEditButton, 15, 15);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
return listViewEditButton;
|
||||
}
|
||||
|
||||
private JComboBox<GameView> getListViewComboBox()
|
||||
{
|
||||
if (listViewComboBox == null)
|
||||
{
|
||||
listViewComboBox = new JComboBox<>();
|
||||
listViewComboBox.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
uiModel.setSelectedGameView((GameView) listViewComboBox.getSelectedItem());
|
||||
//TODO: keep track of selected index for the view and select it once data is updated
|
||||
getList().setSelectedIndex(0);
|
||||
}
|
||||
});
|
||||
listViewComboBox.setModel(uiModel.getGameViewModel());
|
||||
}
|
||||
return listViewComboBox;
|
||||
}
|
||||
|
||||
private JPanel getViewInfoPanel()
|
||||
{
|
||||
if (viewInfoPanel == null)
|
||||
{
|
||||
viewInfoPanel = new JPanel();
|
||||
viewInfoPanel.add(getViewInfoLabel());
|
||||
}
|
||||
return viewInfoPanel;
|
||||
}
|
||||
|
||||
private JLabel getViewInfoLabel()
|
||||
{
|
||||
if (viewInfoLabel == null)
|
||||
{
|
||||
viewInfoLabel = new JLabel("125 of 1000");
|
||||
}
|
||||
return viewInfoLabel;
|
||||
}
|
||||
|
||||
public void addNewGame()
|
||||
{
|
||||
//Add new entry and select in the list
|
||||
uiModel.addNewGameListData();
|
||||
int rowToSelect = getList().getModel().getSize() - 1;
|
||||
getList().setSelectionInterval(rowToSelect, rowToSelect);
|
||||
getList().ensureIndexIsVisible(rowToSelect);
|
||||
getGameDetailsBackgroundPanel().updateSelectedGame(list.getSelectedValue());
|
||||
getGameDetailsBackgroundPanel().focusTitleField();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
|
||||
import se.lantz.model.MainViewModel;
|
||||
|
||||
public class MainWindow extends JFrame
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 2359068353897458894L;
|
||||
|
||||
private MainPanel mainPanel;
|
||||
private JMenuBar menuBar;
|
||||
private final MainViewModel uiModel;
|
||||
private final MenuManager menuManager;
|
||||
|
||||
private static MainWindow instance = null;
|
||||
|
||||
public static MainWindow getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new MainWindow();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean isInitialized() {
|
||||
return instance != null;
|
||||
}
|
||||
|
||||
|
||||
private MainWindow()
|
||||
{
|
||||
this.setIconImage(new ImageIcon(getClass().getResource("/se/lantz/FrameIcon.png")).getImage());
|
||||
this.setTitle("PCU Game Manager");
|
||||
uiModel = new MainViewModel();
|
||||
menuManager = new MenuManager(uiModel, this);
|
||||
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
|
||||
this.addWindowListener(new java.awt.event.WindowAdapter()
|
||||
{
|
||||
public void windowClosing(java.awt.event.WindowEvent e)
|
||||
{
|
||||
menuManager.triggerExit();
|
||||
}
|
||||
});
|
||||
getContentPane().add(getMainPanel(), BorderLayout.CENTER);
|
||||
|
||||
|
||||
this.setJMenuBar(getMainMenuBar());
|
||||
}
|
||||
|
||||
public void initialize()
|
||||
{
|
||||
getMainPanel().initialize();
|
||||
}
|
||||
|
||||
MainPanel getMainPanel()
|
||||
{
|
||||
if (mainPanel == null)
|
||||
{
|
||||
mainPanel = new MainPanel(uiModel);
|
||||
}
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
private JMenuBar getMainMenuBar()
|
||||
{
|
||||
if (menuBar == null)
|
||||
{
|
||||
menuBar = new JMenuBar();
|
||||
for (JMenu menu : menuManager.getMenues())
|
||||
{
|
||||
menuBar.add(menu);
|
||||
}
|
||||
}
|
||||
return menuBar;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import se.lantz.gui.imports.ImportOptionsDialog;
|
||||
import se.lantz.gui.imports.ImportProgressDialog;
|
||||
import se.lantz.gui.imports.ImportWorker;
|
||||
import se.lantz.model.ImportManager;
|
||||
import se.lantz.model.MainViewModel;
|
||||
|
||||
public class MenuManager
|
||||
{
|
||||
|
||||
private JMenu fileMenu;
|
||||
private JMenu dbMenu;
|
||||
private JMenu helpMenu;
|
||||
|
||||
private JMenuItem addGameItem;
|
||||
private JMenuItem importItem;
|
||||
private JMenuItem exportItem;
|
||||
private JMenuItem exitItem;
|
||||
|
||||
private JMenuItem backupDbItem;
|
||||
private JMenuItem restoreDbItem;
|
||||
private JMenuItem createEmptyDbItem;
|
||||
|
||||
private JMenuItem helpItem;
|
||||
private JMenuItem aboutItem;
|
||||
|
||||
private MainViewModel uiModel;
|
||||
private ImportManager importManager;
|
||||
private MainWindow mainWindow;
|
||||
|
||||
public MenuManager(final MainViewModel uiModel, MainWindow mainWindow)
|
||||
{
|
||||
this.uiModel = uiModel;
|
||||
this.mainWindow = mainWindow;
|
||||
this.importManager = new ImportManager(uiModel);
|
||||
setupMenues();
|
||||
}
|
||||
|
||||
public void triggerExit()
|
||||
{
|
||||
exitItem.doClick();
|
||||
}
|
||||
|
||||
private void setupMenues()
|
||||
{
|
||||
fileMenu = new JMenu("File");
|
||||
fileMenu.add(getAddGameMenuItem());
|
||||
fileMenu.add(getImportItem());
|
||||
fileMenu.add(getExportItem());
|
||||
fileMenu.addSeparator();
|
||||
fileMenu.add(getExitItem());
|
||||
dbMenu = new JMenu("Database");
|
||||
dbMenu.add(getBackupDbItem());
|
||||
dbMenu.add(getRestoreDbItem());
|
||||
dbMenu.add(getCreateEmptyDbItem());
|
||||
helpMenu = new JMenu("Help");
|
||||
helpMenu.add(getHelpItem());
|
||||
helpMenu.add(getAboutItem());
|
||||
|
||||
uiModel.addSaveChangeListener(e -> {
|
||||
addGameItem.setEnabled(!uiModel.isDataChanged());
|
||||
});
|
||||
// KeyStroke keyStrokeToAddGame = KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK);
|
||||
//
|
||||
// mainWindow.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(keyStrokeToAddGame, "AddGame");
|
||||
// mainWindow.getRootPane().getActionMap().put("AddGame", new AbstractAction()
|
||||
// {
|
||||
// @Override
|
||||
// public void actionPerformed(ActionEvent arg0)
|
||||
// {
|
||||
// mainWindow.getMainPanel().addNewGame();
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
public List<JMenu> getMenues()
|
||||
{
|
||||
List<JMenu> menuList = new ArrayList<JMenu>();
|
||||
menuList.add(fileMenu);
|
||||
menuList.add(dbMenu);
|
||||
menuList.add(helpMenu);
|
||||
return menuList;
|
||||
}
|
||||
|
||||
JMenuItem getAddGameMenuItem()
|
||||
{
|
||||
addGameItem = new JMenuItem("Add New Game");
|
||||
KeyStroke keyStrokeToAddGame = KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK);
|
||||
addGameItem.setAccelerator(keyStrokeToAddGame);
|
||||
addGameItem.setMnemonic('N');
|
||||
|
||||
addGameItem.addActionListener((e) -> {
|
||||
mainWindow.getMainPanel().addNewGame();
|
||||
});
|
||||
return addGameItem;
|
||||
}
|
||||
|
||||
private JMenuItem getImportItem()
|
||||
{
|
||||
importItem = new JMenuItem("Import Games...");
|
||||
KeyStroke keyStrokeToImportGames = KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_DOWN_MASK);
|
||||
importItem.setAccelerator(keyStrokeToImportGames);
|
||||
importItem.setMnemonic('I');
|
||||
importItem.addActionListener((e) -> {
|
||||
importGameList();
|
||||
});
|
||||
return importItem;
|
||||
}
|
||||
|
||||
private JMenuItem getExportItem()
|
||||
{
|
||||
exportItem = new JMenuItem("Export Games...");
|
||||
KeyStroke keyStrokeToExportGames = KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK);
|
||||
exportItem.setAccelerator(keyStrokeToExportGames);
|
||||
exportItem.setMnemonic('E');
|
||||
exportItem.addActionListener((e) -> {
|
||||
|
||||
});
|
||||
return exportItem;
|
||||
}
|
||||
|
||||
private JMenuItem getExitItem()
|
||||
{
|
||||
exitItem = new JMenuItem("Exit");
|
||||
exitItem.setMnemonic('x');
|
||||
exitItem.addActionListener((e) -> {
|
||||
if (uiModel.isDataChanged())
|
||||
{
|
||||
int value = mainWindow.getMainPanel().showUnsavedChangesDialog();
|
||||
if (value == JOptionPane.YES_OPTION)
|
||||
{
|
||||
if (!uiModel.saveData())
|
||||
{
|
||||
//Do not exit, save was not successful
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (value == JOptionPane.CANCEL_OPTION)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
//Exit here
|
||||
System.exit(0);
|
||||
});
|
||||
return exitItem;
|
||||
}
|
||||
|
||||
private JMenuItem getBackupDbItem()
|
||||
{
|
||||
backupDbItem = new JMenuItem("Backup database...");
|
||||
backupDbItem.addActionListener((e) -> {
|
||||
|
||||
});
|
||||
return backupDbItem;
|
||||
}
|
||||
|
||||
private JMenuItem getRestoreDbItem()
|
||||
{
|
||||
restoreDbItem = new JMenuItem("Restore backup...");
|
||||
restoreDbItem.addActionListener((e) -> {
|
||||
//TODO
|
||||
});
|
||||
return restoreDbItem;
|
||||
}
|
||||
|
||||
private JMenuItem getCreateEmptyDbItem()
|
||||
{
|
||||
createEmptyDbItem = new JMenuItem("Create empty database...");
|
||||
createEmptyDbItem.addActionListener((e) -> {
|
||||
//TODO
|
||||
});
|
||||
return createEmptyDbItem;
|
||||
}
|
||||
|
||||
private JMenuItem getHelpItem()
|
||||
{
|
||||
helpItem = new JMenuItem("Help");
|
||||
KeyStroke keyStrokeToImportGames = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0);
|
||||
helpItem.setAccelerator(keyStrokeToImportGames);
|
||||
helpItem.addActionListener((e) -> {
|
||||
//TODO
|
||||
});
|
||||
return helpItem;
|
||||
}
|
||||
|
||||
private JMenuItem getAboutItem()
|
||||
{
|
||||
aboutItem = new JMenuItem("About...");
|
||||
aboutItem.addActionListener((e) -> {
|
||||
//TODO
|
||||
});
|
||||
return aboutItem;
|
||||
}
|
||||
|
||||
private void importGameList()
|
||||
{
|
||||
final JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Select directory containing a Carousel");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
fileChooser.setSelectedFile(new File("F:\\C64\\GameManagerTest"));
|
||||
int value = fileChooser.showOpenDialog(this.mainWindow);
|
||||
if (value == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
if (importManager.checkSelectedFolder(fileChooser.getSelectedFile().toPath()))
|
||||
{
|
||||
//Show options dialog
|
||||
ImportOptionsDialog optionsDialog = new ImportOptionsDialog(this.mainWindow);
|
||||
optionsDialog.pack();
|
||||
optionsDialog.setLocationRelativeTo(this.mainWindow);
|
||||
if (optionsDialog.showDialog())
|
||||
{
|
||||
importManager.setSelectedOption(optionsDialog.getSelectedOption());
|
||||
ImportProgressDialog dialog = new ImportProgressDialog(this.mainWindow);
|
||||
ImportWorker worker = new ImportWorker(importManager, dialog);
|
||||
worker.execute();
|
||||
dialog.setVisible(true);
|
||||
//Refresh current game view after import
|
||||
uiModel.reloadCurrentGameView();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JOptionPane.showMessageDialog(this.mainWindow,
|
||||
"The selected directory doesn't contain a valid carousel structure.",
|
||||
"Import games",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GridBagLayout;
|
||||
import javax.swing.JLabel;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
public class ScreenshotEditDialog extends JDialog
|
||||
{
|
||||
private JPanel backroundPanel;
|
||||
private JLabel imageLabel;
|
||||
private JPanel buttonPanel;
|
||||
private JButton okButton;
|
||||
private JButton cancelButton;
|
||||
private JCheckBox cropCheckBox;
|
||||
|
||||
public ScreenshotEditDialog(Frame owner)
|
||||
{
|
||||
super(owner, "Edit screenshot", true);
|
||||
getContentPane().add(getBackroundPanel(), BorderLayout.CENTER);
|
||||
getContentPane().add(getButtonPanel(), BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
private JPanel getBackroundPanel()
|
||||
{
|
||||
if (backroundPanel == null)
|
||||
{
|
||||
backroundPanel = new JPanel();
|
||||
GridBagLayout gbl_backroundPanel = new GridBagLayout();
|
||||
gbl_backroundPanel.columnWidths = new int[] { 0, 0 };
|
||||
gbl_backroundPanel.rowHeights = new int[] { 0, 0, 0 };
|
||||
gbl_backroundPanel.columnWeights = new double[] { 0.0, Double.MIN_VALUE };
|
||||
gbl_backroundPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
|
||||
backroundPanel.setLayout(gbl_backroundPanel);
|
||||
GridBagConstraints gbc_imageLabel = new GridBagConstraints();
|
||||
gbc_imageLabel.weighty = 1.0;
|
||||
gbc_imageLabel.weightx = 1.0;
|
||||
gbc_imageLabel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_imageLabel.fill = GridBagConstraints.BOTH;
|
||||
gbc_imageLabel.insets = new Insets(10, 10, 10, 0);
|
||||
gbc_imageLabel.gridx = 0;
|
||||
gbc_imageLabel.gridy = 0;
|
||||
backroundPanel.add(getImageLabel(), gbc_imageLabel);
|
||||
GridBagConstraints gbc_cropCheckBox = new GridBagConstraints();
|
||||
gbc_cropCheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_cropCheckBox.weightx = 1.0;
|
||||
gbc_cropCheckBox.gridx = 0;
|
||||
gbc_cropCheckBox.gridy = 1;
|
||||
backroundPanel.add(getCropCheckBox(), gbc_cropCheckBox);
|
||||
}
|
||||
return backroundPanel;
|
||||
}
|
||||
|
||||
private JLabel getImageLabel()
|
||||
{
|
||||
if (imageLabel == null)
|
||||
{
|
||||
imageLabel = new JLabel("New label");
|
||||
}
|
||||
return imageLabel;
|
||||
}
|
||||
|
||||
private JPanel getButtonPanel()
|
||||
{
|
||||
if (buttonPanel == null)
|
||||
{
|
||||
buttonPanel = new JPanel();
|
||||
buttonPanel.add(getOkButton());
|
||||
buttonPanel.add(getCancelButton());
|
||||
}
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private JButton getOkButton()
|
||||
{
|
||||
if (okButton == null)
|
||||
{
|
||||
okButton = new JButton("OK");
|
||||
}
|
||||
return okButton;
|
||||
}
|
||||
|
||||
private JButton getCancelButton()
|
||||
{
|
||||
if (cancelButton == null)
|
||||
{
|
||||
cancelButton = new JButton("Cancel");
|
||||
}
|
||||
return cancelButton;
|
||||
}
|
||||
|
||||
private JCheckBox getCropCheckBox()
|
||||
{
|
||||
if (cropCheckBox == null)
|
||||
{
|
||||
cropCheckBox = new JCheckBox("Crop screenshot to 320x200 pixels");
|
||||
}
|
||||
return cropCheckBox;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,539 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
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.image.BufferedImage;
|
||||
import java.beans.Beans;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.model.InfoModel;
|
||||
import se.lantz.util.FileDrop;
|
||||
|
||||
public class ScreenshotsPanel extends JPanel
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(ScreenshotsPanel.class);
|
||||
private JPanel coverPanel;
|
||||
private JLabel coverImageLabel;
|
||||
private JButton changeCoverButton;
|
||||
private JPanel screenshotPanel;
|
||||
private JLabel screen1ImageLabel;
|
||||
private JButton screen1Button;
|
||||
private JLabel screen2ImageLabel;
|
||||
private JButton screen2Button;
|
||||
private JPanel gamePanel;
|
||||
private JLabel gameLabel;
|
||||
private JTextField gameTextField;
|
||||
private JButton gameButton;
|
||||
private InfoModel model;
|
||||
|
||||
private String currentCoverFile = "";
|
||||
private String currentScreen1File = "";
|
||||
private String currentScreen2File = "";
|
||||
|
||||
private ImageIcon missingSceenshotIcon = null;
|
||||
private ImageIcon missingCoverIcon = null;
|
||||
private JButton crop1Button;
|
||||
private JButton crop2Button;
|
||||
|
||||
private ImageIcon warningIcon = new ImageIcon(getClass().getResource("/se/lantz/warning-icon.png"));
|
||||
private String cropTooltip =
|
||||
"<html>Optimal resolution for the carousel is 320x200.<br>Press to automatically crop the image to this size.</html>";
|
||||
|
||||
public ScreenshotsPanel(InfoModel model)
|
||||
{
|
||||
this.model = model;
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
gridBagLayout.columnWeights = new double[] { 1.0, 0.0, 0.0 };
|
||||
gridBagLayout.rowWeights = new double[] { 0.0, 1.0 };
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_coverPanel = new GridBagConstraints();
|
||||
gbc_coverPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_coverPanel.insets = new Insets(10, 0, 5, 5);
|
||||
gbc_coverPanel.gridx = 1;
|
||||
gbc_coverPanel.gridy = 0;
|
||||
add(getCoverPanel(), gbc_coverPanel);
|
||||
GridBagConstraints gbc_screenshotPanel = new GridBagConstraints();
|
||||
gbc_screenshotPanel.insets = new Insets(10, 0, 5, 5);
|
||||
gbc_screenshotPanel.anchor = GridBagConstraints.WEST;
|
||||
gbc_screenshotPanel.fill = GridBagConstraints.VERTICAL;
|
||||
gbc_screenshotPanel.gridx = 2;
|
||||
gbc_screenshotPanel.gridy = 0;
|
||||
add(getScreenshotPanel(), gbc_screenshotPanel);
|
||||
GridBagConstraints gbc_gamePanel = new GridBagConstraints();
|
||||
gbc_gamePanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_gamePanel.gridwidth = 2;
|
||||
gbc_gamePanel.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_gamePanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_gamePanel.gridx = 1;
|
||||
gbc_gamePanel.gridy = 1;
|
||||
add(getGamePanel(), gbc_gamePanel);
|
||||
if (!Beans.isDesignTime())
|
||||
{
|
||||
model.addPropertyChangeListener((e) -> modelChanged());
|
||||
}
|
||||
}
|
||||
|
||||
private void modelChanged()
|
||||
{
|
||||
// Read from model
|
||||
getGameTextField().setText(model.getGamesFile());
|
||||
reloadScreens();
|
||||
}
|
||||
|
||||
private void reloadScreens()
|
||||
{
|
||||
String modelCoverFile = model.getCoverFile();
|
||||
if (!modelCoverFile.equals(currentCoverFile))
|
||||
{
|
||||
loadCover(modelCoverFile);
|
||||
currentCoverFile = modelCoverFile;
|
||||
}
|
||||
String modelScreen1File = model.getScreens1File();
|
||||
if (!model.getScreens1File().equals(currentScreen1File))
|
||||
{
|
||||
loadScreen(modelScreen1File, getScreen1ImageLabel());
|
||||
currentScreen1File = modelScreen1File;
|
||||
}
|
||||
String modelScreen2File = model.getScreens2File();
|
||||
if (!modelScreen2File.equals(currentScreen2File))
|
||||
{
|
||||
loadScreen(modelScreen2File, getScreen2ImageLabel());
|
||||
currentScreen2File = modelScreen2File;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadCover(String filename)
|
||||
{
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
File imagefile = new File("./covers/" + filename);
|
||||
try
|
||||
{
|
||||
BufferedImage image = ImageIO.read(imagefile);
|
||||
Image newImage = image.getScaledInstance(130, 200, Image.SCALE_DEFAULT);
|
||||
getCoverImageLabel().setIcon(new ImageIcon(newImage));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("can't read file: " + filename, e);
|
||||
getCoverImageLabel().setIcon(getMissingCoverImageIcon());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getCoverImageLabel().setIcon(getMissingCoverImageIcon());
|
||||
}
|
||||
}
|
||||
|
||||
private void loadScreen(String filename, JLabel screenLabel)
|
||||
{
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
File imagefile = new File("./screens/" + filename);
|
||||
try
|
||||
{
|
||||
BufferedImage image = ImageIO.read(imagefile);
|
||||
Image newImage = image.getScaledInstance(320, 200, Image.SCALE_DEFAULT);
|
||||
screenLabel.setIcon(new ImageIcon(newImage));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("can't read file: " + filename, e);
|
||||
screenLabel.setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screenLabel.setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
}
|
||||
|
||||
private ImageIcon getMissingScreenshotImageIcon()
|
||||
{
|
||||
if (missingSceenshotIcon == null)
|
||||
{
|
||||
missingSceenshotIcon = new ImageIcon(getClass().getResource("/se/lantz/MissingScreenshot.png"));
|
||||
}
|
||||
return missingSceenshotIcon;
|
||||
}
|
||||
|
||||
private ImageIcon getMissingCoverImageIcon()
|
||||
{
|
||||
if (missingCoverIcon == null)
|
||||
{
|
||||
missingCoverIcon = new ImageIcon(getClass().getResource("/se/lantz/MissingCover.png"));
|
||||
}
|
||||
return missingCoverIcon;
|
||||
}
|
||||
|
||||
private JPanel getCoverPanel()
|
||||
{
|
||||
if (coverPanel == null)
|
||||
{
|
||||
coverPanel = new JPanel();
|
||||
coverPanel.setMinimumSize(new Dimension(152, 255));
|
||||
coverPanel.setPreferredSize(new Dimension(152, 255));
|
||||
coverPanel.setBorder(new TitledBorder(null, "Cover", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_coverPanel = new GridBagLayout();
|
||||
coverPanel.setLayout(gbl_coverPanel);
|
||||
GridBagConstraints gbc_CoverImageLabel = new GridBagConstraints();
|
||||
gbc_CoverImageLabel.weighty = 1.0;
|
||||
gbc_CoverImageLabel.weightx = 1.0;
|
||||
gbc_CoverImageLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_CoverImageLabel.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_CoverImageLabel.gridx = 0;
|
||||
gbc_CoverImageLabel.gridy = 1;
|
||||
coverPanel.add(getCoverImageLabel(), gbc_CoverImageLabel);
|
||||
GridBagConstraints gbc_changeCoverButton = new GridBagConstraints();
|
||||
gbc_changeCoverButton.weightx = 1.0;
|
||||
gbc_changeCoverButton.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_changeCoverButton.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_changeCoverButton.gridx = 0;
|
||||
gbc_changeCoverButton.gridy = 2;
|
||||
coverPanel.add(getChangeCoverButton(), gbc_changeCoverButton);
|
||||
}
|
||||
return coverPanel;
|
||||
}
|
||||
|
||||
private JLabel getCoverImageLabel()
|
||||
{
|
||||
if (coverImageLabel == null)
|
||||
{
|
||||
coverImageLabel = new JLabel("");
|
||||
new FileDrop(coverImageLabel, new FileDrop.Listener()
|
||||
{
|
||||
public void filesDropped(java.io.File[] files)
|
||||
{
|
||||
// handle file drop
|
||||
logger.debug("File dropped for cover!");
|
||||
model.setCoverImage(handleCoverFileDrop(files, coverImageLabel));
|
||||
}
|
||||
});
|
||||
}
|
||||
return coverImageLabel;
|
||||
}
|
||||
|
||||
private JButton getChangeCoverButton()
|
||||
{
|
||||
if (changeCoverButton == null)
|
||||
{
|
||||
changeCoverButton = new JButton("...");
|
||||
changeCoverButton.setMargin(new Insets(1, 3, 1, 3));
|
||||
}
|
||||
return changeCoverButton;
|
||||
}
|
||||
|
||||
private JPanel getScreenshotPanel()
|
||||
{
|
||||
if (screenshotPanel == null)
|
||||
{
|
||||
screenshotPanel = new JPanel();
|
||||
screenshotPanel.setMinimumSize(new Dimension(672, 255));
|
||||
screenshotPanel.setPreferredSize(new Dimension(672, 255));
|
||||
screenshotPanel
|
||||
.setBorder(new TitledBorder(null, "Screenshots", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_screenshotPanel = new GridBagLayout();
|
||||
screenshotPanel.setLayout(gbl_screenshotPanel);
|
||||
GridBagConstraints gbc_screen1ImageLabel = new GridBagConstraints();
|
||||
gbc_screen1ImageLabel.gridwidth = 2;
|
||||
gbc_screen1ImageLabel.weightx = 0.5;
|
||||
gbc_screen1ImageLabel.weighty = 1.0;
|
||||
gbc_screen1ImageLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_screen1ImageLabel.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_screen1ImageLabel.gridx = 0;
|
||||
gbc_screen1ImageLabel.gridy = 0;
|
||||
screenshotPanel.add(getScreen1ImageLabel(), gbc_screen1ImageLabel);
|
||||
GridBagConstraints gbc_screen1Button = new GridBagConstraints();
|
||||
gbc_screen1Button.weightx = 0.5;
|
||||
gbc_screen1Button.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_screen1Button.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_screen1Button.gridx = 0;
|
||||
gbc_screen1Button.gridy = 1;
|
||||
screenshotPanel.add(getScreen1Button(), gbc_screen1Button);
|
||||
GridBagConstraints gbc_screen2ImageLabel = new GridBagConstraints();
|
||||
gbc_screen2ImageLabel.gridwidth = 3;
|
||||
gbc_screen2ImageLabel.weighty = 1.0;
|
||||
gbc_screen2ImageLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_screen2ImageLabel.weightx = 0.5;
|
||||
gbc_screen2ImageLabel.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_screen2ImageLabel.gridx = 2;
|
||||
gbc_screen2ImageLabel.gridy = 0;
|
||||
screenshotPanel.add(getScreen2ImageLabel(), gbc_screen2ImageLabel);
|
||||
GridBagConstraints gbc_crop1Button = new GridBagConstraints();
|
||||
gbc_crop1Button.anchor = GridBagConstraints.NORTHEAST;
|
||||
gbc_crop1Button.insets = new Insets(0, 0, 3, 5);
|
||||
gbc_crop1Button.gridx = 1;
|
||||
gbc_crop1Button.gridy = 1;
|
||||
screenshotPanel.add(getCrop1Button(), gbc_crop1Button);
|
||||
GridBagConstraints gbc_screen2Button = new GridBagConstraints();
|
||||
gbc_screen2Button.weightx = 0.5;
|
||||
gbc_screen2Button.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_screen2Button.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_screen2Button.gridx = 2;
|
||||
gbc_screen2Button.gridy = 1;
|
||||
screenshotPanel.add(getScreen2Button(), gbc_screen2Button);
|
||||
GridBagConstraints gbc_crop2Button = new GridBagConstraints();
|
||||
gbc_crop2Button.anchor = GridBagConstraints.NORTHEAST;
|
||||
gbc_crop2Button.insets = new Insets(0, 0, 3, 5);
|
||||
gbc_crop2Button.gridx = 3;
|
||||
gbc_crop2Button.gridy = 1;
|
||||
screenshotPanel.add(getCrop2Button(), gbc_crop2Button);
|
||||
}
|
||||
return screenshotPanel;
|
||||
}
|
||||
|
||||
private JLabel getScreen1ImageLabel()
|
||||
{
|
||||
if (screen1ImageLabel == null)
|
||||
{
|
||||
screen1ImageLabel = new JLabel("");
|
||||
new FileDrop(screen1ImageLabel, new FileDrop.Listener()
|
||||
{
|
||||
public void filesDropped(java.io.File[] files)
|
||||
{
|
||||
logger.debug("File dropped for screen 1!");
|
||||
model.setScreen1Image(handleScreenFileDrop(files, screen1ImageLabel, crop1Button));
|
||||
}
|
||||
});
|
||||
}
|
||||
return screen1ImageLabel;
|
||||
}
|
||||
|
||||
private JButton getScreen1Button()
|
||||
{
|
||||
if (screen1Button == null)
|
||||
{
|
||||
screen1Button = new JButton("...");
|
||||
screen1Button.setMargin(new Insets(1, 3, 1, 3));
|
||||
screen1Button.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
showEditPanel(screen1Button);
|
||||
}
|
||||
});
|
||||
}
|
||||
return screen1Button;
|
||||
}
|
||||
|
||||
private JLabel getScreen2ImageLabel()
|
||||
{
|
||||
if (screen2ImageLabel == null)
|
||||
{
|
||||
screen2ImageLabel = new JLabel("");
|
||||
new FileDrop(screen2ImageLabel, new FileDrop.Listener()
|
||||
{
|
||||
public void filesDropped(java.io.File[] files)
|
||||
{
|
||||
logger.debug("File dropped for screen 2!");
|
||||
model.setScreen2Image(handleScreenFileDrop(files, screen2ImageLabel, crop2Button));
|
||||
}
|
||||
});
|
||||
}
|
||||
return screen2ImageLabel;
|
||||
}
|
||||
|
||||
private JButton getScreen2Button()
|
||||
{
|
||||
if (screen2Button == null)
|
||||
{
|
||||
screen2Button = new JButton("...");
|
||||
screen2Button.setMargin(new Insets(1, 3, 1, 3));
|
||||
}
|
||||
return screen2Button;
|
||||
}
|
||||
|
||||
private JPanel getGamePanel()
|
||||
{
|
||||
if (gamePanel == null)
|
||||
{
|
||||
gamePanel = new JPanel();
|
||||
GridBagLayout gbl_gamePanel = new GridBagLayout();
|
||||
gamePanel.setLayout(gbl_gamePanel);
|
||||
GridBagConstraints gbc_gameLabel = new GridBagConstraints();
|
||||
gbc_gameLabel.weightx = 1.0;
|
||||
gbc_gameLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_gameLabel.insets = new Insets(5, 0, 0, 5);
|
||||
gbc_gameLabel.gridx = 0;
|
||||
gbc_gameLabel.gridy = 0;
|
||||
gamePanel.add(getGameLabel(), gbc_gameLabel);
|
||||
GridBagConstraints gbc_gameTextField = new GridBagConstraints();
|
||||
gbc_gameTextField.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_gameTextField.weighty = 1.0;
|
||||
gbc_gameTextField.insets = new Insets(1, 0, 5, 5);
|
||||
gbc_gameTextField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_gameTextField.gridx = 0;
|
||||
gbc_gameTextField.gridy = 1;
|
||||
gamePanel.add(getGameTextField(), gbc_gameTextField);
|
||||
GridBagConstraints gbc_gameButton = new GridBagConstraints();
|
||||
gbc_gameButton.weighty = 1.0;
|
||||
gbc_gameButton.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_gameButton.weightx = 1.0;
|
||||
gbc_gameButton.insets = new Insets(0, 0, 5, 5);
|
||||
gbc_gameButton.gridx = 1;
|
||||
gbc_gameButton.gridy = 1;
|
||||
gamePanel.add(getGameButton(), gbc_gameButton);
|
||||
}
|
||||
return gamePanel;
|
||||
}
|
||||
|
||||
private JLabel getGameLabel()
|
||||
{
|
||||
if (gameLabel == null)
|
||||
{
|
||||
gameLabel = new JLabel("Game file");
|
||||
}
|
||||
return gameLabel;
|
||||
}
|
||||
|
||||
private JTextField getGameTextField()
|
||||
{
|
||||
if (gameTextField == null)
|
||||
{
|
||||
gameTextField = new JTextField();
|
||||
gameTextField.setPreferredSize(new Dimension(160, 20));
|
||||
}
|
||||
return gameTextField;
|
||||
}
|
||||
|
||||
private JButton getGameButton()
|
||||
{
|
||||
if (gameButton == null)
|
||||
{
|
||||
gameButton = new JButton("...");
|
||||
gameButton.setMargin(new Insets(1, 3, 1, 3));
|
||||
}
|
||||
return gameButton;
|
||||
}
|
||||
|
||||
private void showEditPanel(JComponent centerOver)
|
||||
{
|
||||
ScreenshotEditDialog dialog =
|
||||
new ScreenshotEditDialog((Frame) SwingUtilities.getAncestorOfClass(Frame.class, this));
|
||||
dialog.pack();
|
||||
dialog.setLocationRelativeTo(centerOver);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
private JButton getCrop1Button()
|
||||
{
|
||||
if (crop1Button == null)
|
||||
{
|
||||
crop1Button = new JButton(warningIcon);
|
||||
crop1Button.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setScreen1Image(cropImage(model.getScreen1Image(), getScreen1ImageLabel()));
|
||||
crop1Button.setVisible(false);
|
||||
}
|
||||
});
|
||||
crop1Button.setMargin(new Insets(1, 3, 1, 3));
|
||||
crop1Button.setToolTipText(cropTooltip);
|
||||
crop1Button.setVisible(false);
|
||||
}
|
||||
return crop1Button;
|
||||
}
|
||||
|
||||
private JButton getCrop2Button()
|
||||
{
|
||||
if (crop2Button == null)
|
||||
{
|
||||
crop2Button = new JButton(warningIcon);
|
||||
crop2Button.addActionListener(new ActionListener()
|
||||
{
|
||||
public void actionPerformed(ActionEvent arg0)
|
||||
{
|
||||
model.setScreen2Image(cropImage(model.getScreen2Image(), getScreen2ImageLabel()));
|
||||
crop2Button.setVisible(false);
|
||||
}
|
||||
});
|
||||
crop2Button.setMargin(new Insets(1, 3, 1, 3));
|
||||
crop2Button.setToolTipText(cropTooltip);
|
||||
crop2Button.setVisible(false);
|
||||
}
|
||||
return crop2Button;
|
||||
}
|
||||
|
||||
private BufferedImage handleCoverFileDrop(File[] files, JLabel imageLabel)
|
||||
{
|
||||
BufferedImage returnImage = null;
|
||||
if (files.length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
returnImage = ImageIO.read(files[0]);
|
||||
Image newImage = returnImage.getScaledInstance(135, 200, Image.SCALE_DEFAULT);
|
||||
imageLabel.setIcon(new ImageIcon(newImage));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("can't read file: " + files[0].getName(), e);
|
||||
imageLabel.setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
}
|
||||
return returnImage;
|
||||
}
|
||||
|
||||
private BufferedImage handleScreenFileDrop(File[] files, JLabel imageLabel, JButton cropButton)
|
||||
{
|
||||
BufferedImage returnImage = null;
|
||||
if (files.length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
returnImage = ImageIO.read(files[0]);
|
||||
|
||||
if (returnImage.getHeight() > 200 && returnImage.getWidth() > 320)
|
||||
{
|
||||
cropButton.setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cropButton.setVisible(false);
|
||||
}
|
||||
Image newImage = returnImage.getScaledInstance(320, 200, Image.SCALE_DEFAULT);
|
||||
imageLabel.setIcon(new ImageIcon(newImage));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("can't read file: " + files[0].getName(), e);
|
||||
imageLabel.setIcon(getMissingScreenshotImageIcon());
|
||||
}
|
||||
}
|
||||
return returnImage;
|
||||
}
|
||||
|
||||
private BufferedImage cropImage(BufferedImage originalImage, JLabel screenLabel)
|
||||
{
|
||||
// Crop to right size: Remove the border to fit nicely in the carousel.
|
||||
BufferedImage newImage = originalImage.getSubimage(32, 35, 320, 200);
|
||||
BufferedImage copyOfImage =
|
||||
new BufferedImage(newImage.getWidth(), newImage.getHeight(), BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = copyOfImage.createGraphics();
|
||||
g.drawImage(newImage, 0, 0, null);
|
||||
screenLabel.setIcon(new ImageIcon(newImage));
|
||||
return newImage;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,527 @@
|
|||
package se.lantz.gui;
|
||||
|
||||
import java.awt.LayoutManager;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import javax.swing.JRadioButton;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.CardLayout;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.Font;
|
||||
|
||||
public class SystemPanel extends JPanel
|
||||
{
|
||||
private JPanel radioPanel;
|
||||
private JRadioButton c64Button;
|
||||
private JRadioButton vic20Button;
|
||||
private final ButtonGroup typeButtonGroup = new ButtonGroup();
|
||||
private JPanel typePanel;
|
||||
private JPanel drivePanel;
|
||||
private JPanel displayPanel;
|
||||
private JPanel cardPanel;
|
||||
private JPanel audioPanel;
|
||||
private JPanel ramPanel;
|
||||
private JPanel configPanel;
|
||||
private JLabel configLabel;
|
||||
private JTextField configTextField;
|
||||
private JRadioButton palRadioButton;
|
||||
private JRadioButton ntscRadioButton;
|
||||
private final ButtonGroup typeGroup = new ButtonGroup();
|
||||
private JCheckBox driveIconCheckBox;
|
||||
private JCheckBox accurateDiskCheckBox;
|
||||
private JCheckBox fullHeightCheckBox;
|
||||
private DisplayShiftComboBox displayShiftComboBox;
|
||||
private JLabel displayShiftLabel;
|
||||
private JRadioButton sid6581RadioButton;
|
||||
private JRadioButton sid8580RadioButton;
|
||||
private JRadioButton sid8580dRadioButton;
|
||||
private JCheckBox noAudioScaleCheckBox;
|
||||
private JCheckBox bank0CheckBox;
|
||||
private JCheckBox bank1CheckBox;
|
||||
private JCheckBox bank2CheckBox;
|
||||
private JCheckBox bank3CheckBox;
|
||||
private JCheckBox bank5CheckBox;
|
||||
private JLabel ramLabel;
|
||||
|
||||
private CardLayout cardLayout = new CardLayout(0, 0);
|
||||
private final ButtonGroup audioGroup = new ButtonGroup();
|
||||
|
||||
public SystemPanel()
|
||||
{
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_radioPanel = new GridBagConstraints();
|
||||
gbc_radioPanel.weightx = 1.0;
|
||||
gbc_radioPanel.gridwidth = 2;
|
||||
gbc_radioPanel.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_radioPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_radioPanel.gridx = 0;
|
||||
gbc_radioPanel.gridy = 0;
|
||||
add(getRadioPanel(), gbc_radioPanel);
|
||||
GridBagConstraints gbc_typePanel = new GridBagConstraints();
|
||||
gbc_typePanel.weightx = 0.5;
|
||||
gbc_typePanel.insets = new Insets(5, 5, 5, 5);
|
||||
gbc_typePanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_typePanel.gridx = 0;
|
||||
gbc_typePanel.gridy = 1;
|
||||
add(getTypePanel(), gbc_typePanel);
|
||||
GridBagConstraints gbc_drivePanel = new GridBagConstraints();
|
||||
gbc_drivePanel.insets = new Insets(5, 0, 5, 5);
|
||||
gbc_drivePanel.weightx = 0.5;
|
||||
gbc_drivePanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_drivePanel.gridx = 1;
|
||||
gbc_drivePanel.gridy = 1;
|
||||
add(getDrivePanel(), gbc_drivePanel);
|
||||
GridBagConstraints gbc_displayPanel = new GridBagConstraints();
|
||||
gbc_displayPanel.weightx = 1.0;
|
||||
gbc_displayPanel.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_displayPanel.gridwidth = 2;
|
||||
gbc_displayPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_displayPanel.gridx = 0;
|
||||
gbc_displayPanel.gridy = 2;
|
||||
add(getDisplayPanel(), gbc_displayPanel);
|
||||
GridBagConstraints gbc_cardPanel = new GridBagConstraints();
|
||||
gbc_cardPanel.weightx = 1.0;
|
||||
gbc_cardPanel.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_cardPanel.gridwidth = 2;
|
||||
gbc_cardPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_cardPanel.gridx = 0;
|
||||
gbc_cardPanel.gridy = 3;
|
||||
add(getCardPanel(), gbc_cardPanel);
|
||||
GridBagConstraints gbc_configPanel = new GridBagConstraints();
|
||||
gbc_configPanel.gridwidth = 2;
|
||||
gbc_configPanel.weightx = 1.0;
|
||||
gbc_configPanel.weighty = 1.0;
|
||||
gbc_configPanel.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_configPanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_configPanel.gridx = 0;
|
||||
gbc_configPanel.gridy = 4;
|
||||
add(getConfigPanel(), gbc_configPanel);
|
||||
}
|
||||
|
||||
private JPanel getRadioPanel() {
|
||||
if (radioPanel == null) {
|
||||
radioPanel = new JPanel();
|
||||
GridBagLayout gbl_radioPanel = new GridBagLayout();
|
||||
radioPanel.setLayout(gbl_radioPanel);
|
||||
GridBagConstraints gbc_c64Button = new GridBagConstraints();
|
||||
gbc_c64Button.weightx = 1.0;
|
||||
gbc_c64Button.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_c64Button.insets = new Insets(5, 5, 0, 5);
|
||||
gbc_c64Button.gridx = 0;
|
||||
gbc_c64Button.gridy = 0;
|
||||
radioPanel.add(getC64Button(), gbc_c64Button);
|
||||
GridBagConstraints gbc_vic20Button = new GridBagConstraints();
|
||||
gbc_vic20Button.weightx = 1.0;
|
||||
gbc_vic20Button.weighty = 1.0;
|
||||
gbc_vic20Button.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_vic20Button.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_vic20Button.gridx = 0;
|
||||
gbc_vic20Button.gridy = 1;
|
||||
radioPanel.add(getVic20Button(), gbc_vic20Button);
|
||||
}
|
||||
return radioPanel;
|
||||
}
|
||||
private JRadioButton getC64Button() {
|
||||
if (c64Button == null) {
|
||||
c64Button = new JRadioButton("Commodore 64");
|
||||
c64Button.setSelected(true);
|
||||
c64Button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
cardLayout.show(getCardPanel(), "audio");
|
||||
getDisplayShiftComboBox().setup64Items();
|
||||
}
|
||||
});
|
||||
typeButtonGroup.add(c64Button);
|
||||
}
|
||||
return c64Button;
|
||||
}
|
||||
private JRadioButton getVic20Button() {
|
||||
if (vic20Button == null) {
|
||||
vic20Button = new JRadioButton("Commodore Vic-20");
|
||||
vic20Button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
cardLayout.show(getCardPanel(), "ram");
|
||||
getDisplayShiftComboBox().setupVic20Items();
|
||||
}
|
||||
});
|
||||
typeButtonGroup.add(vic20Button);
|
||||
}
|
||||
return vic20Button;
|
||||
}
|
||||
private JPanel getTypePanel() {
|
||||
if (typePanel == null) {
|
||||
typePanel = new JPanel();
|
||||
typePanel.setBorder(new TitledBorder(null, "System Type", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_typePanel = new GridBagLayout();
|
||||
typePanel.setLayout(gbl_typePanel);
|
||||
GridBagConstraints gbc_palRadioButton = new GridBagConstraints();
|
||||
gbc_palRadioButton.weightx = 1.0;
|
||||
gbc_palRadioButton.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_palRadioButton.gridx = 0;
|
||||
gbc_palRadioButton.gridy = 0;
|
||||
typePanel.add(getPalRadioButton(), gbc_palRadioButton);
|
||||
GridBagConstraints gbc_ntscRadioButton = new GridBagConstraints();
|
||||
gbc_ntscRadioButton.weightx = 1.0;
|
||||
gbc_ntscRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_ntscRadioButton.gridx = 0;
|
||||
gbc_ntscRadioButton.gridy = 1;
|
||||
typePanel.add(getNtscRadioButton(), gbc_ntscRadioButton);
|
||||
}
|
||||
return typePanel;
|
||||
}
|
||||
private JPanel getDrivePanel() {
|
||||
if (drivePanel == null) {
|
||||
drivePanel = new JPanel();
|
||||
drivePanel.setBorder(new TitledBorder(null, "Drive Emulation", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_drivePanel = new GridBagLayout();
|
||||
drivePanel.setLayout(gbl_drivePanel);
|
||||
GridBagConstraints gbc_driveIconCheckBox = new GridBagConstraints();
|
||||
gbc_driveIconCheckBox.weightx = 1.0;
|
||||
gbc_driveIconCheckBox.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_driveIconCheckBox.gridx = 0;
|
||||
gbc_driveIconCheckBox.gridy = 0;
|
||||
drivePanel.add(getDriveIconCheckBox(), gbc_driveIconCheckBox);
|
||||
GridBagConstraints gbc_accurateDiskCheckBox = new GridBagConstraints();
|
||||
gbc_accurateDiskCheckBox.weightx = 1.0;
|
||||
gbc_accurateDiskCheckBox.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_accurateDiskCheckBox.gridx = 0;
|
||||
gbc_accurateDiskCheckBox.gridy = 1;
|
||||
drivePanel.add(getAccurateDiskCheckBox(), gbc_accurateDiskCheckBox);
|
||||
}
|
||||
return drivePanel;
|
||||
}
|
||||
private JPanel getDisplayPanel() {
|
||||
if (displayPanel == null) {
|
||||
displayPanel = new JPanel();
|
||||
displayPanel.setBorder(new TitledBorder(null, "Display", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_displayPanel = new GridBagLayout();
|
||||
displayPanel.setLayout(gbl_displayPanel);
|
||||
GridBagConstraints gbc_fullHeightCheckBox = new GridBagConstraints();
|
||||
gbc_fullHeightCheckBox.gridwidth = 2;
|
||||
gbc_fullHeightCheckBox.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_fullHeightCheckBox.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_fullHeightCheckBox.gridx = 0;
|
||||
gbc_fullHeightCheckBox.gridy = 0;
|
||||
displayPanel.add(getFullHeightCheckBox(), gbc_fullHeightCheckBox);
|
||||
GridBagConstraints gbc_displayShiftComboBox = new GridBagConstraints();
|
||||
gbc_displayShiftComboBox.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_displayShiftComboBox.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_displayShiftComboBox.gridx = 0;
|
||||
gbc_displayShiftComboBox.gridy = 1;
|
||||
displayPanel.add(getDisplayShiftComboBox(), gbc_displayShiftComboBox);
|
||||
GridBagConstraints gbc_displayShiftLabel = new GridBagConstraints();
|
||||
gbc_displayShiftLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_displayShiftLabel.weightx = 1.0;
|
||||
gbc_displayShiftLabel.gridx = 1;
|
||||
gbc_displayShiftLabel.gridy = 1;
|
||||
displayPanel.add(getDisplayShiftLabel(), gbc_displayShiftLabel);
|
||||
}
|
||||
return displayPanel;
|
||||
}
|
||||
private JPanel getCardPanel() {
|
||||
if (cardPanel == null) {
|
||||
cardPanel = new JPanel();
|
||||
cardPanel.setLayout(cardLayout);
|
||||
cardPanel.add(getAudioPanel(), "audio");
|
||||
cardPanel.add(getRamPanel(), "ram");
|
||||
}
|
||||
return cardPanel;
|
||||
}
|
||||
private JPanel getAudioPanel() {
|
||||
if (audioPanel == null) {
|
||||
audioPanel = new JPanel();
|
||||
audioPanel.setBorder(new TitledBorder(null, "Audio", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_audioPanel = new GridBagLayout();
|
||||
gbl_audioPanel.columnWidths = new int[]{0, 0, 0};
|
||||
gbl_audioPanel.rowHeights = new int[]{0, 0, 0, 0};
|
||||
gbl_audioPanel.columnWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
|
||||
gbl_audioPanel.rowWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE};
|
||||
audioPanel.setLayout(gbl_audioPanel);
|
||||
GridBagConstraints gbc_sid6581RadioButton = new GridBagConstraints();
|
||||
gbc_sid6581RadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_sid6581RadioButton.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_sid6581RadioButton.gridx = 0;
|
||||
gbc_sid6581RadioButton.gridy = 0;
|
||||
audioPanel.add(getSid6581RadioButton(), gbc_sid6581RadioButton);
|
||||
GridBagConstraints gbc_noAudioScaleCheckBox = new GridBagConstraints();
|
||||
gbc_noAudioScaleCheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_noAudioScaleCheckBox.weightx = 1.0;
|
||||
gbc_noAudioScaleCheckBox.gridx = 1;
|
||||
gbc_noAudioScaleCheckBox.gridy = 0;
|
||||
audioPanel.add(getNoAudioScaleCheckBox(), gbc_noAudioScaleCheckBox);
|
||||
GridBagConstraints gbc_sid8580RadioButton = new GridBagConstraints();
|
||||
gbc_sid8580RadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_sid8580RadioButton.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_sid8580RadioButton.gridx = 0;
|
||||
gbc_sid8580RadioButton.gridy = 1;
|
||||
audioPanel.add(getSid8580RadioButton(), gbc_sid8580RadioButton);
|
||||
GridBagConstraints gbc_sid8580dRadioButton = new GridBagConstraints();
|
||||
gbc_sid8580dRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_sid8580dRadioButton.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_sid8580dRadioButton.gridx = 0;
|
||||
gbc_sid8580dRadioButton.gridy = 2;
|
||||
audioPanel.add(getSid8580dRadioButton(), gbc_sid8580dRadioButton);
|
||||
}
|
||||
return audioPanel;
|
||||
}
|
||||
private JPanel getRamPanel() {
|
||||
if (ramPanel == null) {
|
||||
ramPanel = new JPanel();
|
||||
ramPanel.setBorder(new TitledBorder(null, "Ram", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_ramPanel = new GridBagLayout();
|
||||
ramPanel.setLayout(gbl_ramPanel);
|
||||
GridBagConstraints gbc_bank0CheckBox = new GridBagConstraints();
|
||||
gbc_bank0CheckBox.weightx = 1.0;
|
||||
gbc_bank0CheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_bank0CheckBox.gridx = 0;
|
||||
gbc_bank0CheckBox.gridy = 0;
|
||||
ramPanel.add(getBank0CheckBox(), gbc_bank0CheckBox);
|
||||
GridBagConstraints gbc_bank1CheckBox = new GridBagConstraints();
|
||||
gbc_bank1CheckBox.weightx = 1.0;
|
||||
gbc_bank1CheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_bank1CheckBox.gridx = 0;
|
||||
gbc_bank1CheckBox.gridy = 1;
|
||||
ramPanel.add(getBank1CheckBox(), gbc_bank1CheckBox);
|
||||
GridBagConstraints gbc_bank2CheckBox = new GridBagConstraints();
|
||||
gbc_bank2CheckBox.weightx = 1.0;
|
||||
gbc_bank2CheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_bank2CheckBox.gridx = 0;
|
||||
gbc_bank2CheckBox.gridy = 2;
|
||||
ramPanel.add(getBank2CheckBox(), gbc_bank2CheckBox);
|
||||
GridBagConstraints gbc_bank3CheckBox = new GridBagConstraints();
|
||||
gbc_bank3CheckBox.weightx = 1.0;
|
||||
gbc_bank3CheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_bank3CheckBox.gridx = 0;
|
||||
gbc_bank3CheckBox.gridy = 3;
|
||||
ramPanel.add(getBank3CheckBox(), gbc_bank3CheckBox);
|
||||
GridBagConstraints gbc_bank5CheckBox = new GridBagConstraints();
|
||||
gbc_bank5CheckBox.weightx = 1.0;
|
||||
gbc_bank5CheckBox.anchor = GridBagConstraints.WEST;
|
||||
gbc_bank5CheckBox.insets = new Insets(0, 0, 5, 0);
|
||||
gbc_bank5CheckBox.gridx = 0;
|
||||
gbc_bank5CheckBox.gridy = 4;
|
||||
ramPanel.add(getBank5CheckBox(), gbc_bank5CheckBox);
|
||||
GridBagConstraints gbc_ramLabel = new GridBagConstraints();
|
||||
gbc_ramLabel.insets = new Insets(0, 5, 10, 5);
|
||||
gbc_ramLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_ramLabel.weightx = 1.0;
|
||||
gbc_ramLabel.gridx = 0;
|
||||
gbc_ramLabel.gridy = 5;
|
||||
ramPanel.add(getRamLabel(), gbc_ramLabel);
|
||||
}
|
||||
return ramPanel;
|
||||
}
|
||||
private JPanel getConfigPanel() {
|
||||
if (configPanel == null) {
|
||||
configPanel = new JPanel();
|
||||
GridBagLayout gbl_configPanel = new GridBagLayout();
|
||||
configPanel.setLayout(gbl_configPanel);
|
||||
GridBagConstraints gbc_configLabel = new GridBagConstraints();
|
||||
gbc_configLabel.weighty = 1.0;
|
||||
gbc_configLabel.anchor = GridBagConstraints.SOUTHWEST;
|
||||
gbc_configLabel.insets = new Insets(5, 5, 16, 5);
|
||||
gbc_configLabel.gridx = 0;
|
||||
gbc_configLabel.gridy = 0;
|
||||
configPanel.add(getConfigLabel(), gbc_configLabel);
|
||||
GridBagConstraints gbc_configTextField = new GridBagConstraints();
|
||||
gbc_configTextField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_configTextField.weightx = 1.0;
|
||||
gbc_configTextField.insets = new Insets(5, 0, 14, 5);
|
||||
gbc_configTextField.weighty = 1.0;
|
||||
gbc_configTextField.anchor = GridBagConstraints.SOUTHWEST;
|
||||
gbc_configTextField.gridx = 1;
|
||||
gbc_configTextField.gridy = 0;
|
||||
configPanel.add(getConfigTextField(), gbc_configTextField);
|
||||
}
|
||||
return configPanel;
|
||||
}
|
||||
private JLabel getConfigLabel() {
|
||||
if (configLabel == null) {
|
||||
configLabel = new JLabel("Config:");
|
||||
}
|
||||
return configLabel;
|
||||
}
|
||||
private JTextField getConfigTextField() {
|
||||
if (configTextField == null) {
|
||||
configTextField = new JTextField();
|
||||
configTextField.setColumns(10);
|
||||
}
|
||||
return configTextField;
|
||||
}
|
||||
private JRadioButton getPalRadioButton() {
|
||||
if (palRadioButton == null) {
|
||||
palRadioButton = new JRadioButton("PAL");
|
||||
palRadioButton.setSelected(true);
|
||||
typeGroup.add(palRadioButton);
|
||||
}
|
||||
return palRadioButton;
|
||||
}
|
||||
private JRadioButton getNtscRadioButton() {
|
||||
if (ntscRadioButton == null) {
|
||||
ntscRadioButton = new JRadioButton("NTSC");
|
||||
typeGroup.add(ntscRadioButton);
|
||||
}
|
||||
return ntscRadioButton;
|
||||
}
|
||||
private JCheckBox getDriveIconCheckBox() {
|
||||
if (driveIconCheckBox == null) {
|
||||
driveIconCheckBox = new JCheckBox("Drive Icon");
|
||||
}
|
||||
return driveIconCheckBox;
|
||||
}
|
||||
private JCheckBox getAccurateDiskCheckBox() {
|
||||
if (accurateDiskCheckBox == null) {
|
||||
accurateDiskCheckBox = new JCheckBox("Accurate Disk");
|
||||
}
|
||||
return accurateDiskCheckBox;
|
||||
}
|
||||
private JCheckBox getFullHeightCheckBox() {
|
||||
if (fullHeightCheckBox == null) {
|
||||
fullHeightCheckBox = new JCheckBox("Full Height");
|
||||
}
|
||||
return fullHeightCheckBox;
|
||||
}
|
||||
private DisplayShiftComboBox getDisplayShiftComboBox() {
|
||||
if (displayShiftComboBox == null) {
|
||||
displayShiftComboBox = new DisplayShiftComboBox();
|
||||
}
|
||||
return displayShiftComboBox;
|
||||
}
|
||||
private JLabel getDisplayShiftLabel() {
|
||||
if (displayShiftLabel == null) {
|
||||
displayShiftLabel = new JLabel("Vertical Display Shift");
|
||||
}
|
||||
return displayShiftLabel;
|
||||
}
|
||||
private JRadioButton getSid6581RadioButton() {
|
||||
if (sid6581RadioButton == null) {
|
||||
sid6581RadioButton = new JRadioButton("SID 6581");
|
||||
audioGroup.add(sid6581RadioButton);
|
||||
sid6581RadioButton.setSelected(true);
|
||||
sid6581RadioButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
return sid6581RadioButton;
|
||||
}
|
||||
private JRadioButton getSid8580RadioButton() {
|
||||
if (sid8580RadioButton == null) {
|
||||
sid8580RadioButton = new JRadioButton("SID 8580");
|
||||
audioGroup.add(sid8580RadioButton);
|
||||
}
|
||||
return sid8580RadioButton;
|
||||
}
|
||||
private JRadioButton getSid8580dRadioButton() {
|
||||
if (sid8580dRadioButton == null) {
|
||||
sid8580dRadioButton = new JRadioButton("SID 8580D");
|
||||
audioGroup.add(sid8580dRadioButton);
|
||||
}
|
||||
return sid8580dRadioButton;
|
||||
}
|
||||
private JCheckBox getNoAudioScaleCheckBox() {
|
||||
if (noAudioScaleCheckBox == null) {
|
||||
noAudioScaleCheckBox = new JCheckBox("No Audio Scale");
|
||||
}
|
||||
return noAudioScaleCheckBox;
|
||||
}
|
||||
private JCheckBox getBank0CheckBox() {
|
||||
if (bank0CheckBox == null) {
|
||||
bank0CheckBox = new JCheckBox("Bank 0 (3K @ $0400-$0FFF)");
|
||||
bank0CheckBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
calculateTotalRam();
|
||||
}
|
||||
});
|
||||
}
|
||||
return bank0CheckBox;
|
||||
}
|
||||
private JCheckBox getBank1CheckBox() {
|
||||
if (bank1CheckBox == null) {
|
||||
bank1CheckBox = new JCheckBox("Bank 1 (8K @ $2000-$3FFF)");
|
||||
bank1CheckBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
calculateTotalRam();
|
||||
}
|
||||
});
|
||||
}
|
||||
return bank1CheckBox;
|
||||
}
|
||||
private JCheckBox getBank2CheckBox() {
|
||||
if (bank2CheckBox == null) {
|
||||
bank2CheckBox = new JCheckBox("Bank 2 (8K @ $4000-$5FFF)");
|
||||
bank2CheckBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
calculateTotalRam();
|
||||
}
|
||||
});
|
||||
}
|
||||
return bank2CheckBox;
|
||||
}
|
||||
private JCheckBox getBank3CheckBox() {
|
||||
if (bank3CheckBox == null) {
|
||||
bank3CheckBox = new JCheckBox("Bank 3 (8K @ $6000-$7FFF)");
|
||||
bank3CheckBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
calculateTotalRam();
|
||||
}
|
||||
});
|
||||
}
|
||||
return bank3CheckBox;
|
||||
}
|
||||
private JCheckBox getBank5CheckBox() {
|
||||
if (bank5CheckBox == null) {
|
||||
bank5CheckBox = new JCheckBox("Bank 5 (8K @ $A000-$BFFF)");
|
||||
bank5CheckBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
calculateTotalRam();
|
||||
}
|
||||
});
|
||||
}
|
||||
return bank5CheckBox;
|
||||
}
|
||||
private JLabel getRamLabel() {
|
||||
if (ramLabel == null) {
|
||||
ramLabel = new JLabel("Ram Expansion: 0K");
|
||||
ramLabel.setFont(new Font("Tahoma", Font.BOLD, 11));
|
||||
}
|
||||
return ramLabel;
|
||||
}
|
||||
|
||||
private void calculateTotalRam()
|
||||
{
|
||||
int totalRam = 0;
|
||||
if (getBank0CheckBox().isSelected())
|
||||
{
|
||||
totalRam = totalRam + 3;
|
||||
}
|
||||
if (getBank1CheckBox().isSelected())
|
||||
{
|
||||
totalRam = totalRam + 8;
|
||||
}
|
||||
if (getBank2CheckBox().isSelected())
|
||||
{
|
||||
totalRam = totalRam + 8;
|
||||
}
|
||||
if (getBank3CheckBox().isSelected())
|
||||
{
|
||||
totalRam = totalRam + 8;
|
||||
}
|
||||
if (getBank5CheckBox().isSelected())
|
||||
{
|
||||
totalRam = totalRam + 8;
|
||||
}
|
||||
getRamLabel().setText("Ram Expansion: " + totalRam + "K");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,364 @@
|
|||
package se.lantz.gui.gameview;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.DefaultCellEditor;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableColumn;
|
||||
|
||||
import se.lantz.model.data.GameView;
|
||||
import se.lantz.model.data.ViewFilter;
|
||||
import se.lantz.util.DbConstants;
|
||||
|
||||
public class FilterPanel extends JPanel
|
||||
{
|
||||
private static final long serialVersionUID = 8720361450360137735L;
|
||||
|
||||
private JPanel filterOptionPanel;
|
||||
private JRadioButton matchAllRadioButton;
|
||||
private JRadioButton anyFilterRadioButton;
|
||||
private final ButtonGroup buttonGroup = new ButtonGroup();
|
||||
private JPanel tablePanel;
|
||||
private JPanel buttonPanel;
|
||||
private JButton addButton;
|
||||
private JButton removeButton;
|
||||
private JTable filterTable;
|
||||
private JScrollPane scrollPane;
|
||||
private JComboBox<String> fieldTableComboBox;
|
||||
private JComboBox<String> operatorTableComboBox;
|
||||
|
||||
private String[] tableColumns = { "Field", "Operator", "Value" };
|
||||
DefaultTableModel model;
|
||||
private GameView gameView;
|
||||
|
||||
public FilterPanel(GameView gameView)
|
||||
{
|
||||
this.gameView = gameView;
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_filterOptionPanel = new GridBagConstraints();
|
||||
gbc_filterOptionPanel.weightx = 1.0;
|
||||
gbc_filterOptionPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_filterOptionPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_filterOptionPanel.insets = new Insets(0, 3, 5, 3);
|
||||
gbc_filterOptionPanel.gridx = 0;
|
||||
gbc_filterOptionPanel.gridy = 0;
|
||||
add(getFilterOptionPanel(), gbc_filterOptionPanel);
|
||||
GridBagConstraints gbc_tablePanel = new GridBagConstraints();
|
||||
gbc_tablePanel.weighty = 1.0;
|
||||
gbc_tablePanel.weightx = 1.0;
|
||||
gbc_tablePanel.fill = GridBagConstraints.BOTH;
|
||||
gbc_tablePanel.gridx = 0;
|
||||
gbc_tablePanel.gridy = 1;
|
||||
add(getTablePanel(), gbc_tablePanel);
|
||||
GridBagConstraints gbc_buttonPanel = new GridBagConstraints();
|
||||
gbc_buttonPanel.weightx = 1.0;
|
||||
gbc_buttonPanel.anchor = GridBagConstraints.NORTH;
|
||||
gbc_buttonPanel.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_buttonPanel.gridx = 0;
|
||||
gbc_buttonPanel.gridy = 2;
|
||||
add(getButtonPanel(), gbc_buttonPanel);
|
||||
setupFromGameView();
|
||||
}
|
||||
|
||||
private JPanel getFilterOptionPanel()
|
||||
{
|
||||
if (filterOptionPanel == null)
|
||||
{
|
||||
filterOptionPanel = new JPanel();
|
||||
filterOptionPanel
|
||||
.setBorder(new TitledBorder(null, "Filter matching", TitledBorder.LEADING, TitledBorder.TOP, null, null));
|
||||
GridBagLayout gbl_filterOptionPanel = new GridBagLayout();
|
||||
gbl_filterOptionPanel.columnWidths = new int[] { 0, 0, 0 };
|
||||
gbl_filterOptionPanel.rowHeights = new int[] { 0, 0, 0 };
|
||||
gbl_filterOptionPanel.columnWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
|
||||
gbl_filterOptionPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
|
||||
filterOptionPanel.setLayout(gbl_filterOptionPanel);
|
||||
GridBagConstraints gbc_matchAllRadioButton = new GridBagConstraints();
|
||||
gbc_matchAllRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_matchAllRadioButton.insets = new Insets(0, 0, 0, 5);
|
||||
gbc_matchAllRadioButton.gridx = 0;
|
||||
gbc_matchAllRadioButton.gridy = 0;
|
||||
filterOptionPanel.add(getMatchAllRadioButton(), gbc_matchAllRadioButton);
|
||||
GridBagConstraints gbc_anyFilterRadioButton = new GridBagConstraints();
|
||||
gbc_anyFilterRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_anyFilterRadioButton.gridx = 0;
|
||||
gbc_anyFilterRadioButton.gridy = 1;
|
||||
filterOptionPanel.add(getAnyFilterRadioButton(), gbc_anyFilterRadioButton);
|
||||
}
|
||||
return filterOptionPanel;
|
||||
}
|
||||
|
||||
private JRadioButton getMatchAllRadioButton()
|
||||
{
|
||||
if (matchAllRadioButton == null)
|
||||
{
|
||||
matchAllRadioButton = new JRadioButton("All filters must match");
|
||||
buttonGroup.add(matchAllRadioButton);
|
||||
matchAllRadioButton.setSelected(this.gameView.isMatchAll());
|
||||
}
|
||||
return matchAllRadioButton;
|
||||
}
|
||||
|
||||
private JRadioButton getAnyFilterRadioButton()
|
||||
{
|
||||
if (anyFilterRadioButton == null)
|
||||
{
|
||||
anyFilterRadioButton = new JRadioButton("Any filter must match");
|
||||
buttonGroup.add(anyFilterRadioButton);
|
||||
anyFilterRadioButton.setSelected(!this.gameView.isMatchAll());
|
||||
}
|
||||
return anyFilterRadioButton;
|
||||
}
|
||||
|
||||
private JPanel getTablePanel()
|
||||
{
|
||||
if (tablePanel == null)
|
||||
{
|
||||
tablePanel = new JPanel();
|
||||
GridBagLayout gbl_tablePanel = new GridBagLayout();
|
||||
tablePanel.setLayout(gbl_tablePanel);
|
||||
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
||||
gbc_scrollPane.weighty = 1.0;
|
||||
gbc_scrollPane.weightx = 1.0;
|
||||
gbc_scrollPane.insets = new Insets(5, 5, 0, 5);
|
||||
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
||||
gbc_scrollPane.gridx = 0;
|
||||
gbc_scrollPane.gridy = 0;
|
||||
tablePanel.add(getScrollPane(), gbc_scrollPane);
|
||||
}
|
||||
return tablePanel;
|
||||
}
|
||||
|
||||
private JPanel getButtonPanel()
|
||||
{
|
||||
if (buttonPanel == null)
|
||||
{
|
||||
buttonPanel = new JPanel();
|
||||
GridBagLayout gbl_buttonPanel = new GridBagLayout();
|
||||
buttonPanel.setLayout(gbl_buttonPanel);
|
||||
GridBagConstraints gbc_addButton = new GridBagConstraints();
|
||||
gbc_addButton.anchor = GridBagConstraints.EAST;
|
||||
gbc_addButton.weightx = 1.0;
|
||||
gbc_addButton.insets = new Insets(5, 5, 5, 5);
|
||||
gbc_addButton.gridx = 0;
|
||||
gbc_addButton.gridy = 0;
|
||||
buttonPanel.add(getAddButton(), gbc_addButton);
|
||||
GridBagConstraints gbc_removeButton = new GridBagConstraints();
|
||||
gbc_removeButton.anchor = GridBagConstraints.EAST;
|
||||
gbc_removeButton.insets = new Insets(5, 0, 5, 5);
|
||||
gbc_removeButton.gridx = 1;
|
||||
gbc_removeButton.gridy = 0;
|
||||
buttonPanel.add(getRemoveButton(), gbc_removeButton);
|
||||
}
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private JButton getAddButton()
|
||||
{
|
||||
if (addButton == null)
|
||||
{
|
||||
addButton = new JButton("Add row");
|
||||
addButton.addActionListener(e -> {
|
||||
model.addRow(new String[] { DbConstants.TITLE, ViewFilter.BEGINS_WITH_TEXT, "" });
|
||||
});
|
||||
}
|
||||
return addButton;
|
||||
}
|
||||
|
||||
private JButton getRemoveButton()
|
||||
{
|
||||
if (removeButton == null)
|
||||
{
|
||||
removeButton = new JButton("Remove row");
|
||||
removeButton.addActionListener(e -> {
|
||||
model.removeRow(getFilterTable().getSelectedRow());
|
||||
if (model.getRowCount() > 0)
|
||||
{
|
||||
//Select last row
|
||||
getFilterTable().getSelectionModel().setSelectionInterval(model.getRowCount() - 1, model.getRowCount() - 1);
|
||||
}
|
||||
});
|
||||
removeButton.setEnabled(false);
|
||||
}
|
||||
return removeButton;
|
||||
}
|
||||
|
||||
private JTable getFilterTable()
|
||||
{
|
||||
if (filterTable == null)
|
||||
{
|
||||
|
||||
filterTable = new JTable();
|
||||
setupTable();
|
||||
}
|
||||
return filterTable;
|
||||
}
|
||||
|
||||
private JComboBox<String> getFieldTableComboBox()
|
||||
{
|
||||
if (fieldTableComboBox == null)
|
||||
{
|
||||
fieldTableComboBox = new JComboBox<>();
|
||||
fieldTableComboBox.addItem(DbConstants.TITLE);
|
||||
fieldTableComboBox.addItem(DbConstants.AUTHOR);
|
||||
fieldTableComboBox.addItem(DbConstants.COMPOSER);
|
||||
fieldTableComboBox.addItem(DbConstants.GENRE);
|
||||
fieldTableComboBox.addItem(DbConstants.YEAR);
|
||||
fieldTableComboBox.addItem(DbConstants.DESC);
|
||||
fieldTableComboBox.addItem(DbConstants.JOY1);
|
||||
fieldTableComboBox.addItem(DbConstants.JOY2);
|
||||
fieldTableComboBox.addItem(DbConstants.SYSTEM);
|
||||
|
||||
fieldTableComboBox.addActionListener(e -> {
|
||||
if (!fieldTableComboBox.getSelectedItem().equals(DbConstants.YEAR))
|
||||
{
|
||||
addStringOperators();
|
||||
}
|
||||
else
|
||||
{
|
||||
addIntOperators();
|
||||
}
|
||||
});
|
||||
}
|
||||
return fieldTableComboBox;
|
||||
}
|
||||
|
||||
private void addStringOperators()
|
||||
{
|
||||
getOperatorTableComboBox().removeAllItems();
|
||||
getOperatorTableComboBox().addItem(ViewFilter.BEGINS_WITH_TEXT);
|
||||
getOperatorTableComboBox().addItem(ViewFilter.ENDS_WITH_TEXT);
|
||||
getOperatorTableComboBox().addItem(ViewFilter.CONTAINS_TEXT);
|
||||
getOperatorTableComboBox().addItem(ViewFilter.EQUALS_TEXT);
|
||||
}
|
||||
|
||||
private void addIntOperators()
|
||||
{
|
||||
getOperatorTableComboBox().removeAllItems();
|
||||
getOperatorTableComboBox().addItem(ViewFilter.IS);
|
||||
getOperatorTableComboBox().addItem(ViewFilter.BEFORE);
|
||||
getOperatorTableComboBox().addItem(ViewFilter.AFTER);
|
||||
}
|
||||
|
||||
private JComboBox<String> getOperatorTableComboBox()
|
||||
{
|
||||
if (operatorTableComboBox == null)
|
||||
{
|
||||
operatorTableComboBox = new JComboBox<>();
|
||||
addStringOperators();
|
||||
}
|
||||
return operatorTableComboBox;
|
||||
}
|
||||
|
||||
private JScrollPane getScrollPane()
|
||||
{
|
||||
if (scrollPane == null)
|
||||
{
|
||||
scrollPane = new JScrollPane();
|
||||
scrollPane.setViewportView(getFilterTable());
|
||||
}
|
||||
return scrollPane;
|
||||
}
|
||||
|
||||
private void setupTable()
|
||||
{
|
||||
filterTable.putClientProperty("terminateEditOnFocusLost", true);
|
||||
model = new DefaultTableModel(tableColumns, 0)
|
||||
{
|
||||
@Override
|
||||
public void setValueAt(Object value, int row, int column)
|
||||
{
|
||||
if (column == 0)
|
||||
{
|
||||
if (!value.equals(DbConstants.YEAR) && getValueAt(row, 0).equals(DbConstants.YEAR))
|
||||
{
|
||||
setValueAt(ViewFilter.BEGINS_WITH_TEXT, row, 1);
|
||||
}
|
||||
if (value.equals(DbConstants.YEAR) && !getValueAt(row, 0).equals(DbConstants.YEAR))
|
||||
{
|
||||
setValueAt(ViewFilter.IS, row, 1);
|
||||
}
|
||||
}
|
||||
super.setValueAt(value, row, column);
|
||||
}
|
||||
};
|
||||
filterTable.setModel(model);
|
||||
|
||||
TableColumn fieldColumn = filterTable.getColumnModel().getColumn(0);
|
||||
fieldColumn.setCellEditor(new DefaultCellEditor(getFieldTableComboBox()));
|
||||
TableColumn operatorColumn = filterTable.getColumnModel().getColumn(1);
|
||||
//Set operator combobox editor, updates based on selected field.
|
||||
operatorColumn.setCellEditor(new DefaultCellEditor(getOperatorTableComboBox())
|
||||
{
|
||||
public Component getTableCellEditorComponent(JTable table,
|
||||
Object value,
|
||||
boolean isSelected,
|
||||
int row,
|
||||
int column)
|
||||
{
|
||||
if (column == 1)
|
||||
{
|
||||
String field = (String) table.getModel().getValueAt(row, 0);
|
||||
if (field.equals(DbConstants.YEAR))
|
||||
{
|
||||
addIntOperators();
|
||||
}
|
||||
else
|
||||
{
|
||||
addStringOperators();
|
||||
}
|
||||
}
|
||||
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
|
||||
}
|
||||
});
|
||||
|
||||
filterTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
filterTable.setColumnSelectionAllowed(false);
|
||||
filterTable.getSelectionModel().addListSelectionListener(e -> {
|
||||
if (!e.getValueIsAdjusting())
|
||||
{
|
||||
getRemoveButton().setEnabled(filterTable.getSelectedRow() > -1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupFromGameView()
|
||||
{
|
||||
getMatchAllRadioButton().setSelected(this.gameView.isMatchAll());
|
||||
|
||||
for (ViewFilter filter : this.gameView.getViewFilters())
|
||||
{
|
||||
model.addRow(new String[] { filter.getField(), filter.getOperator(), filter.getFilterData() });
|
||||
}
|
||||
}
|
||||
|
||||
public void updateGameView()
|
||||
{
|
||||
//Set fields in game view from UI
|
||||
this.gameView.setMatchAll(getMatchAllRadioButton().isSelected());
|
||||
List<ViewFilter> filterList = new ArrayList<>();
|
||||
for (int i = 0; i < model.getRowCount(); i++)
|
||||
{
|
||||
filterList.add(new ViewFilter((String) model.getValueAt(i, 0),
|
||||
(String) model.getValueAt(i, 1),
|
||||
(String) model.getValueAt(i, 2)));
|
||||
}
|
||||
this.gameView.setViewFilters(filterList);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package se.lantz.gui.gameview;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Frame;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import se.lantz.gui.BaseDialog;
|
||||
import se.lantz.model.data.GameView;
|
||||
|
||||
public class GameViewEditDialog extends BaseDialog
|
||||
{
|
||||
|
||||
private FilterPanel filterPanel;
|
||||
private ViewNamePanel namePanel;
|
||||
|
||||
public GameViewEditDialog(Frame owner, GameView gameView)
|
||||
{
|
||||
super(owner);
|
||||
JPanel content = new JPanel();
|
||||
content.setLayout(new BorderLayout());
|
||||
content.add(getViewNamePanel(gameView), BorderLayout.NORTH);
|
||||
content.add(getFilterPanel(gameView), BorderLayout.CENTER);
|
||||
|
||||
addContent(content);
|
||||
}
|
||||
|
||||
private FilterPanel getFilterPanel(GameView gameView)
|
||||
{
|
||||
if (filterPanel == null)
|
||||
{
|
||||
filterPanel = new FilterPanel(gameView);
|
||||
}
|
||||
return filterPanel;
|
||||
}
|
||||
|
||||
private ViewNamePanel getViewNamePanel(GameView gameView)
|
||||
{
|
||||
if (namePanel == null)
|
||||
{
|
||||
namePanel = new ViewNamePanel(gameView);
|
||||
}
|
||||
return namePanel;
|
||||
}
|
||||
|
||||
public void updateGameViewAfterClosing() {
|
||||
namePanel.updateGameView();
|
||||
filterPanel.updateGameView();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package se.lantz.gui.gameview;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import se.lantz.gui.MainWindow;
|
||||
import se.lantz.model.MainViewModel;
|
||||
import se.lantz.model.data.GameView;
|
||||
|
||||
public class GameViewManager
|
||||
{
|
||||
|
||||
private JComboBox viewCombobox;
|
||||
private MainWindow mainWindow;
|
||||
private final MainViewModel uiModel;
|
||||
|
||||
public GameViewManager(JComboBox viewCombobox, MainViewModel uiModel)
|
||||
{
|
||||
this.viewCombobox = viewCombobox;
|
||||
this.uiModel = uiModel;
|
||||
}
|
||||
|
||||
public void openViewEditDialog(GameView gameView)
|
||||
{
|
||||
mainWindow = (MainWindow)SwingUtilities.getAncestorOfClass(MainWindow.class, viewCombobox);
|
||||
GameViewEditDialog dialog = new GameViewEditDialog(mainWindow, gameView);
|
||||
if (gameView.getGameViewId() == 0)
|
||||
{
|
||||
dialog.setTitle("Add game view");
|
||||
}
|
||||
else
|
||||
{
|
||||
dialog.setTitle("Edit game view");
|
||||
}
|
||||
dialog.pack();
|
||||
dialog.setLocationRelativeTo(mainWindow);
|
||||
if (dialog.showDialog())
|
||||
{
|
||||
//Update gameView instance with edited values in the dialog
|
||||
dialog.updateGameViewAfterClosing();
|
||||
boolean newGameView = gameView.getGameViewId() == 0;
|
||||
//Save in Dd
|
||||
uiModel.saveGameView(gameView);
|
||||
if (newGameView)
|
||||
{
|
||||
//new view, add to combobox
|
||||
viewCombobox.addItem(gameView);
|
||||
viewCombobox.setSelectedItem(gameView);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Trigger reload of game view after editing
|
||||
uiModel.setSelectedGameView(gameView);
|
||||
viewCombobox.invalidate();
|
||||
viewCombobox.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package se.lantz.gui.gameview;
|
||||
|
||||
import java.awt.LayoutManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import java.awt.GridBagLayout;
|
||||
import javax.swing.JLabel;
|
||||
import java.awt.GridBagConstraints;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import se.lantz.model.data.GameView;
|
||||
import se.lantz.model.data.ViewFilter;
|
||||
|
||||
import java.awt.Insets;
|
||||
|
||||
public class ViewNamePanel extends JPanel
|
||||
{
|
||||
private JLabel nameLabel;
|
||||
private JTextField textField;
|
||||
private GameView gameView;
|
||||
|
||||
public ViewNamePanel(GameView gameView)
|
||||
{
|
||||
this.gameView = gameView;
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
gridBagLayout.columnWidths = new int[]{0, 0};
|
||||
gridBagLayout.rowHeights = new int[]{0, 0, 0};
|
||||
gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
|
||||
gridBagLayout.rowWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_nameLabel = new GridBagConstraints();
|
||||
gbc_nameLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_nameLabel.insets = new Insets(10, 5, 5, 5);
|
||||
gbc_nameLabel.gridx = 0;
|
||||
gbc_nameLabel.gridy = 0;
|
||||
add(getNameLabel(), gbc_nameLabel);
|
||||
GridBagConstraints gbc_textField = new GridBagConstraints();
|
||||
gbc_textField.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_textField.anchor = GridBagConstraints.WEST;
|
||||
gbc_textField.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_textField.gridx = 0;
|
||||
gbc_textField.gridy = 1;
|
||||
add(getTextField(), gbc_textField);
|
||||
|
||||
getTextField().setText(gameView.getName());
|
||||
}
|
||||
private JLabel getNameLabel() {
|
||||
if (nameLabel == null) {
|
||||
nameLabel = new JLabel("View name");
|
||||
}
|
||||
return nameLabel;
|
||||
}
|
||||
private JTextField getTextField() {
|
||||
if (textField == null) {
|
||||
textField = new JTextField();
|
||||
textField.setColumns(10);
|
||||
}
|
||||
return textField;
|
||||
}
|
||||
|
||||
public void updateGameView()
|
||||
{
|
||||
//Set name in game view from UI
|
||||
this.gameView.setName(getTextField().getText());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import java.awt.Frame;
|
||||
|
||||
import se.lantz.gui.BaseDialog;
|
||||
import se.lantz.model.ImportManager;
|
||||
|
||||
public class ImportOptionsDialog extends BaseDialog
|
||||
{
|
||||
private ImportOptionsPanel panel;
|
||||
|
||||
public ImportOptionsDialog(Frame owner)
|
||||
{
|
||||
super(owner);
|
||||
setTitle("Import game carousel");
|
||||
addContent(getImportOptionsPanel());
|
||||
getOkButton().setText("Import");
|
||||
}
|
||||
|
||||
private ImportOptionsPanel getImportOptionsPanel() {
|
||||
if (panel == null) {
|
||||
panel = new ImportOptionsPanel();
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
public ImportManager.Options getSelectedOption()
|
||||
{
|
||||
return getImportOptionsPanel().getSelectedOption();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
|
||||
import se.lantz.model.ImportManager;
|
||||
import javax.swing.ButtonGroup;
|
||||
|
||||
public class ImportOptionsPanel extends JPanel
|
||||
{
|
||||
private JLabel infoLabel;
|
||||
private JRadioButton overwriteRadioButton;
|
||||
private JRadioButton skipRadioButton;
|
||||
private final ButtonGroup buttonGroup = new ButtonGroup();
|
||||
private JLabel matchLabel;
|
||||
|
||||
public ImportOptionsPanel()
|
||||
{
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_infoLabel = new GridBagConstraints();
|
||||
gbc_infoLabel.anchor = GridBagConstraints.WEST;
|
||||
gbc_infoLabel.weightx = 1.0;
|
||||
gbc_infoLabel.insets = new Insets(15, 10, 5, 10);
|
||||
gbc_infoLabel.gridx = 0;
|
||||
gbc_infoLabel.gridy = 0;
|
||||
add(getInfoLabel(), gbc_infoLabel);
|
||||
GridBagConstraints gbc_skipRadioButton = new GridBagConstraints();
|
||||
gbc_skipRadioButton.weightx = 1.0;
|
||||
gbc_skipRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_skipRadioButton.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_skipRadioButton.gridx = 0;
|
||||
gbc_skipRadioButton.gridy = 1;
|
||||
add(getSkipRadioButton(), gbc_skipRadioButton);
|
||||
GridBagConstraints gbc_overwriteRadioButton = new GridBagConstraints();
|
||||
gbc_overwriteRadioButton.weightx = 1.0;
|
||||
gbc_overwriteRadioButton.insets = new Insets(0, 5, 5, 0);
|
||||
gbc_overwriteRadioButton.anchor = GridBagConstraints.WEST;
|
||||
gbc_overwriteRadioButton.gridx = 0;
|
||||
gbc_overwriteRadioButton.gridy = 2;
|
||||
add(getOverwriteRadioButton(), gbc_overwriteRadioButton);
|
||||
GridBagConstraints gbc_matchLabel = new GridBagConstraints();
|
||||
gbc_matchLabel.insets = new Insets(20, 10, 15, 10);
|
||||
gbc_matchLabel.anchor = GridBagConstraints.NORTHWEST;
|
||||
gbc_matchLabel.weighty = 1.0;
|
||||
gbc_matchLabel.weightx = 1.0;
|
||||
gbc_matchLabel.gridx = 0;
|
||||
gbc_matchLabel.gridy = 3;
|
||||
add(getMatchLabel(), gbc_matchLabel);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
private JLabel getInfoLabel()
|
||||
{
|
||||
if (infoLabel == null)
|
||||
{
|
||||
infoLabel =
|
||||
new JLabel("How shall already existing game entries in the database be handled?");
|
||||
}
|
||||
return infoLabel;
|
||||
}
|
||||
private JRadioButton getOverwriteRadioButton() {
|
||||
if (overwriteRadioButton == null) {
|
||||
overwriteRadioButton = new JRadioButton("Overwrite with imported game");
|
||||
buttonGroup.add(overwriteRadioButton);
|
||||
}
|
||||
return overwriteRadioButton;
|
||||
}
|
||||
private JRadioButton getSkipRadioButton() {
|
||||
if (skipRadioButton == null) {
|
||||
skipRadioButton = new JRadioButton("Keep existing game in database");
|
||||
skipRadioButton.setSelected(true);
|
||||
buttonGroup.add(skipRadioButton);
|
||||
}
|
||||
return skipRadioButton;
|
||||
}
|
||||
|
||||
public ImportManager.Options getSelectedOption()
|
||||
{
|
||||
ImportManager.Options returnValue = ImportManager.Options.SKIP;
|
||||
if (getOverwriteRadioButton().isSelected())
|
||||
{
|
||||
returnValue = ImportManager.Options.OVERWRITE;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
private JLabel getMatchLabel() {
|
||||
if (matchLabel == null) {
|
||||
matchLabel = new JLabel("Games are matched by title, case insensitive.");
|
||||
}
|
||||
return matchLabel;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class ImportProgressDialog extends JDialog
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ImportProgressPanel panel;
|
||||
private JFrame frame;
|
||||
|
||||
public ImportProgressDialog(JFrame frame)
|
||||
{
|
||||
this.setModal(true);
|
||||
this.setIconImage(new ImageIcon(getClass().getResource("/se/lantz/FrameIcon.png")).getImage());
|
||||
this.frame = frame;
|
||||
this.setTitle("Import games");
|
||||
this.add(getImportProgressPanel());
|
||||
setSize(900, 600);
|
||||
setAlwaysOnTop(true);
|
||||
setLocationRelativeTo(frame);
|
||||
}
|
||||
|
||||
public void updateProgress(String progressText, String infoText)
|
||||
{
|
||||
getImportProgressPanel().updateProgress(progressText, infoText);
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
public void finish()
|
||||
{
|
||||
getImportProgressPanel().finish();
|
||||
}
|
||||
|
||||
public ImportProgressPanel getImportProgressPanel()
|
||||
{
|
||||
if (panel == null)
|
||||
{
|
||||
panel = new ImportProgressPanel();
|
||||
panel.getCloseButton().addActionListener(e -> setVisible(false));
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
public class ImportProgressPanel extends JPanel
|
||||
{
|
||||
private JProgressBar progressBar;
|
||||
private JTextArea textArea;
|
||||
private JScrollPane textScrollPane;
|
||||
private JButton closeButton;
|
||||
|
||||
public ImportProgressPanel()
|
||||
{
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
setLayout(gridBagLayout);
|
||||
GridBagConstraints gbc_progressBar = new GridBagConstraints();
|
||||
gbc_progressBar.weightx = 1.0;
|
||||
gbc_progressBar.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc_progressBar.insets = new Insets(10, 5, 5, 5);
|
||||
gbc_progressBar.gridx = 0;
|
||||
gbc_progressBar.gridy = 0;
|
||||
add(getProgressBar(), gbc_progressBar);
|
||||
GridBagConstraints gbc_textScrollPane = new GridBagConstraints();
|
||||
gbc_textScrollPane.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_textScrollPane.weighty = 1.0;
|
||||
gbc_textScrollPane.weightx = 1.0;
|
||||
gbc_textScrollPane.fill = GridBagConstraints.BOTH;
|
||||
gbc_textScrollPane.gridx = 0;
|
||||
gbc_textScrollPane.gridy = 1;
|
||||
add(getTextScrollPane(), gbc_textScrollPane);
|
||||
GridBagConstraints gbc_closeButton = new GridBagConstraints();
|
||||
gbc_closeButton.insets = new Insets(0, 5, 5, 5);
|
||||
gbc_closeButton.gridx = 0;
|
||||
gbc_closeButton.gridy = 2;
|
||||
add(getCloseButton(), gbc_closeButton);
|
||||
}
|
||||
|
||||
private JProgressBar getProgressBar()
|
||||
{
|
||||
if (progressBar == null)
|
||||
{
|
||||
progressBar = new JProgressBar();
|
||||
progressBar.setIndeterminate(true);
|
||||
}
|
||||
return progressBar;
|
||||
}
|
||||
|
||||
private JTextArea getTextArea()
|
||||
{
|
||||
if (textArea == null)
|
||||
{
|
||||
textArea = new JTextArea();
|
||||
textArea.setEditable(false);
|
||||
}
|
||||
return textArea;
|
||||
}
|
||||
|
||||
private JScrollPane getTextScrollPane()
|
||||
{
|
||||
if (textScrollPane == null)
|
||||
{
|
||||
textScrollPane = new JScrollPane();
|
||||
textScrollPane.setViewportView(getTextArea());
|
||||
}
|
||||
return textScrollPane;
|
||||
}
|
||||
|
||||
JButton getCloseButton()
|
||||
{
|
||||
if (closeButton == null)
|
||||
{
|
||||
closeButton = new JButton("Close");
|
||||
closeButton.setEnabled(false);
|
||||
}
|
||||
return closeButton;
|
||||
}
|
||||
|
||||
void updateProgress(String progressText, String infoText)
|
||||
{
|
||||
getTextArea().append(infoText);
|
||||
}
|
||||
|
||||
public void finish()
|
||||
{
|
||||
getCloseButton().setEnabled(true);
|
||||
getProgressBar().setIndeterminate(false);
|
||||
getProgressBar().setValue(getProgressBar().getMaximum());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package se.lantz.gui.imports;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import se.lantz.model.ImportManager;
|
||||
|
||||
public class ImportWorker extends SwingWorker<Void, String>
|
||||
{
|
||||
|
||||
private ImportManager importManager;
|
||||
private ImportProgressDialog dialog;
|
||||
|
||||
public ImportWorker(ImportManager importManager, ImportProgressDialog dialog)
|
||||
{
|
||||
this.importManager = importManager;
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception
|
||||
{
|
||||
//TODO: These are the steps to perform:
|
||||
//-Read gameinfo files
|
||||
//-Convert into db rows
|
||||
//-Check which rows (games) are to be updated/added
|
||||
//-Update db
|
||||
//-Copy screenshots/covers/games for all that has been updated
|
||||
//-Cleanup
|
||||
|
||||
publish("Reading game info files...");
|
||||
StringBuilder infoBuilder = new StringBuilder();
|
||||
importManager.readGameInfoFiles(infoBuilder);
|
||||
publish(infoBuilder.toString());
|
||||
|
||||
importManager.convertIntoDbRows();
|
||||
publish("Importing to db...");
|
||||
publish(importManager.insertRowsIntoDb().toString());
|
||||
publish("Copy screenshots, covers and game files...");
|
||||
publish(importManager.copyFiles().toString());
|
||||
importManager.clearAfterImport();
|
||||
publish("Done!");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(List<String> chunks)
|
||||
{
|
||||
for (String value : chunks)
|
||||
{
|
||||
dialog.updateProgress(value, value + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done()
|
||||
{
|
||||
dialog.finish();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
|
||||
/**
|
||||
* Adds propertyChange support
|
||||
*
|
||||
* @author Mikael
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractModel
|
||||
{
|
||||
|
||||
protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
||||
|
||||
protected boolean dataChanged = false;
|
||||
|
||||
private boolean disable;
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener)
|
||||
{
|
||||
propertyChangeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener)
|
||||
{
|
||||
propertyChangeSupport.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
protected void notifyChange()
|
||||
{
|
||||
if (!disable)
|
||||
{
|
||||
dataChanged = true;
|
||||
propertyChangeSupport.firePropertyChange("notify", null, "");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDataChanged()
|
||||
{
|
||||
return dataChanged;
|
||||
}
|
||||
|
||||
public void resetDataChanged()
|
||||
{
|
||||
dataChanged = false;
|
||||
propertyChangeSupport.firePropertyChange("notify", null, "");
|
||||
}
|
||||
|
||||
public void disableChangeNotification(boolean disable)
|
||||
{
|
||||
this.disable = disable;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
|
||||
import se.lantz.model.data.GameListData;
|
||||
|
||||
public class GameListModel extends DefaultListModel<GameListData>
|
||||
{
|
||||
void notifySave()
|
||||
{
|
||||
fireContentsChanged(this, 0, getSize()-1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.CopyOption;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.util.ExceptionHandler;
|
||||
|
||||
public class ImportManager
|
||||
{
|
||||
public enum Options
|
||||
{
|
||||
SKIP, OVERWRITE;
|
||||
};
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ImportManager.class);
|
||||
|
||||
Path srcParentFolder;
|
||||
Path srcCoversFolder;
|
||||
Path srcGamesFolder;
|
||||
Path srcScreensFolder;
|
||||
|
||||
Map<Path, List<String>> gameInfoFilesMap = new HashMap<>();
|
||||
List<String> dbRowDataList = new ArrayList<>();
|
||||
|
||||
private MainViewModel uiModel;
|
||||
private Options selectedOption;
|
||||
|
||||
public ImportManager(MainViewModel uiModel)
|
||||
{
|
||||
this.uiModel = uiModel;
|
||||
}
|
||||
|
||||
public void setSelectedOption(Options option)
|
||||
{
|
||||
this.selectedOption = option;
|
||||
}
|
||||
|
||||
public boolean checkSelectedFolder(Path folder)
|
||||
{
|
||||
|
||||
logger.debug("Selected folder: {}", folder.toString());
|
||||
|
||||
srcParentFolder = folder.resolve("games");
|
||||
srcCoversFolder = srcParentFolder.resolve("covers");
|
||||
srcGamesFolder = srcParentFolder.resolve("games");
|
||||
srcScreensFolder = srcParentFolder.resolve("screens");
|
||||
|
||||
logger.debug("parent folder: " + srcParentFolder);
|
||||
logger.debug("covers folder: " + srcCoversFolder);
|
||||
logger.debug("games folder: " + srcGamesFolder);
|
||||
logger.debug("screens folder: " + srcScreensFolder);
|
||||
|
||||
// Verify that subfolders are available
|
||||
if (Files.exists(srcParentFolder, LinkOption.NOFOLLOW_LINKS) &&
|
||||
Files.exists(srcCoversFolder, LinkOption.NOFOLLOW_LINKS) &&
|
||||
Files.exists(srcGamesFolder, LinkOption.NOFOLLOW_LINKS) &&
|
||||
Files.exists(srcScreensFolder, LinkOption.NOFOLLOW_LINKS))
|
||||
{
|
||||
logger.debug("A valid directory!");
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("An ivalid directory!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void readGameInfoFiles(StringBuilder infoBuilder)
|
||||
{
|
||||
gameInfoFilesMap.clear();
|
||||
|
||||
try (Stream<Path> filePathStream = Files.walk(srcParentFolder, 1))
|
||||
{
|
||||
filePathStream.forEach(filePath -> {
|
||||
if (Files.isRegularFile(filePath))
|
||||
{
|
||||
infoBuilder.append("Reading game info from ");
|
||||
infoBuilder.append(filePath);
|
||||
infoBuilder.append("\n");
|
||||
gameInfoFilesMap.put(filePath, readFileInList(filePath));
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not read gameInfo files");
|
||||
}
|
||||
}
|
||||
|
||||
public void convertIntoDbRows()
|
||||
{
|
||||
// Construct a List of comma separated strings with all info correctly added.
|
||||
gameInfoFilesMap.values().stream().forEach(fileLines -> extractInfoIntoRowString(fileLines));
|
||||
}
|
||||
|
||||
public StringBuilder insertRowsIntoDb()
|
||||
{
|
||||
return uiModel.importGameInfo(dbRowDataList, selectedOption);
|
||||
}
|
||||
|
||||
private void extractInfoIntoRowString(List<String> fileLines)
|
||||
{
|
||||
String title = "";
|
||||
String year = "";
|
||||
String author = "";
|
||||
String composer = "";
|
||||
String genre = "";
|
||||
String description = "";
|
||||
String gamefile = "";
|
||||
String coverfile = "";
|
||||
String screen1file = "";
|
||||
String screen2file = "";
|
||||
String joy1config = "";
|
||||
String joy2config = "";
|
||||
String advanced = "";
|
||||
|
||||
for (String line : fileLines)
|
||||
{
|
||||
if (line.startsWith("T:"))
|
||||
{
|
||||
title = line.substring(2);
|
||||
}
|
||||
else if (line.startsWith("Y:"))
|
||||
{
|
||||
year = line.substring(2);
|
||||
}
|
||||
else if (line.startsWith("A:"))
|
||||
{
|
||||
author = line.substring(2);
|
||||
}
|
||||
else if (line.startsWith("M:"))
|
||||
{
|
||||
composer = line.substring(2);
|
||||
}
|
||||
else if (line.startsWith("E:"))
|
||||
{
|
||||
genre = line.substring(2);
|
||||
}
|
||||
else if (line.startsWith("D:en"))
|
||||
{
|
||||
description = line.replaceAll("\"", "\"\"").substring(5);
|
||||
}
|
||||
else if (line.startsWith("F:"))
|
||||
{
|
||||
gamefile = line.substring(2);
|
||||
if (gamefile.lastIndexOf("/") > -1)
|
||||
{
|
||||
gamefile = gamefile.substring(gamefile.lastIndexOf("/")+1);
|
||||
}
|
||||
}
|
||||
else if (line.startsWith("C:"))
|
||||
{
|
||||
coverfile = line.substring(2);
|
||||
if (coverfile.lastIndexOf("/") > -1)
|
||||
{
|
||||
coverfile = coverfile.substring(coverfile.lastIndexOf("/")+1);
|
||||
}
|
||||
}
|
||||
else if (line.startsWith("G:"))
|
||||
{
|
||||
if (screen1file.isEmpty())
|
||||
{
|
||||
screen1file = line.substring(2);
|
||||
if (screen1file.lastIndexOf("/") > -1)
|
||||
{
|
||||
screen1file = screen1file.substring(screen1file.lastIndexOf("/")+1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen2file = line.substring(2);
|
||||
if (screen2file.lastIndexOf("/") > -1)
|
||||
{
|
||||
screen2file = screen2file.substring(screen2file.lastIndexOf("/")+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (line.startsWith("J:1"))
|
||||
{
|
||||
joy1config = line;
|
||||
}
|
||||
else if (line.startsWith("J:2"))
|
||||
{
|
||||
joy2config = line;
|
||||
}
|
||||
else if (line.startsWith("X:"))
|
||||
{
|
||||
advanced = line.substring(2);
|
||||
}
|
||||
}
|
||||
// Construct a data row
|
||||
List<String> list = Arrays.asList(title,
|
||||
year,
|
||||
author,
|
||||
composer,
|
||||
genre,
|
||||
description,
|
||||
gamefile,
|
||||
coverfile,
|
||||
screen1file,
|
||||
screen2file,
|
||||
joy1config,
|
||||
joy2config,
|
||||
advanced);
|
||||
String result = String.join("\",\"", list);
|
||||
result = "\"" + result + "\"";
|
||||
dbRowDataList.add(result);
|
||||
}
|
||||
|
||||
private List<String> readFileInList(Path filePath)
|
||||
{
|
||||
List<String> lines = Collections.emptyList();
|
||||
try
|
||||
{
|
||||
lines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not read files in list");
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
public StringBuilder copyFiles()
|
||||
{
|
||||
StringBuilder infoBuilder = new StringBuilder();
|
||||
//Copy with the existing file names. At export convert to a name that works with the maxi tool if needed.
|
||||
dbRowDataList.stream().forEach(dbRowData -> copyFiles(dbRowData, infoBuilder));
|
||||
return infoBuilder;
|
||||
}
|
||||
|
||||
public void copyFiles(String dbRowData, StringBuilder infoBuilder)
|
||||
{
|
||||
String coverName = "";
|
||||
String screen1Name = "";
|
||||
String screen2Name = "";
|
||||
String gameName = "";
|
||||
|
||||
String[] splittedForPaths = dbRowData.split("\",\"");
|
||||
|
||||
gameName = splittedForPaths[6];
|
||||
coverName = splittedForPaths[7];
|
||||
screen1Name = splittedForPaths[8];
|
||||
screen2Name = splittedForPaths[9];
|
||||
//Copy!
|
||||
Path coverPath = srcCoversFolder.resolve(coverName);
|
||||
Path targetPath = Paths.get("./covers/" + coverName);
|
||||
|
||||
Path screens1Path = srcScreensFolder.resolve(screen1Name);
|
||||
Path targetScreen1Path = Paths.get("./screens/" + screen1Name);
|
||||
|
||||
Path screens2Path = srcScreensFolder.resolve(screen2Name);
|
||||
Path targetScreen2Path = Paths.get("./screens/" + screen2Name);
|
||||
|
||||
Path gamePath = srcGamesFolder.resolve(gameName);
|
||||
Path targetGamePath = Paths.get("./games/" + gameName);
|
||||
|
||||
try
|
||||
{
|
||||
infoBuilder.append("Copying cover from ");
|
||||
infoBuilder.append(coverPath.toString());
|
||||
infoBuilder.append("\n");
|
||||
logger.debug("RowData = {}", dbRowData);
|
||||
Files.copy(coverPath, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
infoBuilder.append("Copying screenshot from ");
|
||||
infoBuilder.append(screens1Path.toString());
|
||||
infoBuilder.append("\n");
|
||||
Files.copy(screens1Path, targetScreen1Path, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
infoBuilder.append("Copying screenshot from ");
|
||||
infoBuilder.append(screens2Path.toString());
|
||||
infoBuilder.append("\n");
|
||||
Files.copy(screens2Path, targetScreen2Path, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
infoBuilder.append("Copying game file from ");
|
||||
infoBuilder.append(gamePath.toString());
|
||||
infoBuilder.append("\n");
|
||||
Files.copy(gamePath, targetGamePath, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ExceptionHandler.handleException(e, "Could not copy files");
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAfterImport()
|
||||
{
|
||||
dbRowDataList.clear();
|
||||
gameInfoFilesMap.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,278 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Objects;
|
||||
|
||||
import se.lantz.util.FileManager;
|
||||
|
||||
public class InfoModel extends AbstractModel
|
||||
{
|
||||
private String title = "";
|
||||
//Use this when saving cover/screen/game files: If the title has been changed the files shall be renamed.
|
||||
private String titleInDb = "";
|
||||
private String description = "";
|
||||
private int year = 0;
|
||||
private String genre = "";
|
||||
private String composer = "";
|
||||
private String author = "";
|
||||
private String gamesFile = "";
|
||||
private String coverFile = "";
|
||||
private String screens1File = "";
|
||||
private String screens2File = "";
|
||||
|
||||
//These images have there original sizes. Scale cover to 122x175 once storing it
|
||||
private BufferedImage coverImage;
|
||||
private BufferedImage screen1Image;
|
||||
private BufferedImage screen2Image;
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitleFromDb(String title)
|
||||
{
|
||||
titleInDb = title;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitleInDb()
|
||||
{
|
||||
return titleInDb;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
String old = getTitle();
|
||||
this.title = title;
|
||||
if (!Objects.equals(old, title))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
String old = getDescription();
|
||||
this.description = description;
|
||||
if (!Objects.equals(old, description))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public int getYear()
|
||||
{
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(int year)
|
||||
{
|
||||
int old = getYear();
|
||||
this.year = year;
|
||||
if (old != year)
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getGenre()
|
||||
{
|
||||
return genre;
|
||||
}
|
||||
|
||||
public void setGenre(String genre)
|
||||
{
|
||||
String old = getGenre();
|
||||
this.genre = genre;
|
||||
if (!Objects.equals(old, genre))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getComposer()
|
||||
{
|
||||
return composer;
|
||||
}
|
||||
|
||||
public void setComposer(String composer)
|
||||
{
|
||||
String old = getComposer();
|
||||
this.composer = composer;
|
||||
if (!Objects.equals(old, composer))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getAuthor()
|
||||
{
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author)
|
||||
{
|
||||
String old = getAuthor();
|
||||
this.author = author;
|
||||
if (!Objects.equals(old, author))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getGamesFile()
|
||||
{
|
||||
return gamesFile;
|
||||
}
|
||||
|
||||
public void setGamesFile(String gamesFile)
|
||||
{
|
||||
String old = getGamesFile();
|
||||
this.gamesFile = gamesFile;
|
||||
if (!Objects.equals(old, gamesFile))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getCoverFile()
|
||||
{
|
||||
return coverFile;
|
||||
}
|
||||
|
||||
public void setCoverFile(String coverFile)
|
||||
{
|
||||
String old = getCoverFile();
|
||||
this.coverFile = coverFile;
|
||||
if (!Objects.equals(old, coverFile))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getScreens1File()
|
||||
{
|
||||
return screens1File;
|
||||
}
|
||||
|
||||
public void setScreens1File(String screens1File)
|
||||
{
|
||||
String old = getScreens1File();
|
||||
this.screens1File = screens1File;
|
||||
if (!Objects.equals(old, screens1File))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getScreens2File()
|
||||
{
|
||||
return screens2File;
|
||||
}
|
||||
|
||||
public void setScreens2File(String screens2File)
|
||||
{
|
||||
String old = getScreens2File();
|
||||
this.screens2File = screens2File;
|
||||
if (!Objects.equals(old, screens2File))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getCoverImage()
|
||||
{
|
||||
return coverImage;
|
||||
}
|
||||
|
||||
public void setCoverImage(BufferedImage newCoverImage)
|
||||
{
|
||||
BufferedImage old = getCoverImage();
|
||||
this.coverImage = newCoverImage;
|
||||
if (!Objects.equals(old, newCoverImage))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getScreen1Image()
|
||||
{
|
||||
return screen1Image;
|
||||
}
|
||||
|
||||
public void setScreen1Image(BufferedImage newScreen1Image)
|
||||
{
|
||||
BufferedImage old = getScreen1Image();
|
||||
this.screen1Image = newScreen1Image;
|
||||
if (!Objects.equals(old, newScreen1Image))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getScreen2Image()
|
||||
{
|
||||
return screen2Image;
|
||||
}
|
||||
|
||||
public void setScreen2Image(BufferedImage newScreen2Image)
|
||||
{
|
||||
BufferedImage old = getScreen2Image();
|
||||
this.screen2Image = newScreen2Image;
|
||||
if (!Objects.equals(old, newScreen2Image))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFileNames()
|
||||
{
|
||||
disableChangeNotification(true);
|
||||
String fileName = FileManager.generateFileNameFromTitle(this.title);
|
||||
if (!getCoverFile().isEmpty() || getCoverImage() != null)
|
||||
{
|
||||
setCoverFile(fileName + "-cover.png");
|
||||
}
|
||||
if (!getScreens1File().isEmpty() || getScreen1Image() != null)
|
||||
{
|
||||
setScreens1File(fileName + "-00.png");
|
||||
}
|
||||
if (!getScreens2File().isEmpty() || getScreen2Image() != null)
|
||||
{
|
||||
setScreens2File(fileName + "-01.png");
|
||||
}
|
||||
if (!getGamesFile().isEmpty())
|
||||
{
|
||||
String fileEnding = getGamesFile().substring(getGamesFile().indexOf("."));
|
||||
setGamesFile(fileName + fileEnding);
|
||||
}
|
||||
|
||||
//todo for screens, game file
|
||||
disableChangeNotification(false);
|
||||
}
|
||||
|
||||
public boolean isNewGame()
|
||||
{
|
||||
return titleInDb.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isTitleChanged()
|
||||
{
|
||||
return !titleInDb.isEmpty() && !titleInDb.equals(title);
|
||||
}
|
||||
|
||||
|
||||
public void resetImages()
|
||||
{
|
||||
this.coverImage = null;
|
||||
this.screen1Image = null;
|
||||
this.screen2Image = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class JoystickModel extends AbstractModel
|
||||
{
|
||||
public static final String DEFAULT_CONFIG = "JU,JD,JL,JR,JF,JF,SP,EN,,F1,F3,F5,,,";
|
||||
private final boolean port1;
|
||||
private boolean primary = false;
|
||||
|
||||
private List<String> configList = new ArrayList<>();
|
||||
private ActionListener primaryListener;
|
||||
|
||||
public JoystickModel(boolean port1)
|
||||
{
|
||||
this.port1 = port1;
|
||||
|
||||
}
|
||||
|
||||
public String getConfigString()
|
||||
{
|
||||
// Construct from config list
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (port1)
|
||||
{
|
||||
builder.append("J:1");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.append("J:2");
|
||||
}
|
||||
if (primary)
|
||||
{
|
||||
builder.append("*");
|
||||
}
|
||||
builder.append(":");
|
||||
builder.append(String.join(",", configList));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public void setConfigStringFromDb(String configString)
|
||||
{
|
||||
if (configString == null || configString.isEmpty())
|
||||
{
|
||||
configList = new ArrayList<>();
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
configList.add("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] colonSplit = configString.split(":");
|
||||
if (colonSplit.length != 3)
|
||||
{
|
||||
throw new IllegalStateException("Invalid config string");
|
||||
}
|
||||
|
||||
configList = new ArrayList<>(Arrays.asList(colonSplit[2].split(",")));
|
||||
while (configList.size() < 15)
|
||||
{
|
||||
configList.add("");
|
||||
}
|
||||
setPrimaryWithoutListenerNotification(colonSplit[1].contains("*"));
|
||||
}
|
||||
resetDataChanged();
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
public void setConfigString(String configString)
|
||||
{
|
||||
// Set all other fields based on configString
|
||||
String[] colonSplit = configString.split(":");
|
||||
if (colonSplit.length != 3)
|
||||
{
|
||||
throw new IllegalStateException("Invalid config string");
|
||||
}
|
||||
configList.clear();
|
||||
|
||||
configList = new ArrayList<>(Arrays.asList(colonSplit[2].split(",")));
|
||||
while (configList.size() < 15)
|
||||
{
|
||||
configList.add("");
|
||||
}
|
||||
disableChangeNotification(true);
|
||||
setUp(configList.get(0));
|
||||
setDown(configList.get(1));
|
||||
setLeft(configList.get(2));
|
||||
setRight(configList.get(3));
|
||||
setLeftFire(configList.get(4));
|
||||
setRightFire(configList.get(5));
|
||||
setTl(configList.get(6));
|
||||
setTr(configList.get(7));
|
||||
setUnused1(configList.get(8));
|
||||
setA(configList.get(9));
|
||||
setB(configList.get(10));
|
||||
setC(configList.get(11));
|
||||
setUnused2(configList.get(12));
|
||||
setUnused3(configList.get(13));
|
||||
setUnused4(configList.get(14));
|
||||
|
||||
setPrimary(colonSplit[1].contains("*"));
|
||||
disableChangeNotification(false);
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
public String getUp()
|
||||
{
|
||||
return configList.get(0);
|
||||
}
|
||||
|
||||
public void setUp(String up)
|
||||
{
|
||||
String old = getUp();
|
||||
configList.set(0, up);
|
||||
if (!Objects.equals(old, up))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getDown()
|
||||
{
|
||||
return configList.get(1);
|
||||
}
|
||||
|
||||
public void setDown(String down)
|
||||
{
|
||||
String old = getDown();
|
||||
configList.set(1, down);
|
||||
if (!Objects.equals(old, down))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getLeft()
|
||||
{
|
||||
return configList.get(2);
|
||||
}
|
||||
|
||||
public void setLeft(String left)
|
||||
{
|
||||
String old = getLeft();
|
||||
configList.set(2, left);
|
||||
if (!Objects.equals(old, left))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getRight()
|
||||
{
|
||||
return configList.get(3);
|
||||
}
|
||||
|
||||
public void setRight(String right)
|
||||
{
|
||||
String old = getRight();
|
||||
configList.set(3, right);
|
||||
if (!Objects.equals(old, right))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getLeftFire()
|
||||
{
|
||||
return configList.get(4);
|
||||
}
|
||||
|
||||
public void setLeftFire(String leftFire)
|
||||
{
|
||||
String old = getLeftFire();
|
||||
configList.set(4, leftFire);
|
||||
if (!Objects.equals(old, leftFire))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getRightFire()
|
||||
{
|
||||
return configList.get(5);
|
||||
}
|
||||
|
||||
public void setRightFire(String rightFire)
|
||||
{
|
||||
String old = getRightFire();
|
||||
configList.set(5, rightFire);
|
||||
if (!Objects.equals(old, rightFire))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getTl()
|
||||
{
|
||||
return configList.get(6);
|
||||
}
|
||||
|
||||
public void setTl(String tl)
|
||||
{
|
||||
String old = getTl();
|
||||
configList.set(6, tl);
|
||||
if (!Objects.equals(old, tl))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getTr()
|
||||
{
|
||||
return configList.get(7);
|
||||
}
|
||||
|
||||
public void setTr(String tr)
|
||||
{
|
||||
String old = getTr();
|
||||
configList.set(7, tr);
|
||||
if (!Objects.equals(old, tr))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnused1()
|
||||
{
|
||||
return configList.get(8);
|
||||
}
|
||||
|
||||
public void setUnused1(String unused1)
|
||||
{
|
||||
String old = getUnused1();
|
||||
configList.set(8, unused1);
|
||||
if (!Objects.equals(old, unused1))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getA()
|
||||
{
|
||||
return configList.get(9);
|
||||
}
|
||||
|
||||
public void setA(String a)
|
||||
{
|
||||
String old = getA();
|
||||
configList.set(9, a);
|
||||
if (!Objects.equals(old, a))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getB()
|
||||
{
|
||||
return configList.get(10);
|
||||
}
|
||||
|
||||
public void setB(String b)
|
||||
{
|
||||
String old = getB();
|
||||
configList.set(10, b);
|
||||
if (!Objects.equals(old, b))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getC()
|
||||
{
|
||||
return configList.get(11);
|
||||
}
|
||||
|
||||
public void setC(String c)
|
||||
{
|
||||
String old = getC();
|
||||
configList.set(11, c);
|
||||
if (!Objects.equals(old, c))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnused2()
|
||||
{
|
||||
return configList.get(12);
|
||||
}
|
||||
|
||||
public void setUnused2(String unused2)
|
||||
{
|
||||
String old = getUnused2();
|
||||
configList.set(12, unused2);
|
||||
if (!Objects.equals(old, unused2))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnused3()
|
||||
{
|
||||
return configList.get(13);
|
||||
}
|
||||
|
||||
public void setUnused3(String unused3)
|
||||
{
|
||||
String old = getUnused3();
|
||||
configList.set(13, unused3);
|
||||
if (!Objects.equals(old, unused3))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUnused4()
|
||||
{
|
||||
return configList.get(14);
|
||||
}
|
||||
|
||||
public void setUnused4(String unused4)
|
||||
{
|
||||
String old = getUnused4();
|
||||
configList.set(14, unused4);
|
||||
if (!Objects.equals(old, unused4))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPrimary()
|
||||
{
|
||||
return primary;
|
||||
}
|
||||
|
||||
public void setPrimary(boolean primary)
|
||||
{
|
||||
boolean old = isPrimary();
|
||||
this.primary = primary;
|
||||
if (!(Boolean.compare(old, primary) == 0))
|
||||
{
|
||||
notifyChange();
|
||||
if (primaryListener != null)
|
||||
{
|
||||
this.primaryListener.actionPerformed(new ActionEvent(this, 0, Boolean.toString(this.primary)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setPrimaryWithoutListenerNotification(boolean primary)
|
||||
{
|
||||
boolean old = isPrimary();
|
||||
this.primary = primary;
|
||||
if (!(Boolean.compare(old, primary) == 0))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
void setPrimaryChangeListener(ActionListener e)
|
||||
{
|
||||
this.primaryListener = e;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,316 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.ListModel;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.db.DbConnector;
|
||||
import se.lantz.model.data.GameDetails;
|
||||
import se.lantz.model.data.GameListData;
|
||||
import se.lantz.model.data.GameView;
|
||||
import se.lantz.util.FileManager;
|
||||
|
||||
public class MainViewModel extends AbstractModel
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(MainViewModel.class);
|
||||
|
||||
DbConnector dbConnector;
|
||||
DefaultComboBoxModel<GameView> gameViewModel = new DefaultComboBoxModel<>();
|
||||
GameListModel gameListModel = new GameListModel();
|
||||
|
||||
private GameView selectedGameView;
|
||||
|
||||
private InfoModel infoModel = new InfoModel();
|
||||
private JoystickModel joy1Model = new JoystickModel(true);
|
||||
private JoystickModel joy2Model = new JoystickModel(false);
|
||||
private SystemModel systemModel = new SystemModel();
|
||||
|
||||
private FileManager fileManager = new FileManager(infoModel);
|
||||
|
||||
private String currentGameId = "";
|
||||
|
||||
private PropertyChangeListener duplicateListener;
|
||||
|
||||
private PropertyChangeListener requiredFieldsListener;
|
||||
|
||||
private GameListData selectedData;
|
||||
|
||||
public void initialize()
|
||||
{
|
||||
logger.debug("Creating DBConnector...");
|
||||
dbConnector = new DbConnector();
|
||||
logger.debug("...done.");
|
||||
//Setup game views
|
||||
selectedGameView = new GameView(GameView.ALL_GAMES_ID);
|
||||
selectedGameView.setName("All Games");
|
||||
selectedGameView.setSqlQuery("");
|
||||
gameViewModel.addElement(selectedGameView);
|
||||
for (GameView gameView : dbConnector.loadGameViews())
|
||||
{
|
||||
gameViewModel.addElement(gameView);
|
||||
}
|
||||
|
||||
joy1Model.setPrimaryChangeListener(e -> {
|
||||
joy2Model.setPrimaryWithoutListenerNotification(!Boolean.valueOf(e.getActionCommand()));
|
||||
});
|
||||
|
||||
joy2Model.setPrimaryChangeListener(e -> {
|
||||
joy1Model.setPrimaryWithoutListenerNotification(!Boolean.valueOf(e.getActionCommand()));
|
||||
});
|
||||
}
|
||||
|
||||
public ListModel<GameListData> getGameListModel()
|
||||
{
|
||||
|
||||
return gameListModel;
|
||||
}
|
||||
|
||||
public void readGameDetails(GameListData selectedData)
|
||||
{
|
||||
this.selectedData = selectedData;
|
||||
currentGameId = selectedData.getGameId();
|
||||
GameDetails details = null;
|
||||
if (selectedData.getGameId().isEmpty())
|
||||
{
|
||||
//Create a default GameDetails and return
|
||||
details = new GameDetails();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read from db, update all models after that.
|
||||
details = dbConnector.getGameDetails(selectedData.getGameId());
|
||||
}
|
||||
// Map to models
|
||||
infoModel.setTitleFromDb(details.getTitle());
|
||||
|
||||
infoModel.setTitle(details.getTitle());
|
||||
infoModel.setDescription(details.getDescription());
|
||||
infoModel.setYear(details.getYear());
|
||||
infoModel.setAuthor(details.getAuthor());
|
||||
infoModel.setGenre(details.getGenre());
|
||||
infoModel.setComposer(details.getComposer());
|
||||
infoModel.setGamesFile(details.getGame());
|
||||
infoModel.setCoverFile(details.getCover());
|
||||
infoModel.setScreens1File(details.getScreen1());
|
||||
infoModel.setScreens2File(details.getScreen2());
|
||||
//Reset and images that where added previously
|
||||
infoModel.resetImages();
|
||||
|
||||
infoModel.resetDataChanged();
|
||||
|
||||
joy1Model.setConfigStringFromDb(details.getJoy1());
|
||||
joy1Model.resetDataChanged();
|
||||
joy2Model.setConfigStringFromDb(details.getJoy2());
|
||||
joy2Model.resetDataChanged();
|
||||
systemModel.setConfigStringFromDb(details.getSystem());
|
||||
systemModel.resetDataChanged();
|
||||
//Set empty title to trigger a change
|
||||
if (selectedData.getGameId().isEmpty())
|
||||
{
|
||||
infoModel.setTitle("");
|
||||
}
|
||||
}
|
||||
|
||||
public StringBuilder importGameInfo(List<String> rowValues, ImportManager.Options option)
|
||||
{
|
||||
return dbConnector.importRowsInGameInfoTable(rowValues, option);
|
||||
}
|
||||
|
||||
public InfoModel getInfoModel()
|
||||
{
|
||||
return infoModel;
|
||||
}
|
||||
|
||||
public JoystickModel getJoy1Model()
|
||||
{
|
||||
return joy1Model;
|
||||
}
|
||||
|
||||
public JoystickModel getJoy2Model()
|
||||
{
|
||||
return joy2Model;
|
||||
}
|
||||
|
||||
public SystemModel getSystemModel()
|
||||
{
|
||||
return systemModel;
|
||||
}
|
||||
|
||||
public void reloadCurrentGameView()
|
||||
{
|
||||
setSelectedGameView(getSelectedGameView());
|
||||
}
|
||||
|
||||
public void setSelectedGameView(GameView gameView)
|
||||
{
|
||||
this.selectedGameView = gameView;
|
||||
if (gameView != null)
|
||||
{
|
||||
logger.debug("Fetching games for view {}...", gameView);
|
||||
gameListModel.clear();
|
||||
List<GameListData> gamesList = dbConnector.fetchGamesByView(gameView);
|
||||
for (GameListData gameListData : gamesList)
|
||||
{
|
||||
gameListModel.addElement(gameListData);
|
||||
}
|
||||
logger.debug("...done.");
|
||||
}
|
||||
}
|
||||
|
||||
public GameView getSelectedGameView()
|
||||
{
|
||||
return this.selectedGameView;
|
||||
}
|
||||
|
||||
public DefaultComboBoxModel<GameView> getGameViewModel()
|
||||
{
|
||||
return gameViewModel;
|
||||
}
|
||||
|
||||
public void saveGameView(GameView gameView)
|
||||
{
|
||||
dbConnector.saveGameView(gameView);
|
||||
}
|
||||
|
||||
public void addSaveChangeListener(PropertyChangeListener saveChangeListener)
|
||||
{
|
||||
getInfoModel().addPropertyChangeListener(saveChangeListener);
|
||||
getJoy1Model().addPropertyChangeListener(saveChangeListener);
|
||||
getJoy2Model().addPropertyChangeListener(saveChangeListener);
|
||||
getSystemModel().addPropertyChangeListener(saveChangeListener);
|
||||
}
|
||||
|
||||
public void addDuplicateGameListener(PropertyChangeListener duplicateListener)
|
||||
{
|
||||
this.duplicateListener = duplicateListener;
|
||||
}
|
||||
|
||||
public void addRequireFieldsListener(PropertyChangeListener requiredFieldsListener)
|
||||
{
|
||||
this.requiredFieldsListener = requiredFieldsListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataChanged()
|
||||
{
|
||||
return infoModel.isDataChanged() || joy1Model.isDataChanged() || joy2Model.isDataChanged() ||
|
||||
systemModel.isDataChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if save was successful, false if not.
|
||||
*/
|
||||
public boolean saveData()
|
||||
{
|
||||
if (isDataChanged())
|
||||
{
|
||||
if ((infoModel.isNewGame() || infoModel.isTitleChanged()) && dbConnector.isGameInDb(infoModel.getTitle()))
|
||||
{
|
||||
duplicateListener.propertyChange(new PropertyChangeEvent(this, "duplicate", null, infoModel.getTitle()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (validateRequiredFields().size() > 0)
|
||||
{
|
||||
//Validate that all required fields are set here!!
|
||||
requiredFieldsListener.propertyChange(new PropertyChangeEvent(this, "missing", null, validateRequiredFields()));
|
||||
return false;
|
||||
}
|
||||
|
||||
//Update all file names to match title
|
||||
infoModel.updateFileNames();
|
||||
//Create game details
|
||||
GameDetails updatedGame = new GameDetails();
|
||||
updatedGame.setTitle(infoModel.getTitle().replaceAll("\"", "\"\""));
|
||||
updatedGame.setAuthor(infoModel.getAuthor().replaceAll("\"", "\"\""));
|
||||
updatedGame.setYear(infoModel.getYear());
|
||||
updatedGame.setComposer(infoModel.getComposer().replaceAll("\"", "\"\""));
|
||||
updatedGame.setGenre(infoModel.getGenre());
|
||||
updatedGame.setDescription(infoModel.getDescription().replaceAll("\"", "\"\""));
|
||||
updatedGame.setGame(infoModel.getGamesFile());
|
||||
updatedGame.setCover(infoModel.getCoverFile());
|
||||
updatedGame.setScreen1(infoModel.getScreens1File());
|
||||
updatedGame.setScreen2(infoModel.getScreens2File());
|
||||
updatedGame.setJoy1(joy1Model.getConfigString());
|
||||
updatedGame.setJoy2(joy2Model.getConfigString());
|
||||
updatedGame.setSystem(systemModel.getConfigString());
|
||||
|
||||
if (currentGameId.isEmpty())
|
||||
{
|
||||
//Create new entry in Db
|
||||
int rowId = dbConnector.createNewGame(updatedGame);
|
||||
currentGameId = Integer.toString(rowId);
|
||||
selectedData.setGameId(currentGameId);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Update with currentGameId
|
||||
dbConnector.saveGame(currentGameId, updatedGame);
|
||||
}
|
||||
selectedData.setTitle(updatedGame.getTitle());
|
||||
gameListModel.notifySave();
|
||||
|
||||
fileManager.saveFiles();
|
||||
//Notify of any changes to covers/screens etc
|
||||
infoModel.notifyChange();
|
||||
//Reset all models
|
||||
infoModel.resetDataChanged();
|
||||
joy1Model.resetDataChanged();
|
||||
joy2Model.resetDataChanged();
|
||||
systemModel.resetDataChanged();
|
||||
|
||||
//Update db title once done
|
||||
infoModel.setTitleFromDb(infoModel.getTitle());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private List<String> validateRequiredFields()
|
||||
{
|
||||
List<String> missingFields = new ArrayList<>();
|
||||
if (infoModel.getTitle().isEmpty())
|
||||
{
|
||||
missingFields.add("Title");
|
||||
}
|
||||
if (infoModel.getCoverFile().isEmpty() && infoModel.getCoverImage() == null)
|
||||
{
|
||||
missingFields.add("Cover");
|
||||
}
|
||||
if (infoModel.getScreens1File().isEmpty() && infoModel.getScreen1Image() == null)
|
||||
{
|
||||
missingFields.add("Screenshot 1");
|
||||
}
|
||||
if (infoModel.getScreens2File().isEmpty() && infoModel.getScreen2Image() == null)
|
||||
{
|
||||
missingFields.add("Screenshot 2");
|
||||
}
|
||||
if (infoModel.getGamesFile().isEmpty())
|
||||
{
|
||||
missingFields.add("Game file");
|
||||
}
|
||||
return missingFields;
|
||||
}
|
||||
|
||||
public void addNewGameListData()
|
||||
{
|
||||
gameListModel.addElement(new GameListData("New Game", ""));
|
||||
}
|
||||
|
||||
public void removeNewGameListData()
|
||||
{
|
||||
if (gameListModel.get(gameListModel.getSize() - 1).getGameId().isEmpty())
|
||||
{
|
||||
gameListModel.remove(gameListModel.getSize() - 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,278 @@
|
|||
package se.lantz.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class SystemModel extends AbstractModel
|
||||
{
|
||||
private final static String C64 = "64";
|
||||
private final static String VIC = "vic";
|
||||
private final static String PAL = "pal";
|
||||
private final static String NTSC = "ntsc";
|
||||
private final static String DRIVEICON = "driveicon";
|
||||
private final static String TRUEDRIVE = "truedrive";
|
||||
private final static String FULLHEIGHT = "fullheight";
|
||||
private final static String SID6581 = "sid6581";
|
||||
private final static String SID8580 = "sid8580";
|
||||
private final static String SID8580D = "sid8580D";
|
||||
private final static String NOAUDIOSCALE = "noaudioscale";
|
||||
private final static String BANK0 = "bank0";
|
||||
private final static String BANK1 = "bank1";
|
||||
private final static String BANK2 = "bank2";
|
||||
private final static String BANK3 = "bank3";
|
||||
private final static String BANK5 = "bank5";
|
||||
|
||||
|
||||
//TODO vertical shift
|
||||
|
||||
private boolean c64 = false;
|
||||
private boolean vic = false;
|
||||
private boolean pal = false;
|
||||
private boolean ntsc = false;
|
||||
private boolean driveIcon = false;
|
||||
private boolean fullHeight = false;
|
||||
private boolean sid6581 = false;
|
||||
private boolean sid8580 = false;
|
||||
private boolean sid8580D = false;
|
||||
private boolean bank0 = false;
|
||||
private boolean bank1 = false;
|
||||
private boolean bank2 = false;
|
||||
private boolean bank3 = false;
|
||||
private boolean bank5 = false;
|
||||
|
||||
private List<String> configList = new ArrayList<>();
|
||||
|
||||
private String configString = "";
|
||||
|
||||
public SystemModel()
|
||||
{
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public String getConfigString()
|
||||
{
|
||||
// Construct from config list
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(String.join(",", configList));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public void setConfigStringFromDb(String configString)
|
||||
{
|
||||
if (configString == null || configString.isEmpty())
|
||||
{
|
||||
configList = new ArrayList<>();
|
||||
}
|
||||
else
|
||||
{
|
||||
configList = new ArrayList<>(Arrays.asList(configString.split(",")));
|
||||
}
|
||||
resetDataChanged();
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
public void setConfigString(String configString)
|
||||
{
|
||||
configList = new ArrayList<>(Arrays.asList(configString.split(",")));
|
||||
for (String flag : configList)
|
||||
{
|
||||
if (flag.equals(C64))
|
||||
{
|
||||
setC64(true);
|
||||
}
|
||||
if (flag.equals(VIC))
|
||||
{
|
||||
setVic(true);
|
||||
}
|
||||
//etc...
|
||||
}
|
||||
|
||||
//TODO
|
||||
// // Set all other fields based on configString
|
||||
// String[] colonSplit = configString.split(":");
|
||||
// if (colonSplit.length != 3)
|
||||
// {
|
||||
// throw new IllegalStateException("Invalid config string");
|
||||
// }
|
||||
// configList.clear();
|
||||
//
|
||||
// configList = new ArrayList<>(Arrays.asList(colonSplit[2].split(",")));
|
||||
// while (configList.size() < 15)
|
||||
// {
|
||||
// configList.add("");
|
||||
// }
|
||||
// disableChangeNotification(true);
|
||||
// setUp(configList.get(0));
|
||||
// setDown(configList.get(1));
|
||||
// setLeft(configList.get(2));
|
||||
// setRight(configList.get(3));
|
||||
// setLeftFire(configList.get(4));
|
||||
// setRightFire(configList.get(5));
|
||||
// setTl(configList.get(6));
|
||||
// setTr(configList.get(7));
|
||||
// setUnused1(configList.get(8));
|
||||
// setA(configList.get(9));
|
||||
// setB(configList.get(10));
|
||||
// setC(configList.get(11));
|
||||
// setUnused2(configList.get(12));
|
||||
// setUnused3(configList.get(13));
|
||||
// setUnused4(configList.get(14));
|
||||
//
|
||||
// setPrimary(colonSplit[1].contains("*"));
|
||||
// disableChangeNotification(false);
|
||||
// notifyChange();
|
||||
}
|
||||
|
||||
public boolean isC64()
|
||||
{
|
||||
return c64;
|
||||
}
|
||||
|
||||
public void setC64(boolean c64)
|
||||
{
|
||||
boolean old = isC64();
|
||||
this.c64 = c64;
|
||||
if (!(Boolean.compare(old, c64) == 0))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isVic()
|
||||
{
|
||||
return vic;
|
||||
}
|
||||
|
||||
public void setVic(boolean vic)
|
||||
{
|
||||
boolean old = isVic();
|
||||
this.vic = vic;
|
||||
if (!(Boolean.compare(old, vic) == 0))
|
||||
{
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPal()
|
||||
{
|
||||
return pal;
|
||||
}
|
||||
|
||||
public void setPal(boolean pal)
|
||||
{
|
||||
this.pal = pal;
|
||||
}
|
||||
|
||||
public boolean isNtsc()
|
||||
{
|
||||
return ntsc;
|
||||
}
|
||||
|
||||
public void setNtsc(boolean ntsc)
|
||||
{
|
||||
this.ntsc = ntsc;
|
||||
}
|
||||
|
||||
public boolean isDriveIcon()
|
||||
{
|
||||
return driveIcon;
|
||||
}
|
||||
|
||||
public void setDriveIcon(boolean driveIcon)
|
||||
{
|
||||
this.driveIcon = driveIcon;
|
||||
}
|
||||
|
||||
public boolean isFullHeight()
|
||||
{
|
||||
return fullHeight;
|
||||
}
|
||||
|
||||
public void setFullHeight(boolean fullHeight)
|
||||
{
|
||||
this.fullHeight = fullHeight;
|
||||
}
|
||||
|
||||
public boolean isSid6581()
|
||||
{
|
||||
return sid6581;
|
||||
}
|
||||
|
||||
public void setSid6581(boolean sid6581)
|
||||
{
|
||||
this.sid6581 = sid6581;
|
||||
}
|
||||
|
||||
public boolean isSid8580()
|
||||
{
|
||||
return sid8580;
|
||||
}
|
||||
|
||||
public void setSid8580(boolean sid8580)
|
||||
{
|
||||
this.sid8580 = sid8580;
|
||||
}
|
||||
|
||||
public boolean isSid8580D()
|
||||
{
|
||||
return sid8580D;
|
||||
}
|
||||
|
||||
public void setSid8580D(boolean sid8580d)
|
||||
{
|
||||
sid8580D = sid8580d;
|
||||
}
|
||||
|
||||
public boolean isBank0()
|
||||
{
|
||||
return bank0;
|
||||
}
|
||||
|
||||
public void setBank0(boolean bank0)
|
||||
{
|
||||
this.bank0 = bank0;
|
||||
}
|
||||
|
||||
public boolean isBank1()
|
||||
{
|
||||
return bank1;
|
||||
}
|
||||
|
||||
public void setBank1(boolean bank1)
|
||||
{
|
||||
this.bank1 = bank1;
|
||||
}
|
||||
|
||||
public boolean isBank2()
|
||||
{
|
||||
return bank2;
|
||||
}
|
||||
|
||||
public void setBank2(boolean bank2)
|
||||
{
|
||||
this.bank2 = bank2;
|
||||
}
|
||||
|
||||
public boolean isBank3()
|
||||
{
|
||||
return bank3;
|
||||
}
|
||||
|
||||
public void setBank3(boolean bank3)
|
||||
{
|
||||
this.bank3 = bank3;
|
||||
}
|
||||
|
||||
public boolean isBank5()
|
||||
{
|
||||
return bank5;
|
||||
}
|
||||
|
||||
public void setBank5(boolean bank5)
|
||||
{
|
||||
this.bank5 = bank5;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
package se.lantz.model.data;
|
||||
|
||||
import se.lantz.model.JoystickModel;
|
||||
|
||||
/**
|
||||
* The data structure representing a specific game.
|
||||
*
|
||||
* @author Mikael
|
||||
*
|
||||
*/
|
||||
public class GameDetails
|
||||
{
|
||||
|
||||
private String title = "";
|
||||
private int year = 1986;
|
||||
private String author = "";
|
||||
private String composer = "";
|
||||
private String genre = "";
|
||||
private String description = "";
|
||||
private String game = "";
|
||||
private String cover = "";
|
||||
private String screen1 = "";
|
||||
private String screen2 = "";
|
||||
private String joy1 = "";
|
||||
private String joy2 = "";
|
||||
private String system = "";
|
||||
|
||||
public GameDetails()
|
||||
{
|
||||
setTitle("New Game");
|
||||
setJoy1("J:1:" + JoystickModel.DEFAULT_CONFIG);
|
||||
setJoy2("J:2*:" + JoystickModel.DEFAULT_CONFIG);
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title == null ? "" : title;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description == null ? "" : description;
|
||||
}
|
||||
|
||||
public int getYear()
|
||||
{
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(int year)
|
||||
{
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public String getAuthor()
|
||||
{
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author)
|
||||
{
|
||||
this.author = author == null ? "" : author;
|
||||
}
|
||||
|
||||
public String getComposer()
|
||||
{
|
||||
return composer;
|
||||
}
|
||||
|
||||
public void setComposer(String composer)
|
||||
{
|
||||
this.composer = composer == null ? "" : composer;
|
||||
}
|
||||
|
||||
public String getGenre()
|
||||
{
|
||||
return genre;
|
||||
}
|
||||
|
||||
public void setGenre(String genre)
|
||||
{
|
||||
this.genre = genre == null ? "" : genre;
|
||||
}
|
||||
|
||||
public String getGame()
|
||||
{
|
||||
return game;
|
||||
}
|
||||
|
||||
public void setGame(String game)
|
||||
{
|
||||
this.game = game == null ? "" : game;
|
||||
}
|
||||
|
||||
public String getCover()
|
||||
{
|
||||
return cover;
|
||||
}
|
||||
|
||||
public void setCover(String cover)
|
||||
{
|
||||
this.cover = cover == null ? "" : cover;
|
||||
}
|
||||
|
||||
public String getScreen1()
|
||||
{
|
||||
return screen1;
|
||||
}
|
||||
|
||||
public void setScreen1(String screen1)
|
||||
{
|
||||
this.screen1 = screen1 == null ? "" : screen1;
|
||||
}
|
||||
|
||||
public String getScreen2()
|
||||
{
|
||||
return screen2;
|
||||
}
|
||||
|
||||
public void setScreen2(String screen2)
|
||||
{
|
||||
this.screen2 = screen2 == null ? "" : screen2;
|
||||
}
|
||||
|
||||
public String getJoy1()
|
||||
{
|
||||
return joy1;
|
||||
}
|
||||
|
||||
public void setJoy1(String joy1)
|
||||
{
|
||||
this.joy1 = joy1 == null ? "" : joy1;
|
||||
}
|
||||
|
||||
public String getJoy2()
|
||||
{
|
||||
return joy2;
|
||||
}
|
||||
|
||||
public void setJoy2(String joy2)
|
||||
{
|
||||
this.joy2 = joy2 == null ? "" : joy2;
|
||||
}
|
||||
|
||||
public String getSystem()
|
||||
{
|
||||
return system;
|
||||
}
|
||||
|
||||
public void setSystem(String system)
|
||||
{
|
||||
this.system = system == null ? "" : system;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package se.lantz.model.data;
|
||||
|
||||
public class GameListData
|
||||
{
|
||||
|
||||
public GameListData(String title, String gameId)
|
||||
{
|
||||
super();
|
||||
this.title = title;
|
||||
this.gameId = gameId;
|
||||
}
|
||||
|
||||
private String title;
|
||||
private String gameId;
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getGameId()
|
||||
{
|
||||
return gameId;
|
||||
}
|
||||
|
||||
public void setGameId(String gameId)
|
||||
{
|
||||
this.gameId = gameId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((gameId == null) ? 0 : gameId.hashCode());
|
||||
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
GameListData other = (GameListData) obj;
|
||||
if (gameId == null)
|
||||
{
|
||||
if (other.gameId != null)
|
||||
return false;
|
||||
}
|
||||
else if (!gameId.equals(other.gameId))
|
||||
return false;
|
||||
if (title == null)
|
||||
{
|
||||
if (other.title != null)
|
||||
return false;
|
||||
}
|
||||
else if (!title.equals(other.title))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
package se.lantz.model.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GameView
|
||||
{
|
||||
public static final int ALL_GAMES_ID = -1;
|
||||
private static final Logger logger = LoggerFactory.getLogger(GameView.class);
|
||||
private String name = "";
|
||||
private boolean matchAll = true;
|
||||
private List<ViewFilter> viewFilters = new ArrayList<>();
|
||||
private String sqlQuery = "";
|
||||
|
||||
private int gameViewId;
|
||||
|
||||
public GameView(int gameViewId)
|
||||
{
|
||||
this.gameViewId = gameViewId;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getSqlQuery()
|
||||
{
|
||||
return sqlQuery;
|
||||
}
|
||||
|
||||
public void setSqlQuery(String sqlQuery)
|
||||
{
|
||||
this.sqlQuery = sqlQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isMatchAll()
|
||||
{
|
||||
return matchAll;
|
||||
}
|
||||
|
||||
public void setMatchAll(boolean matchAll)
|
||||
{
|
||||
this.matchAll = matchAll;
|
||||
}
|
||||
|
||||
public List<ViewFilter> getViewFilters()
|
||||
{
|
||||
return viewFilters;
|
||||
}
|
||||
|
||||
public void setViewFilters(List<ViewFilter> viewFilters)
|
||||
{
|
||||
this.viewFilters = viewFilters;
|
||||
//TODO Create SQL queries from the filters. TODO: Handle AND and OR
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("WHERE ");
|
||||
int index = 0;
|
||||
for (ViewFilter viewFilter : viewFilters)
|
||||
{
|
||||
index++;
|
||||
if (index > 1)
|
||||
{
|
||||
builder.append(isMatchAll() ? " AND ": " OR ");
|
||||
}
|
||||
builder.append(viewFilter.getField());
|
||||
switch (viewFilter.getOperator())
|
||||
{
|
||||
case ViewFilter.BEGINS_WITH_TEXT:
|
||||
builder.append(" LIKE '");
|
||||
builder.append(viewFilter.getFilterData());
|
||||
builder.append("%'");
|
||||
break;
|
||||
|
||||
case ViewFilter.ENDS_WITH_TEXT:
|
||||
builder.append(" LIKE '%");
|
||||
builder.append(viewFilter.getFilterData());
|
||||
builder.append("'");
|
||||
break;
|
||||
|
||||
case ViewFilter.CONTAINS_TEXT:
|
||||
builder.append(" LIKE '%");
|
||||
builder.append(viewFilter.getFilterData());
|
||||
builder.append("%'");
|
||||
break;
|
||||
|
||||
case ViewFilter.IS:
|
||||
builder.append(" = ");
|
||||
builder.append(viewFilter.getFilterData());
|
||||
break;
|
||||
|
||||
case ViewFilter.BEFORE:
|
||||
builder.append(" < ");
|
||||
builder.append(viewFilter.getFilterData());
|
||||
break;
|
||||
|
||||
case ViewFilter.AFTER:
|
||||
builder.append(" > ");
|
||||
builder.append(viewFilter.getFilterData());
|
||||
break;
|
||||
default:
|
||||
logger.debug("Unexpected value: " + viewFilter.getOperator());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// switch (viewFilter.getOperator())
|
||||
// {
|
||||
// case ViewFilter.BEGINS_WITH_TEXT ->
|
||||
// {
|
||||
// builder.append(" LIKE '");
|
||||
// builder.append(viewFilter.getFilterData());
|
||||
// builder.append("%'");
|
||||
// }
|
||||
// case ViewFilter.ENDS_WITH_TEXT ->
|
||||
// {
|
||||
// builder.append(" LIKE '%");
|
||||
// builder.append(viewFilter.getFilterData());
|
||||
// builder.append("'");
|
||||
// }
|
||||
// case ViewFilter.CONTAINS_TEXT ->
|
||||
// {
|
||||
// builder.append(" LIKE '%");
|
||||
// builder.append(viewFilter.getFilterData());
|
||||
// builder.append("%'");
|
||||
// }
|
||||
// case ViewFilter.EQUALS_TEXT ->
|
||||
// {
|
||||
// builder.append(" LIKE '");
|
||||
// builder.append(viewFilter.getFilterData());
|
||||
// builder.append("'");
|
||||
// }
|
||||
// case ViewFilter.IS ->
|
||||
// {
|
||||
// builder.append(" = ");
|
||||
// builder.append(viewFilter.getFilterData());
|
||||
// }
|
||||
// case ViewFilter.BEFORE ->
|
||||
// {
|
||||
// builder.append(" < ");
|
||||
// builder.append(viewFilter.getFilterData());
|
||||
// }
|
||||
// case ViewFilter.AFTER ->
|
||||
// {
|
||||
// builder.append(" > ");
|
||||
// builder.append(viewFilter.getFilterData());
|
||||
// }
|
||||
// default ->
|
||||
// {
|
||||
// logger.debug("Unexpected value: " + viewFilter.getOperator());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
this.sqlQuery = builder.toString();
|
||||
}
|
||||
|
||||
public int getGameViewId()
|
||||
{
|
||||
return gameViewId;
|
||||
}
|
||||
|
||||
public void setGameViewId(int gameViewId)
|
||||
{
|
||||
this.gameViewId = gameViewId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package se.lantz.model.data;
|
||||
|
||||
public class ViewFilter
|
||||
{
|
||||
public static final String BEGINS_WITH_TEXT = "Begins with text";
|
||||
public static final String ENDS_WITH_TEXT = "Ends with text";
|
||||
public static final String CONTAINS_TEXT = "Contains text";
|
||||
public static final String EQUALS_TEXT = "Equals text";
|
||||
public static final String IS = "Is";
|
||||
public static final String BEFORE = "Before";
|
||||
public static final String AFTER = "After";
|
||||
|
||||
|
||||
private String filterData;
|
||||
private String operator;
|
||||
private String field;
|
||||
|
||||
public ViewFilter(String field, String operator, String filterData)
|
||||
{
|
||||
super();
|
||||
this.filterData = filterData;
|
||||
this.operator = operator;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public String getFilterData()
|
||||
{
|
||||
return filterData;
|
||||
}
|
||||
|
||||
public void setFilterData(String filterData)
|
||||
{
|
||||
this.filterData = filterData;
|
||||
}
|
||||
|
||||
public String getOperator()
|
||||
{
|
||||
return operator;
|
||||
}
|
||||
|
||||
public void setOperator(String operator)
|
||||
{
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
public String getField()
|
||||
{
|
||||
return field;
|
||||
}
|
||||
|
||||
public void setField(String field)
|
||||
{
|
||||
this.field = field;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package se.lantz.util;
|
||||
|
||||
public class DbConstants
|
||||
{
|
||||
|
||||
public static final String TITLE = "Title";
|
||||
public static final String YEAR = "Year";
|
||||
public static final String AUTHOR = "Author";
|
||||
public static final String COMPOSER = "Composer";
|
||||
public static final String GENRE = "Genre";
|
||||
public static final String DESC = "Description";
|
||||
public static final String GAME = "Gamefile";
|
||||
public static final String COVER = "Coverfile";
|
||||
public static final String SCREEN1 = "Screen1file";
|
||||
public static final String SCREEN2 = "Screen2file";
|
||||
public static final String JOY1 = "Joy1config";
|
||||
public static final String JOY2 = "Joy2config";
|
||||
public static final String SYSTEM = "System";
|
||||
|
||||
private DbConstants()
|
||||
{
|
||||
//No instance allowed
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package se.lantz.util;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.gui.MainWindow;
|
||||
|
||||
public class ExceptionHandler extends JDialog
|
||||
{
|
||||
private static final long serialVersionUID = 8120908659146305672L;
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);
|
||||
private JTextArea stacktraceArea;
|
||||
private JScrollPane scrollPane;
|
||||
private JButton copyButton;
|
||||
private Window owner;
|
||||
|
||||
public ExceptionHandler(Window owner)
|
||||
{
|
||||
super(owner);
|
||||
this.owner = owner;
|
||||
initDialog();
|
||||
}
|
||||
|
||||
private void initDialog()
|
||||
{
|
||||
setTitle("Unexpected error");
|
||||
setMinimumSize(new Dimension(250, 200));
|
||||
setSize(new Dimension(700, 700));
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
getContentPane().setLayout(gridBagLayout);
|
||||
GridBagConstraints scrollPaneConstraints = new GridBagConstraints();
|
||||
scrollPaneConstraints.insets = new Insets(5, 5, 5, 0);
|
||||
scrollPaneConstraints.weighty = 1.0;
|
||||
scrollPaneConstraints.weightx = 1.0;
|
||||
scrollPaneConstraints.fill = GridBagConstraints.BOTH;
|
||||
scrollPaneConstraints.gridx = 0;
|
||||
scrollPaneConstraints.gridy = 0;
|
||||
getContentPane().add(getScrollPane(), scrollPaneConstraints);
|
||||
GridBagConstraints copyButtonConstraints = new GridBagConstraints();
|
||||
copyButtonConstraints.weightx = 1.0;
|
||||
copyButtonConstraints.anchor = GridBagConstraints.EAST;
|
||||
copyButtonConstraints.insets = new Insets(5, 5, 5, 5);
|
||||
copyButtonConstraints.gridx = 0;
|
||||
copyButtonConstraints.gridy = 1;
|
||||
getContentPane().add(getCopyButton(), copyButtonConstraints);
|
||||
|
||||
ActionListener escapeAction = e -> getCopyButton().doClick();
|
||||
getRootPane().registerKeyboardAction(escapeAction,
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
getStacktraceArea()
|
||||
.registerKeyboardAction(escapeAction, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED);
|
||||
setLocationRelativeTo(owner);
|
||||
stacktraceArea.setEditable(false);
|
||||
}
|
||||
|
||||
private JTextArea getStacktraceArea()
|
||||
{
|
||||
if (stacktraceArea == null)
|
||||
{
|
||||
stacktraceArea = new JTextArea();
|
||||
|
||||
}
|
||||
return stacktraceArea;
|
||||
}
|
||||
|
||||
private JScrollPane getScrollPane()
|
||||
{
|
||||
if (scrollPane == null)
|
||||
{
|
||||
scrollPane = new JScrollPane();
|
||||
scrollPane.setViewportView(getStacktraceArea());
|
||||
}
|
||||
return scrollPane;
|
||||
}
|
||||
|
||||
private JButton getCopyButton()
|
||||
{
|
||||
if (copyButton == null)
|
||||
{
|
||||
copyButton = new JButton("Copy to clipboard and close");
|
||||
copyButton.addActionListener(e -> copyToClipboardAndClose());
|
||||
}
|
||||
return copyButton;
|
||||
}
|
||||
|
||||
private void copyToClipboardAndClose()
|
||||
{
|
||||
//Copy to clipboard
|
||||
final StringSelection selection = new StringSelection(stacktraceArea.getText());
|
||||
|
||||
final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
clipboard.setContents(selection, selection);
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
public static void handleException(final Throwable ex, final String message)
|
||||
{
|
||||
logger.error("message", ex);
|
||||
Window owner = null;
|
||||
if (MainWindow.isInitialized())
|
||||
{
|
||||
owner = MainWindow.getInstance();
|
||||
}
|
||||
ExceptionHandler dialog = new ExceptionHandler(owner);
|
||||
if (owner != null)
|
||||
{
|
||||
dialog.setLocationRelativeTo(owner);
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (message != null)
|
||||
{
|
||||
builder.append(message + "\n\n");
|
||||
}
|
||||
builder.append(getStackTraceAsString(ex));
|
||||
|
||||
dialog.stacktraceArea.setText(builder.toString());
|
||||
dialog.stacktraceArea.setCaretPosition(0);
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
private static String getStackTraceAsString(Throwable throwable)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
throwable.printStackTrace(new PrintWriter(stringWriter));
|
||||
return stringWriter.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,877 @@
|
|||
package se.lantz.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* This class makes it easy to drag and drop files from the operating system to a Java program. Any
|
||||
* <tt>java.awt.Component</tt> can be dropped onto, but only <tt>javax.swing.JComponent</tt>s will indicate the drop
|
||||
* event with a changed border.
|
||||
* <p/>
|
||||
* To use this class, construct a new <tt>FileDrop</tt> by passing it the target component and a <tt>Listener</tt> to
|
||||
* receive notification when file(s) have been dropped. Here is an example:
|
||||
* <p/>
|
||||
* <code><pre>
|
||||
* JPanel myPanel = new JPanel();
|
||||
* new FileDrop( myPanel, new FileDrop.Listener()
|
||||
* { public void filesDropped( java.io.File[] files )
|
||||
* {
|
||||
* // handle file drop
|
||||
* ...
|
||||
* } // end filesDropped
|
||||
* }); // end FileDrop.Listener
|
||||
* </pre></code>
|
||||
* <p/>
|
||||
* You can specify the border that will appear when files are being dragged by calling the constructor with a
|
||||
* <tt>javax.swing.border.Border</tt>. Only <tt>JComponent</tt>s will show any indication with a border.
|
||||
* <p/>
|
||||
* You can turn on some debugging features by passing a <tt>PrintStream</tt> object (such as <tt>System.out</tt>) into
|
||||
* the full constructor. A <tt>null</tt> value will result in no extra debugging information being output.
|
||||
* <p/>
|
||||
*
|
||||
* <p>
|
||||
* I'm releasing this code into the Public Domain. Enjoy.
|
||||
* </p>
|
||||
* <p>
|
||||
* <em>Original author: Robert Harder, rharder@usa.net</em>
|
||||
* </p>
|
||||
* <p>
|
||||
* 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
* </p>
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @author rharder@users.sf.net
|
||||
* @version 1.0.1
|
||||
*/
|
||||
public class FileDrop
|
||||
{
|
||||
private transient javax.swing.border.Border normalBorder;
|
||||
private transient java.awt.dnd.DropTargetListener dropListener;
|
||||
|
||||
/** Discover if the running JVM is modern enough to have drag and drop. */
|
||||
private static Boolean supportsDnD;
|
||||
|
||||
// Default border color
|
||||
// private static java.awt.Color defaultBorderColor = new java.awt.Color( 0f, 0f, 1f, 0.25f );
|
||||
private static java.awt.Color defaultBorderColor = Color.RED;
|
||||
|
||||
/**
|
||||
* Constructs a {@link FileDrop} with a default light-blue border and, if <var>c</var> is a
|
||||
* {@link java.awt.Container}, recursively sets all elements contained within as drop targets, though only the top
|
||||
* level container will change borders.
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.awt.Component c, final Listener listener)
|
||||
{
|
||||
this(null, // Logging stream
|
||||
c, // Drop target
|
||||
// javax.swing.BorderFactory.createLineBorder(defaultBorderColor, 3),
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor), // Drag border
|
||||
true, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Constructor with a default border and the option to recursively set drop targets. If your component is a
|
||||
* <tt>java.awt.Container</tt>, then each of its children components will also listen for drops, though only the
|
||||
* parent will change borders.
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.awt.Component c, final boolean recursive, final Listener listener)
|
||||
{
|
||||
this(null, // Logging stream
|
||||
c, // Drop target
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor), // Drag border
|
||||
recursive, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Constructor with a default border and debugging optionally turned on. With Debugging turned on, more status
|
||||
* messages will be displayed to <tt>out</tt>. A common way to use this constructor is with <tt>System.out</tt> or
|
||||
* <tt>System.err</tt>. A <tt>null</tt> value for the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param out
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.io.PrintStream out, final java.awt.Component c, final Listener listener)
|
||||
{
|
||||
this(out, // Logging stream
|
||||
c, // Drop target
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor), false, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Constructor with a default border, debugging optionally turned on and the option to recursively set drop targets.
|
||||
* If your component is a <tt>java.awt.Container</tt>, then each of its children components will also listen for
|
||||
* drops, though only the parent will change borders. With Debugging turned on, more status messages will be displayed
|
||||
* to <tt>out</tt>. A common way to use this constructor is with <tt>System.out</tt> or <tt>System.err</tt>. A
|
||||
* <tt>null</tt> value for the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param out
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.io.PrintStream out,
|
||||
final java.awt.Component c,
|
||||
final boolean recursive,
|
||||
final Listener listener)
|
||||
{
|
||||
this(out, // Logging stream
|
||||
c, // Drop target
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor), // Drag border
|
||||
recursive, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Constructor with a specified border
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.awt.Component c, final javax.swing.border.Border dragBorder, final Listener listener)
|
||||
{
|
||||
this(null, // Logging stream
|
||||
c, // Drop target
|
||||
dragBorder, // Drag border
|
||||
false, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Constructor with a specified border and the option to recursively set drop targets. If your component is a
|
||||
* <tt>java.awt.Container</tt>, then each of its children components will also listen for drops, though only the
|
||||
* parent will change borders.
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.awt.Component c,
|
||||
final javax.swing.border.Border dragBorder,
|
||||
final boolean recursive,
|
||||
final Listener listener)
|
||||
{
|
||||
this(null, c, dragBorder, recursive, listener);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Constructor with a specified border and debugging optionally turned on. With Debugging turned on, more status
|
||||
* messages will be displayed to <tt>out</tt>. A common way to use this constructor is with <tt>System.out</tt> or
|
||||
* <tt>System.err</tt>. A <tt>null</tt> value for the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.io.PrintStream out,
|
||||
final java.awt.Component c,
|
||||
final javax.swing.border.Border dragBorder,
|
||||
final Listener listener)
|
||||
{
|
||||
this(out, // Logging stream
|
||||
c, // Drop target
|
||||
dragBorder, // Drag border
|
||||
false, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Full constructor with a specified border and debugging optionally turned on. With Debugging turned on, more status
|
||||
* messages will be displayed to <tt>out</tt>. A common way to use this constructor is with <tt>System.out</tt> or
|
||||
* <tt>System.err</tt>. A <tt>null</tt> value for the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(final java.io.PrintStream out,
|
||||
final java.awt.Component c,
|
||||
final javax.swing.border.Border dragBorder,
|
||||
final boolean recursive,
|
||||
final Listener listener)
|
||||
{
|
||||
|
||||
if (supportsDnD())
|
||||
{ // Make a drop listener
|
||||
dropListener = new java.awt.dnd.DropTargetListener()
|
||||
{
|
||||
public void dragEnter(java.awt.dnd.DropTargetDragEvent evt)
|
||||
{
|
||||
log(out, "FileDrop: dragEnter event.");
|
||||
|
||||
// Is this an acceptable drag event?
|
||||
if (isDragOk(out, evt))
|
||||
{
|
||||
// If it's a Swing component, set its border
|
||||
if (c instanceof javax.swing.JComponent)
|
||||
{
|
||||
javax.swing.JComponent jc = (javax.swing.JComponent) c;
|
||||
normalBorder = jc.getBorder();
|
||||
log(out, "FileDrop: normal border saved.");
|
||||
jc.setBorder(dragBorder);
|
||||
log(out, "FileDrop: drag border set.");
|
||||
} // end if: JComponent
|
||||
|
||||
// Acknowledge that it's okay to enter
|
||||
// evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrag(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: event accepted.");
|
||||
} // end if: drag ok
|
||||
else
|
||||
{ // Reject the drag event
|
||||
evt.rejectDrag();
|
||||
log(out, "FileDrop: event rejected.");
|
||||
} // end else: drag not ok
|
||||
} // end dragEnter
|
||||
|
||||
public void dragOver(java.awt.dnd.DropTargetDragEvent evt)
|
||||
{ // This is called continually as long as the mouse is
|
||||
// over the drag target.
|
||||
} // end dragOver
|
||||
|
||||
public void drop(java.awt.dnd.DropTargetDropEvent evt)
|
||||
{
|
||||
log(out, "FileDrop: drop event.");
|
||||
try
|
||||
{ // Get whatever was dropped
|
||||
java.awt.datatransfer.Transferable tr = evt.getTransferable();
|
||||
|
||||
// Is it a file list?
|
||||
if (tr.isDataFlavorSupported(java.awt.datatransfer.DataFlavor.javaFileListFlavor))
|
||||
{
|
||||
// Say we'll take it.
|
||||
//evt.acceptDrop ( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: file list accepted.");
|
||||
|
||||
// Get a useful list
|
||||
java.util.List fileList =
|
||||
(java.util.List) tr.getTransferData(java.awt.datatransfer.DataFlavor.javaFileListFlavor);
|
||||
java.util.Iterator iterator = fileList.iterator();
|
||||
|
||||
// Convert list to array
|
||||
java.io.File[] filesTemp = new java.io.File[fileList.size()];
|
||||
fileList.toArray(filesTemp);
|
||||
final java.io.File[] files = filesTemp;
|
||||
|
||||
// Alert listener to drop.
|
||||
if (listener != null)
|
||||
listener.filesDropped(files);
|
||||
|
||||
// Mark that drop is completed.
|
||||
evt.getDropTargetContext().dropComplete(true);
|
||||
log(out, "FileDrop: drop complete.");
|
||||
} // end if: file list
|
||||
else // this section will check for a reader flavor.
|
||||
{
|
||||
// Thanks, Nathan!
|
||||
// BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
DataFlavor[] flavors = tr.getTransferDataFlavors();
|
||||
boolean handled = false;
|
||||
for (int zz = 0; zz < flavors.length; zz++)
|
||||
{
|
||||
if (flavors[zz].isRepresentationClassReader())
|
||||
{
|
||||
// Say we'll take it.
|
||||
//evt.acceptDrop ( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: reader accepted.");
|
||||
|
||||
Reader reader = flavors[zz].getReaderForText(tr);
|
||||
|
||||
BufferedReader br = new BufferedReader(reader);
|
||||
|
||||
if (listener != null)
|
||||
listener.filesDropped(createFileArray(br, out));
|
||||
|
||||
// Mark that drop is completed.
|
||||
evt.getDropTargetContext().dropComplete(true);
|
||||
log(out, "FileDrop: drop complete.");
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!handled)
|
||||
{
|
||||
log(out, "FileDrop: not a file list or reader - abort.");
|
||||
evt.rejectDrop();
|
||||
}
|
||||
// END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
} // end else: not a file list
|
||||
} // end try
|
||||
catch (java.io.IOException io)
|
||||
{
|
||||
log(out, "FileDrop: IOException - abort:");
|
||||
io.printStackTrace(out);
|
||||
evt.rejectDrop();
|
||||
} // end catch IOException
|
||||
catch (java.awt.datatransfer.UnsupportedFlavorException ufe)
|
||||
{
|
||||
log(out, "FileDrop: UnsupportedFlavorException - abort:");
|
||||
ufe.printStackTrace(out);
|
||||
evt.rejectDrop();
|
||||
} // end catch: UnsupportedFlavorException
|
||||
finally
|
||||
{
|
||||
// If it's a Swing component, reset its border
|
||||
if (c instanceof javax.swing.JComponent)
|
||||
{
|
||||
javax.swing.JComponent jc = (javax.swing.JComponent) c;
|
||||
jc.setBorder(normalBorder);
|
||||
log(out, "FileDrop: normal border restored.");
|
||||
} // end if: JComponent
|
||||
} // end finally
|
||||
} // end drop
|
||||
|
||||
public void dragExit(java.awt.dnd.DropTargetEvent evt)
|
||||
{
|
||||
log(out, "FileDrop: dragExit event.");
|
||||
// If it's a Swing component, reset its border
|
||||
if (c instanceof javax.swing.JComponent)
|
||||
{
|
||||
javax.swing.JComponent jc = (javax.swing.JComponent) c;
|
||||
jc.setBorder(normalBorder);
|
||||
log(out, "FileDrop: normal border restored.");
|
||||
} // end if: JComponent
|
||||
} // end dragExit
|
||||
|
||||
public void dropActionChanged(java.awt.dnd.DropTargetDragEvent evt)
|
||||
{
|
||||
log(out, "FileDrop: dropActionChanged event.");
|
||||
// Is this an acceptable drag event?
|
||||
if (isDragOk(out, evt))
|
||||
{ //evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrag(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: event accepted.");
|
||||
} // end if: drag ok
|
||||
else
|
||||
{
|
||||
evt.rejectDrag();
|
||||
log(out, "FileDrop: event rejected.");
|
||||
} // end else: drag not ok
|
||||
} // end dropActionChanged
|
||||
}; // end DropTargetListener
|
||||
|
||||
// Make the component (and possibly children) drop targets
|
||||
makeDropTarget(out, c, recursive);
|
||||
} // end if: supports dnd
|
||||
else
|
||||
{
|
||||
log(out, "FileDrop: Drag and drop is not supported with this JVM");
|
||||
} // end else: does not support DnD
|
||||
} // end constructor
|
||||
|
||||
private static boolean supportsDnD()
|
||||
{ // Static Boolean
|
||||
if (supportsDnD == null)
|
||||
{
|
||||
boolean support = false;
|
||||
try
|
||||
{
|
||||
Class arbitraryDndClass = Class.forName("java.awt.dnd.DnDConstants");
|
||||
support = true;
|
||||
} // end try
|
||||
catch (Exception e)
|
||||
{
|
||||
support = false;
|
||||
} // end catch
|
||||
supportsDnD = new Boolean(support);
|
||||
} // end if: first time through
|
||||
return supportsDnD.booleanValue();
|
||||
} // end supportsDnD
|
||||
|
||||
// BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
private static String ZERO_CHAR_STRING = "" + (char) 0;
|
||||
|
||||
private static File[] createFileArray(BufferedReader bReader, PrintStream out)
|
||||
{
|
||||
try
|
||||
{
|
||||
java.util.List list = new java.util.ArrayList();
|
||||
java.lang.String line = null;
|
||||
while ((line = bReader.readLine()) != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// kde seems to append a 0 char to the end of the reader
|
||||
if (ZERO_CHAR_STRING.equals(line))
|
||||
continue;
|
||||
|
||||
java.io.File file = new java.io.File(new java.net.URI(line));
|
||||
list.add(file);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log(out, "Error with " + line + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return (java.io.File[]) list.toArray(new File[list.size()]);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log(out, "FileDrop: IOException");
|
||||
}
|
||||
return new File[0];
|
||||
}
|
||||
// END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
|
||||
private void makeDropTarget(final java.io.PrintStream out, final java.awt.Component c, boolean recursive)
|
||||
{
|
||||
// Make drop target
|
||||
final java.awt.dnd.DropTarget dt = new java.awt.dnd.DropTarget();
|
||||
try
|
||||
{
|
||||
dt.addDropTargetListener(dropListener);
|
||||
} // end try
|
||||
catch (java.util.TooManyListenersException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
log(out, "FileDrop: Drop will not work due to previous error. Do you have another listener attached?");
|
||||
} // end catch
|
||||
|
||||
// Listen for hierarchy changes and remove the drop target when the parent gets cleared out.
|
||||
c.addHierarchyListener(new java.awt.event.HierarchyListener()
|
||||
{
|
||||
public void hierarchyChanged(java.awt.event.HierarchyEvent evt)
|
||||
{
|
||||
log(out, "FileDrop: Hierarchy changed.");
|
||||
java.awt.Component parent = c.getParent();
|
||||
if (parent == null)
|
||||
{
|
||||
c.setDropTarget(null);
|
||||
log(out, "FileDrop: Drop target cleared from component.");
|
||||
} // end if: null parent
|
||||
else
|
||||
{
|
||||
new java.awt.dnd.DropTarget(c, dropListener);
|
||||
log(out, "FileDrop: Drop target added to component.");
|
||||
} // end else: parent not null
|
||||
} // end hierarchyChanged
|
||||
}); // end hierarchy listener
|
||||
if (c.getParent() != null)
|
||||
new java.awt.dnd.DropTarget(c, dropListener);
|
||||
|
||||
if (recursive && (c instanceof java.awt.Container))
|
||||
{
|
||||
// Get the container
|
||||
java.awt.Container cont = (java.awt.Container) c;
|
||||
|
||||
// Get it's components
|
||||
java.awt.Component[] comps = cont.getComponents();
|
||||
|
||||
// Set it's components as listeners also
|
||||
for (int i = 0; i < comps.length; i++)
|
||||
makeDropTarget(out, comps[i], recursive);
|
||||
} // end if: recursively set components as listener
|
||||
} // end dropListener
|
||||
|
||||
/** Determine if the dragged data is a file list. */
|
||||
private boolean isDragOk(final java.io.PrintStream out, final java.awt.dnd.DropTargetDragEvent evt)
|
||||
{
|
||||
boolean ok = false;
|
||||
|
||||
// Get data flavors being dragged
|
||||
java.awt.datatransfer.DataFlavor[] flavors = evt.getCurrentDataFlavors();
|
||||
|
||||
// See if any of the flavors are a file list
|
||||
int i = 0;
|
||||
while (!ok && i < flavors.length)
|
||||
{
|
||||
// BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
// Is the flavor a file list?
|
||||
final DataFlavor curFlavor = flavors[i];
|
||||
if (curFlavor.equals(java.awt.datatransfer.DataFlavor.javaFileListFlavor) ||
|
||||
curFlavor.isRepresentationClassReader())
|
||||
{
|
||||
ok = true;
|
||||
}
|
||||
// END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
i++;
|
||||
} // end while: through flavors
|
||||
|
||||
// If logging is enabled, show data flavors
|
||||
if (out != null)
|
||||
{
|
||||
if (flavors.length == 0)
|
||||
log(out, "FileDrop: no data flavors.");
|
||||
for (i = 0; i < flavors.length; i++)
|
||||
log(out, flavors[i].toString());
|
||||
} // end if: logging enabled
|
||||
|
||||
return ok;
|
||||
} // end isDragOk
|
||||
|
||||
/** Outputs <tt>message</tt> to <tt>out</tt> if it's not null. */
|
||||
private static void log(java.io.PrintStream out, String message)
|
||||
{ // Log message if requested
|
||||
if (out != null)
|
||||
out.println(message);
|
||||
} // end log
|
||||
|
||||
/**
|
||||
* Removes the drag-and-drop hooks from the component and optionally from the all children. You should call this if
|
||||
* you add and remove components after you've set up the drag-and-drop. This will recursively unregister all
|
||||
* components contained within <var>c</var> if <var>c</var> is a {@link java.awt.Container}.
|
||||
*
|
||||
* @param c The component to unregister as a drop target
|
||||
* @since 1.0
|
||||
*/
|
||||
public static boolean remove(java.awt.Component c)
|
||||
{
|
||||
return remove(null, c, true);
|
||||
} // end remove
|
||||
|
||||
/**
|
||||
* Removes the drag-and-drop hooks from the component and optionally from the all children. You should call this if
|
||||
* you add and remove components after you've set up the drag-and-drop.
|
||||
*
|
||||
* @param out Optional {@link java.io.PrintStream} for logging drag and drop messages
|
||||
* @param c The component to unregister
|
||||
* @param recursive Recursively unregister components within a container
|
||||
* @since 1.0
|
||||
*/
|
||||
public static boolean remove(java.io.PrintStream out, java.awt.Component c, boolean recursive)
|
||||
{ // Make sure we support dnd.
|
||||
if (supportsDnD())
|
||||
{
|
||||
log(out, "FileDrop: Removing drag-and-drop hooks.");
|
||||
c.setDropTarget(null);
|
||||
if (recursive && (c instanceof java.awt.Container))
|
||||
{
|
||||
java.awt.Component[] comps = ((java.awt.Container) c).getComponents();
|
||||
for (int i = 0; i < comps.length; i++)
|
||||
remove(out, comps[i], recursive);
|
||||
return true;
|
||||
} // end if: recursive
|
||||
else
|
||||
return false;
|
||||
} // end if: supports DnD
|
||||
else
|
||||
return false;
|
||||
} // end remove
|
||||
|
||||
/* ******** I N N E R I N T E R F A C E L I S T E N E R ******** */
|
||||
|
||||
/**
|
||||
* Implement this inner interface to listen for when files are dropped. For example your class declaration may begin
|
||||
* like this: <code><pre>
|
||||
* public class MyClass implements FileDrop.Listener
|
||||
* ...
|
||||
* public void filesDropped( java.io.File[] files )
|
||||
* {
|
||||
* ...
|
||||
* } // end filesDropped
|
||||
* ...
|
||||
* </pre></code>
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public static interface Listener
|
||||
{
|
||||
|
||||
/**
|
||||
* This method is called when files have been successfully dropped.
|
||||
*
|
||||
* @param files An array of <tt>File</tt>s that were dropped.
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract void filesDropped(java.io.File[] files);
|
||||
|
||||
} // end inner-interface Listener
|
||||
|
||||
/* ******** I N N E R C L A S S ******** */
|
||||
|
||||
/**
|
||||
* This is the event that is passed to the {@link FileDropListener#filesDropped filesDropped(...)} method in your
|
||||
* {@link FileDropListener} when files are dropped onto a registered drop target.
|
||||
*
|
||||
* <p>
|
||||
* I'm releasing this code into the Public Domain. Enjoy.
|
||||
* </p>
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @author rob@iharder.net
|
||||
* @version 1.2
|
||||
*/
|
||||
public static class Event extends java.util.EventObject
|
||||
{
|
||||
|
||||
private java.io.File[] files;
|
||||
|
||||
/**
|
||||
* Constructs an {@link Event} with the array of files that were dropped and the {@link FileDrop} that initiated the
|
||||
* event.
|
||||
*
|
||||
* @param files The array of files that were dropped
|
||||
* @source The event source
|
||||
* @since 1.1
|
||||
*/
|
||||
public Event(java.io.File[] files, Object source)
|
||||
{
|
||||
super(source);
|
||||
this.files = files;
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Returns an array of files that were dropped on a registered drop target.
|
||||
*
|
||||
* @return array of files that were dropped
|
||||
* @since 1.1
|
||||
*/
|
||||
public java.io.File[] getFiles()
|
||||
{
|
||||
return files;
|
||||
} // end getFiles
|
||||
|
||||
} // end inner class Event
|
||||
|
||||
/* ******** I N N E R C L A S S ******** */
|
||||
|
||||
/**
|
||||
* At last an easy way to encapsulate your custom objects for dragging and dropping in your Java programs! When you
|
||||
* need to create a {@link java.awt.datatransfer.Transferable} object, use this class to wrap your object. For
|
||||
* example:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* ...
|
||||
* MyCoolClass myObj = new MyCoolClass();
|
||||
* Transferable xfer = new TransferableObject( myObj );
|
||||
* ...
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* Or if you need to know when the data was actually dropped, like when you're moving data out of a list, say, you can
|
||||
* use the {@link TransferableObject.Fetcher} inner class to return your object Just in Time. For example:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* ...
|
||||
* final MyCoolClass myObj = new MyCoolClass();
|
||||
*
|
||||
* TransferableObject.Fetcher fetcher = new TransferableObject.Fetcher()
|
||||
* { public Object getObject(){ return myObj; }
|
||||
* }; // end fetcher
|
||||
*
|
||||
* Transferable xfer = new TransferableObject( fetcher );
|
||||
* ...
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* The {@link java.awt.datatransfer.DataFlavor} associated with {@link TransferableObject} has the representation
|
||||
* class <tt>net.iharder.dnd.TransferableObject.class</tt> and MIME type
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>. This data flavor is accessible via the static
|
||||
* {@link #DATA_FLAVOR} property.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* I'm releasing this code into the Public Domain. Enjoy.
|
||||
* </p>
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @author rob@iharder.net
|
||||
* @version 1.2
|
||||
*/
|
||||
public static class TransferableObject implements java.awt.datatransfer.Transferable
|
||||
{
|
||||
/**
|
||||
* The MIME type for {@link #DATA_FLAVOR} is <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public final static String MIME_TYPE = "application/x-net.iharder.dnd.TransferableObject";
|
||||
|
||||
/**
|
||||
* The default {@link java.awt.datatransfer.DataFlavor} for {@link TransferableObject} has the representation class
|
||||
* <tt>net.iharder.dnd.TransferableObject.class</tt> and the MIME type
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public final static java.awt.datatransfer.DataFlavor DATA_FLAVOR =
|
||||
new java.awt.datatransfer.DataFlavor(FileDrop.TransferableObject.class, MIME_TYPE);
|
||||
|
||||
private Fetcher fetcher;
|
||||
private Object data;
|
||||
|
||||
private java.awt.datatransfer.DataFlavor customFlavor;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TransferableObject} that wraps <var>data</var>. Along with the {@link #DATA_FLAVOR}
|
||||
* associated with this class, this creates a custom data flavor with a representation class determined from
|
||||
* <code>data.getClass()</code> and the MIME type <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @param data The data to transfer
|
||||
* @since 1.1
|
||||
*/
|
||||
public TransferableObject(Object data)
|
||||
{
|
||||
this.data = data;
|
||||
this.customFlavor = new java.awt.datatransfer.DataFlavor(data.getClass(), MIME_TYPE);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Creates a new {@link TransferableObject} that will return the object that is returned by <var>fetcher</var>. No
|
||||
* custom data flavor is set other than the default {@link #DATA_FLAVOR}.
|
||||
*
|
||||
* @see Fetcher
|
||||
* @param fetcher The {@link Fetcher} that will return the data object
|
||||
* @since 1.1
|
||||
*/
|
||||
public TransferableObject(Fetcher fetcher)
|
||||
{
|
||||
this.fetcher = fetcher;
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Creates a new {@link TransferableObject} that will return the object that is returned by <var>fetcher</var>.
|
||||
* Along with the {@link #DATA_FLAVOR} associated with this class, this creates a custom data flavor with a
|
||||
* representation class <var>dataClass</var> and the MIME type
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @see Fetcher
|
||||
* @param dataClass The {@link java.lang.Class} to use in the custom data flavor
|
||||
* @param fetcher The {@link Fetcher} that will return the data object
|
||||
* @since 1.1
|
||||
*/
|
||||
public TransferableObject(Class dataClass, Fetcher fetcher)
|
||||
{
|
||||
this.fetcher = fetcher;
|
||||
this.customFlavor = new java.awt.datatransfer.DataFlavor(dataClass, MIME_TYPE);
|
||||
} // end constructor
|
||||
|
||||
/**
|
||||
* Returns the custom {@link java.awt.datatransfer.DataFlavor} associated with the encapsulated object or
|
||||
* <tt>null</tt> if the {@link Fetcher} constructor was used without passing a {@link java.lang.Class}.
|
||||
*
|
||||
* @return The custom data flavor for the encapsulated object
|
||||
* @since 1.1
|
||||
*/
|
||||
public java.awt.datatransfer.DataFlavor getCustomDataFlavor()
|
||||
{
|
||||
return customFlavor;
|
||||
} // end getCustomDataFlavor
|
||||
|
||||
/* ******** T R A N S F E R A B L E M E T H O D S ******** */
|
||||
|
||||
/**
|
||||
* Returns a two- or three-element array containing first the custom data flavor, if one was created in the
|
||||
* constructors, second the default {@link #DATA_FLAVOR} associated with {@link TransferableObject}, and third the
|
||||
* {@link java.awt.datatransfer.DataFlavor.stringFlavor}.
|
||||
*
|
||||
* @return An array of supported data flavors
|
||||
* @since 1.1
|
||||
*/
|
||||
public java.awt.datatransfer.DataFlavor[] getTransferDataFlavors()
|
||||
{
|
||||
if (customFlavor != null)
|
||||
return new java.awt.datatransfer.DataFlavor[] { customFlavor, DATA_FLAVOR,
|
||||
java.awt.datatransfer.DataFlavor.stringFlavor }; // end flavors array
|
||||
else
|
||||
return new java.awt.datatransfer.DataFlavor[] { DATA_FLAVOR, java.awt.datatransfer.DataFlavor.stringFlavor }; // end flavors array
|
||||
} // end getTransferDataFlavors
|
||||
|
||||
/**
|
||||
* Returns the data encapsulated in this {@link TransferableObject}. If the {@link Fetcher} constructor was used,
|
||||
* then this is when the {@link Fetcher#getObject getObject()} method will be called. If the requested data flavor
|
||||
* is not supported, then the {@link Fetcher#getObject getObject()} method will not be called.
|
||||
*
|
||||
* @param flavor The data flavor for the data to return
|
||||
* @return The dropped data
|
||||
* @since 1.1
|
||||
*/
|
||||
public Object getTransferData(java.awt.datatransfer.DataFlavor flavor)
|
||||
throws java.awt.datatransfer.UnsupportedFlavorException, java.io.IOException
|
||||
{
|
||||
// Native object
|
||||
if (flavor.equals(DATA_FLAVOR))
|
||||
return fetcher == null ? data : fetcher.getObject();
|
||||
|
||||
// String
|
||||
if (flavor.equals(java.awt.datatransfer.DataFlavor.stringFlavor))
|
||||
return fetcher == null ? data.toString() : fetcher.getObject().toString();
|
||||
|
||||
// We can't do anything else
|
||||
throw new java.awt.datatransfer.UnsupportedFlavorException(flavor);
|
||||
} // end getTransferData
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if <var>flavor</var> is one of the supported flavors. Flavors are supported using the
|
||||
* <code>equals(...)</code> method.
|
||||
*
|
||||
* @param flavor The data flavor to check
|
||||
* @return Whether or not the flavor is supported
|
||||
* @since 1.1
|
||||
*/
|
||||
public boolean isDataFlavorSupported(java.awt.datatransfer.DataFlavor flavor)
|
||||
{
|
||||
// Native object
|
||||
if (flavor.equals(DATA_FLAVOR))
|
||||
return true;
|
||||
|
||||
// String
|
||||
if (flavor.equals(java.awt.datatransfer.DataFlavor.stringFlavor))
|
||||
return true;
|
||||
|
||||
// We can't do anything else
|
||||
return false;
|
||||
} // end isDataFlavorSupported
|
||||
|
||||
/* ******** I N N E R I N T E R F A C E F E T C H E R ******** */
|
||||
|
||||
/**
|
||||
* Instead of passing your data directly to the {@link TransferableObject} constructor, you may want to know exactly
|
||||
* when your data was received in case you need to remove it from its source (or do anyting else to it). When the
|
||||
* {@link #getTransferData getTransferData(...)} method is called on the {@link TransferableObject}, the
|
||||
* {@link Fetcher}'s {@link #getObject getObject()} method will be called.
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @copyright 2001
|
||||
* @version 1.1
|
||||
* @since 1.1
|
||||
*/
|
||||
public static interface Fetcher
|
||||
{
|
||||
/**
|
||||
* Return the object being encapsulated in the {@link TransferableObject}.
|
||||
*
|
||||
* @return The dropped object
|
||||
* @since 1.1
|
||||
*/
|
||||
public abstract Object getObject();
|
||||
} // end inner interface Fetcher
|
||||
|
||||
} // end class TransferableObject
|
||||
|
||||
} // end class FileDrop
|
|
@ -0,0 +1,181 @@
|
|||
package se.lantz.util;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import se.lantz.model.InfoModel;
|
||||
|
||||
public class FileManager
|
||||
{
|
||||
private static final String GAMES = "./games/";
|
||||
private static final String SCREENS = "./screens/";
|
||||
private static final String COVERS = "./covers/";
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FileManager.class);
|
||||
|
||||
private InfoModel model;
|
||||
|
||||
public FileManager(InfoModel model)
|
||||
{
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public void saveFiles()
|
||||
{
|
||||
//Check if title is different that in db, then rename existing files!
|
||||
if (model.isTitleChanged())
|
||||
{
|
||||
//Rename existing covers and screens and game file
|
||||
renameFiles();
|
||||
}
|
||||
|
||||
//Fetch images that has been added
|
||||
BufferedImage cover = model.getCoverImage();
|
||||
BufferedImage screen1 = model.getScreen1Image();
|
||||
BufferedImage screen2 = model.getScreen2Image();
|
||||
//TODO: game file
|
||||
String coverFileName = model.getCoverFile();
|
||||
String screen1FileName = model.getScreens1File();
|
||||
String screen2FileName = model.getScreens2File();
|
||||
|
||||
//Store on disk with the name in the models. The UI must make sure the names is according to the Maxi format.
|
||||
|
||||
//Resize the files, cover size = 122x175
|
||||
if (cover != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Image coverToSave = cover.getScaledInstance(122, 175, Image.SCALE_DEFAULT);
|
||||
BufferedImage copyOfImage =
|
||||
new BufferedImage(coverToSave.getWidth(null), coverToSave.getHeight(null), BufferedImage.TYPE_INT_RGB);
|
||||
Graphics g = copyOfImage.createGraphics();
|
||||
g.drawImage(coverToSave, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
File outputfile = new File(COVERS + coverFileName);
|
||||
ImageIO.write(copyOfImage, "png", outputfile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("Could not store cover", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (screen1 != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
File outputfile = new File(SCREENS + screen1FileName);
|
||||
ImageIO.write(screen1, "png", outputfile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("Could not store screen1", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (screen2 != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
File outputfile = new File(SCREENS + screen2FileName);
|
||||
ImageIO.write(screen2, "png", outputfile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("Could not store screen2", e);
|
||||
}
|
||||
}
|
||||
//TODO: game file
|
||||
}
|
||||
|
||||
private void renameFiles()
|
||||
{
|
||||
String oldTitle = generateFileNameFromTitle(model.getTitleInDb());
|
||||
if (!model.getCoverFile().isEmpty())
|
||||
{
|
||||
File oldCover = new File(COVERS + oldTitle + "-cover.png");
|
||||
File newCover = new File(COVERS + model.getCoverFile());
|
||||
if (oldCover.renameTo(newCover))
|
||||
{
|
||||
logger.debug("Renamed cover {} to {}", oldCover.getName(), newCover.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("Could NOT rename cover {} to {}", oldCover.getName(), newCover.getName());
|
||||
}
|
||||
}
|
||||
if (!model.getScreens1File().isEmpty())
|
||||
{
|
||||
File oldScreen1 = new File(SCREENS + oldTitle + "-00.png");
|
||||
File newScreen1 = new File(SCREENS + model.getScreens1File());
|
||||
if (oldScreen1.renameTo(newScreen1))
|
||||
{
|
||||
logger.debug("Renamed screen1 {} to {}", oldScreen1.getName(), newScreen1.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("Could NOT rename screen1 {} to {}", oldScreen1.getName(), newScreen1.getName());
|
||||
}
|
||||
}
|
||||
if (!model.getScreens2File().isEmpty())
|
||||
{
|
||||
File oldScreen2 = new File(SCREENS + oldTitle + "-01.png");
|
||||
File newScreen2 = new File(SCREENS + model.getScreens2File());
|
||||
if (oldScreen2.renameTo(newScreen2))
|
||||
{
|
||||
logger.debug("Renamed screen2 {} to {}", oldScreen2.getName(), newScreen2.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("Could NOT rename screen2 {} to {}", oldScreen2.getName(), newScreen2.getName());
|
||||
}
|
||||
}
|
||||
if (!model.getGamesFile().isEmpty())
|
||||
{
|
||||
String fileEnding = model.getGamesFile().substring(model.getGamesFile().indexOf("."));
|
||||
File oldGame = new File(GAMES + oldTitle + fileEnding);
|
||||
File newGame = new File(GAMES + model.getGamesFile());
|
||||
if (oldGame.renameTo(newGame))
|
||||
{
|
||||
logger.debug("Renamed game {} to {}", oldGame.getName(), newGame.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.debug("Could NOT rename game {} to {}", oldGame.getName(), newGame.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateFileNameFromTitle(String title) {
|
||||
// All uppercase letters
|
||||
// No spaces or special characters
|
||||
//The maxi game tool seems to work like this: truncate to 23 characters and then remove all special characters.
|
||||
if (title.length() > 23)
|
||||
{
|
||||
title = title.substring(0, 23);
|
||||
logger.debug("FileName: truncating to : {}", title);
|
||||
}
|
||||
// System.out.println("Game title: " + fileNameList.get(0));
|
||||
// Do the conversion
|
||||
List<Character> forbiddenCharsList = " ,:'’-.!+*<>()".chars().mapToObj(item -> (char) item)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Character> newName = title.chars().mapToObj(item -> (char) item)
|
||||
.filter(character -> !forbiddenCharsList.contains(character))
|
||||
.map(character -> Character.toUpperCase(character)).collect(Collectors.toList());
|
||||
String newNameString = newName.stream().map(String::valueOf).collect(Collectors.joining());
|
||||
logger.debug("Game title: \"{}\" ---- New fileName: \"{}\"", title, newNameString);
|
||||
return newNameString;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package se.lantz.util;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
/**
|
||||
* This program demonstrates how to resize an image.
|
||||
*
|
||||
* @author www.codejava.net
|
||||
*
|
||||
*/
|
||||
public class ImageResizer
|
||||
{
|
||||
|
||||
public static BufferedImage scale(BufferedImage before, double scale)
|
||||
{
|
||||
int w = before.getWidth();
|
||||
int h = before.getHeight();
|
||||
// Create a new image of the proper size
|
||||
int w2 = (int) (w * scale);
|
||||
int h2 = (int) (h * scale);
|
||||
BufferedImage after = new BufferedImage(w2, h2, BufferedImage.TYPE_INT_ARGB);
|
||||
AffineTransform scaleInstance = AffineTransform.getScaleInstance(scale, scale);
|
||||
AffineTransformOp scaleOp = new AffineTransformOp(scaleInstance, AffineTransformOp.TYPE_BILINEAR);
|
||||
|
||||
scaleOp.filter(before, after);
|
||||
return after;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes an image to a absolute width and height (the image may not be proportional)
|
||||
*
|
||||
* @param inputImagePath Path of the original image
|
||||
* @param outputImagePath Path to save the resized image
|
||||
* @param scaledWidth absolute width in pixels
|
||||
* @param scaledHeight absolute height in pixels
|
||||
* @throws IOException
|
||||
*/
|
||||
public static ImageIcon resize(String inputImagePath, int scaledWidth, int scaledHeight) throws IOException
|
||||
{
|
||||
// reads input image
|
||||
File inputFile = new File(inputImagePath);
|
||||
BufferedImage inputImage = ImageIO.read(inputFile);
|
||||
// creates output image
|
||||
BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType());
|
||||
|
||||
// scales the input image to the output image
|
||||
Graphics2D g2d = outputImage.createGraphics();
|
||||
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
|
||||
g2d.dispose();
|
||||
return new ImageIcon(outputImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes an image by a percentage of original size (proportional).
|
||||
*
|
||||
* @param inputImagePath Path of the original image
|
||||
* @param outputImagePath Path to save the resized image
|
||||
* @param percent a double number specifies percentage of the output image over the input image.
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void resize(String inputImagePath, double percent) throws IOException
|
||||
{
|
||||
File inputFile = new File(inputImagePath);
|
||||
BufferedImage inputImage = ImageIO.read(inputFile);
|
||||
int scaledWidth = (int) (inputImage.getWidth() * percent);
|
||||
int scaledHeight = (int) (inputImage.getHeight() * percent);
|
||||
resize(inputImagePath, scaledWidth, scaledHeight);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
package se.lantz.util;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import org.jsoup.Connection;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.TextNode;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
public class MobyGamesScraper
|
||||
{
|
||||
|
||||
private String mobyGamesBaseUrl = "https://www.mobygames.com/game/c64/*";
|
||||
|
||||
private String game = "rushn-attack";
|
||||
|
||||
private String descriptionCssQuery = "#main > div > div:eq(2) > div";
|
||||
|
||||
private String authorCssQuery = "#coreGameRelease > div:contains(Published)";
|
||||
|
||||
private String yearCssQuery = "#coreGameRelease > div:contains(Released)";
|
||||
|
||||
private String genreCssQuery = "#coreGameGenre > div > div:contains(Genre)";
|
||||
|
||||
private String coverCssQuery = "#coreGameCover > a > img";
|
||||
|
||||
private long startTime = 0L;
|
||||
|
||||
public MobyGamesScraper()
|
||||
{
|
||||
// TODO Auto-generated constructor stub
|
||||
|
||||
|
||||
//*[@id="coreGameCover"]/a/img
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
MobyGamesScraper scraper = new MobyGamesScraper();
|
||||
scraper.scrapeMobyGames();
|
||||
}
|
||||
|
||||
public void scrapeMobyGames()
|
||||
{
|
||||
startTime = System.currentTimeMillis();
|
||||
System.out.println("Scraping " + mobyGamesBaseUrl + " ...");
|
||||
|
||||
scrapeDescription();
|
||||
|
||||
System.out.println("Author: " + scarpeElementValue(authorCssQuery));
|
||||
System.out.println("Year: " + scarpeElementValue(yearCssQuery));
|
||||
System.out.println("Genre: " + scarpeElementValue(genreCssQuery));
|
||||
|
||||
scrapeCover();
|
||||
}
|
||||
|
||||
|
||||
private void scrapeDescription()
|
||||
{
|
||||
String searchUrl = mobyGamesBaseUrl.replace("*", game);
|
||||
Document doc;
|
||||
try
|
||||
{
|
||||
Connection.Response result = Jsoup.connect(searchUrl).method(Connection.Method.GET).execute();
|
||||
doc = result.parse();
|
||||
//Fetch the right element
|
||||
Elements descriptionDiv = doc.select(descriptionCssQuery);
|
||||
if (descriptionDiv.first() != null)
|
||||
{
|
||||
//Get all text elements
|
||||
List<TextNode> textNodes = descriptionDiv.first().textNodes();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (TextNode textNode : textNodes)
|
||||
{
|
||||
if (textNode.text().length() > 1)
|
||||
{
|
||||
builder.append(textNode.text());
|
||||
}
|
||||
}
|
||||
System.out.println(builder.toString());
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String scarpeElementValue(String cssQuery)
|
||||
{
|
||||
String value = "";
|
||||
|
||||
String searchUrl = mobyGamesBaseUrl.replace("*", game);
|
||||
Document doc;
|
||||
try
|
||||
{
|
||||
Connection.Response result = Jsoup.connect(searchUrl).method(Connection.Method.GET).execute();
|
||||
doc = result.parse();
|
||||
//Fetch the right element
|
||||
Elements queryElements = doc.select(cssQuery);
|
||||
Element first = queryElements.first();
|
||||
if (first != null)
|
||||
{
|
||||
int index = queryElements.first().elementSiblingIndex();
|
||||
Element valueElement = first.parent().child(index+1);
|
||||
value = valueElement.text();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private void scrapeCover()
|
||||
{
|
||||
String searchUrl = mobyGamesBaseUrl.replace("*", game);
|
||||
Document doc;
|
||||
try
|
||||
{
|
||||
Connection.Response result = Jsoup.connect(searchUrl).method(Connection.Method.GET).execute();
|
||||
doc = result.parse();
|
||||
//Fetch the right element
|
||||
Elements coverElements = doc.select(coverCssQuery);
|
||||
if (coverElements.first() != null)
|
||||
{
|
||||
Element coverElement = coverElements.first();
|
||||
String absoluteUrl = coverElement.absUrl("src");
|
||||
String srcValue = coverElement.attr("src");
|
||||
|
||||
|
||||
URL url = new URL(absoluteUrl);
|
||||
BufferedImage c = ImageIO.read(url);
|
||||
ImageIcon image = new ImageIcon(c);
|
||||
|
||||
saveImage(absoluteUrl, game + ".jpg");
|
||||
|
||||
//TODO: big cover:
|
||||
|
||||
String bigCoverUrl = coverElement.parent().attr("href");
|
||||
scrapeBigCover(bigCoverUrl);
|
||||
System.out.println("Cover art: " + absoluteUrl);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void scrapeBigCover(String url)
|
||||
{
|
||||
String cssQuery = "#main > div > div:eq(1) > center > img"; //*[@id="main"]/div/div[2]/center/img
|
||||
Document doc;
|
||||
try
|
||||
{
|
||||
Connection.Response result = Jsoup.connect(url).method(Connection.Method.GET).execute();
|
||||
doc = result.parse();
|
||||
//Fetch the right element
|
||||
Elements coverElements = doc.select(cssQuery);
|
||||
if (coverElements.first() != null)
|
||||
{
|
||||
Element coverElement = coverElements.first();
|
||||
String absoluteUrl = coverElement.absUrl("src");
|
||||
|
||||
URL imageUrl = new URL(absoluteUrl);
|
||||
BufferedImage c = ImageIO.read(imageUrl);
|
||||
ImageIcon image = new ImageIcon(c);
|
||||
|
||||
saveImage(absoluteUrl, game + "-large.jpg");
|
||||
|
||||
System.out.println("Big Cover art: " + absoluteUrl);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveImage(String imageUrl, String destinationFile) throws IOException {
|
||||
URL url = new URL(imageUrl);
|
||||
InputStream is = url.openStream();
|
||||
OutputStream os = new FileOutputStream(destinationFile);
|
||||
|
||||
byte[] b = new byte[2048];
|
||||
int length;
|
||||
|
||||
while ((length = is.read(b)) != -1) {
|
||||
os.write(b, 0, length);
|
||||
}
|
||||
|
||||
is.close();
|
||||
os.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package se.lantz.util;
|
||||
|
||||
import java.awt.IllegalComponentStateException;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
/**
|
||||
* An exception handler that replaces the default exception handler in Java. This class catches all uncaught exceptions
|
||||
* in the EventDispatchThread. This gives a consistent error handling strategy for the application.
|
||||
*
|
||||
*/
|
||||
public class TopLevelExceptionHandler implements Thread.UncaughtExceptionHandler
|
||||
{
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e)
|
||||
{
|
||||
// Workaround for IMOD-86609 (Java bug JDK-8179665)
|
||||
if (e instanceof IllegalComponentStateException &&
|
||||
"component must be showing on the screen to determine its location".equals(e.getMessage()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
SwingUtilities.invokeLater(() -> ExceptionHandler.handleException(e, ""));
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 951 B |
|
@ -0,0 +1,30 @@
|
|||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>pcusb.log</file>
|
||||
<append>true</append>
|
||||
<!-- set immediateFlush to false for much higher logging throughput -->
|
||||
<immediateFlush>true</immediateFlush>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>pcusb-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
<totalSizeCap>100Mb</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>1MB</maxFileSize>
|
||||
</triggeringPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="debug">
|
||||
<appender-ref ref="STDOUT" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
</configuration>
|
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 133 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 494 B |
After Width: | Height: | Size: 772 B |
After Width: | Height: | Size: 951 B |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 704 B |