Initial commit of wip

Initial commit
This commit is contained in:
lantzelot 2020-12-08 13:52:06 +01:00
parent 87081de90c
commit b3715ad713
67 changed files with 8934 additions and 0 deletions

14
.classpath Normal file
View File

@ -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>

18
.project Normal file
View File

@ -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>

BIN
pcusb - emptyWithTable.db Normal file

Binary file not shown.

BIN
pcusb.db Normal file

Binary file not shown.

123
pom.xml Normal file
View File

@ -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>

View File

@ -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();
});
}
}

View File

@ -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.");
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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");
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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
}
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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, ""));
}
}

BIN
src/main/resources/Icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
src/main/resources/Icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

View File

@ -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>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B