Added saved window geometry
This commit is contained in:
parent
c88ecf0bc8
commit
35ae7bacac
4 changed files with 150 additions and 48 deletions
|
@ -5,6 +5,7 @@ Changelog
|
||||||
- Incorporated strict-then-sloppy XML parsing into the patch process
|
- Incorporated strict-then-sloppy XML parsing into the patch process
|
||||||
- Added XML Sandbox for syntax tinkering
|
- Added XML Sandbox for syntax tinkering
|
||||||
- Added scrollbars to progress popups to show long error messages
|
- Added scrollbars to progress popups to show long error messages
|
||||||
|
- The main window's geometry is saved on exit
|
||||||
|
|
||||||
1.1:
|
1.1:
|
||||||
- Added a button to open the mods/ folder
|
- Added a button to open the mods/ folder
|
||||||
|
|
|
@ -2,12 +2,9 @@ package net.vhati.modmanager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
@ -16,6 +13,7 @@ import javax.swing.UIManager;
|
||||||
import net.vhati.modmanager.cli.SlipstreamCLI;
|
import net.vhati.modmanager.cli.SlipstreamCLI;
|
||||||
import net.vhati.modmanager.core.ComparableVersion;
|
import net.vhati.modmanager.core.ComparableVersion;
|
||||||
import net.vhati.modmanager.core.FTLUtilities;
|
import net.vhati.modmanager.core.FTLUtilities;
|
||||||
|
import net.vhati.modmanager.core.SlipstreamConfig;
|
||||||
import net.vhati.modmanager.ui.ManagerFrame;
|
import net.vhati.modmanager.ui.ManagerFrame;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
@ -144,49 +142,34 @@ public class FTLModManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final SlipstreamConfig appConfig = new SlipstreamConfig( config, configFile );
|
||||||
if ( writeConfig ) {
|
if ( writeConfig ) {
|
||||||
OutputStream out = null;
|
|
||||||
try {
|
try {
|
||||||
out = new FileOutputStream( configFile );
|
appConfig.writeConfig();
|
||||||
String configComments = "";
|
|
||||||
configComments += "\n";
|
|
||||||
configComments += " allow_zip - Sets whether to treat .zip files as .ftl files. Default: false.\n";
|
|
||||||
configComments += " ftl_dats_path - The path to FTL's resources folder. If invalid, you'll be prompted.\n";
|
|
||||||
configComments += " never_run_ftl - If true, there will be no offer to run FTL after patching. Default: false.\n";
|
|
||||||
configComments += " update_catalog - If true, periodically download descriptions for the latest mods. If invalid, you'll be prompted.\n";
|
|
||||||
configComments += " use_default_ui - If true, no attempt will be made to resemble a native GUI. Default: false.\n";
|
|
||||||
|
|
||||||
OutputStreamWriter writer = new OutputStreamWriter( out, "UTF-8" );
|
|
||||||
config.store( writer, configComments );
|
|
||||||
writer.flush();
|
|
||||||
}
|
}
|
||||||
catch ( IOException e ) {
|
catch ( IOException e ) {
|
||||||
log.error( "Error saving config to "+ configFile.getPath(), e );
|
String errorMsg = String.format( "Error writing config to \"%s\".", configFile.getPath() );
|
||||||
showErrorDialog( "Error saving config to "+ configFile.getPath() );
|
log.error( errorMsg, e );
|
||||||
}
|
showErrorDialog( errorMsg );
|
||||||
finally {
|
|
||||||
try {if ( out != null ) out.close();}
|
|
||||||
catch ( IOException e ) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the GUI.
|
// Create the GUI.
|
||||||
try {
|
|
||||||
final ManagerFrame frame = new ManagerFrame( config, APP_NAME, APP_VERSION, APP_URL, APP_AUTHOR );
|
|
||||||
frame.setVisible(true);
|
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
try {
|
||||||
|
ManagerFrame frame = new ManagerFrame( appConfig, APP_NAME, APP_VERSION, APP_URL, APP_AUTHOR );
|
||||||
frame.init();
|
frame.init();
|
||||||
}
|
frame.setVisible(true);
|
||||||
});
|
} catch ( Exception e ) {
|
||||||
}
|
|
||||||
catch ( Exception e ) {
|
|
||||||
log.error( "Exception while creating ManagerFrame.", e );
|
log.error( "Exception while creating ManagerFrame.", e );
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void showErrorDialog( String message ) {
|
private static void showErrorDialog( String message ) {
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package net.vhati.modmanager.core;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
|
||||||
|
public class SlipstreamConfig {
|
||||||
|
|
||||||
|
private Properties config;
|
||||||
|
private File configFile;
|
||||||
|
|
||||||
|
|
||||||
|
public SlipstreamConfig( Properties config, File configFile ) {
|
||||||
|
this.config = config;
|
||||||
|
this.configFile = configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Properties getConfig() { return config; }
|
||||||
|
|
||||||
|
public File getConfigFile() { return configFile; }
|
||||||
|
|
||||||
|
|
||||||
|
public Object setProperty( String key, String value ) {
|
||||||
|
return config.setProperty( key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty( String key, String defaultValue ) {
|
||||||
|
return config.getProperty( key, defaultValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty( String key ) {
|
||||||
|
return config.getProperty( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void writeConfig() throws IOException {
|
||||||
|
|
||||||
|
OutputStream out = null;
|
||||||
|
try {
|
||||||
|
out = new FileOutputStream( configFile );
|
||||||
|
String configComments = "";
|
||||||
|
configComments += "\n";
|
||||||
|
configComments += " allow_zip - Sets whether to treat .zip files as .ftl files. Default: false.\n";
|
||||||
|
configComments += " ftl_dats_path - The path to FTL's resources folder. If invalid, you'll be prompted.\n";
|
||||||
|
configComments += " never_run_ftl - If true, there will be no offer to run FTL after patching. Default: false.\n";
|
||||||
|
configComments += " update_catalog - If true, periodically download descriptions for the latest mods. If invalid, you'll be prompted.\n";
|
||||||
|
configComments += " use_default_ui - If true, no attempt will be made to resemble a native GUI. Default: false.\n";
|
||||||
|
configComments += " manager_geometry - Saved position/size/etc of the main window.\n";
|
||||||
|
|
||||||
|
OutputStreamWriter writer = new OutputStreamWriter( out, "UTF-8" );
|
||||||
|
config.store( writer, configComments );
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {if ( out != null ) out.close();}
|
||||||
|
catch ( IOException e ) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import java.awt.Component;
|
||||||
import java.awt.Desktop;
|
import java.awt.Desktop;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
@ -32,7 +33,8 @@ import java.util.HashMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.DropMode;
|
import javax.swing.DropMode;
|
||||||
|
@ -69,6 +71,7 @@ import net.vhati.modmanager.core.ModPatchThread.BackedUpDat;
|
||||||
import net.vhati.modmanager.core.ModUtilities;
|
import net.vhati.modmanager.core.ModUtilities;
|
||||||
import net.vhati.modmanager.core.Report;
|
import net.vhati.modmanager.core.Report;
|
||||||
import net.vhati.modmanager.core.Report.ReportFormatter;
|
import net.vhati.modmanager.core.Report.ReportFormatter;
|
||||||
|
import net.vhati.modmanager.core.SlipstreamConfig;
|
||||||
import net.vhati.modmanager.json.GrognakCatalogFetcher;
|
import net.vhati.modmanager.json.GrognakCatalogFetcher;
|
||||||
import net.vhati.modmanager.json.JacksonGrognakCatalogReader;
|
import net.vhati.modmanager.json.JacksonGrognakCatalogReader;
|
||||||
import net.vhati.modmanager.ui.ChecklistTableModel;
|
import net.vhati.modmanager.ui.ChecklistTableModel;
|
||||||
|
@ -95,7 +98,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
private File catalogFile = new File( backupDir, "current_catalog.json" );
|
private File catalogFile = new File( backupDir, "current_catalog.json" );
|
||||||
private File catalogETagFile = new File( backupDir, "current_catalog_etag.txt" );
|
private File catalogETagFile = new File( backupDir, "current_catalog_etag.txt" );
|
||||||
|
|
||||||
private Properties config;
|
private SlipstreamConfig appConfig;
|
||||||
private String appName;
|
private String appName;
|
||||||
private ComparableVersion appVersion;
|
private ComparableVersion appVersion;
|
||||||
private String appURL;
|
private String appURL;
|
||||||
|
@ -122,15 +125,15 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
private JButton toggleAllBtn;
|
private JButton toggleAllBtn;
|
||||||
private JButton validateBtn;
|
private JButton validateBtn;
|
||||||
private JButton modsFolderBtn;
|
private JButton modsFolderBtn;
|
||||||
|
private JSplitPane splitPane;
|
||||||
private ModInfoArea infoArea;
|
private ModInfoArea infoArea;
|
||||||
|
|
||||||
private JLabel statusLbl;
|
private JLabel statusLbl;
|
||||||
|
|
||||||
|
|
||||||
public ManagerFrame( Properties config, String appName, ComparableVersion appVersion, String appURL, String appAuthor ) {
|
public ManagerFrame( SlipstreamConfig appConfig, String appName, ComparableVersion appVersion, String appURL, String appAuthor ) {
|
||||||
super();
|
super();
|
||||||
this.config = config;
|
this.appConfig = appConfig;
|
||||||
this.appName = appName;
|
this.appName = appName;
|
||||||
this.appVersion = appVersion;
|
this.appVersion = appVersion;
|
||||||
this.appURL = appURL;
|
this.appURL = appURL;
|
||||||
|
@ -211,7 +214,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
infoArea = new ModInfoArea();
|
infoArea = new ModInfoArea();
|
||||||
infoArea.setPreferredSize( new Dimension(504, 220) );
|
infoArea.setPreferredSize( new Dimension(504, 220) );
|
||||||
|
|
||||||
JSplitPane splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
|
splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
|
||||||
splitPane.setTopComponent( topPanel );
|
splitPane.setTopComponent( topPanel );
|
||||||
splitPane.setBottomComponent( infoArea );
|
splitPane.setBottomComponent( infoArea );
|
||||||
mainPane.add( splitPane, BorderLayout.CENTER );
|
mainPane.add( splitPane, BorderLayout.CENTER );
|
||||||
|
@ -236,6 +239,22 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
}
|
}
|
||||||
saveModOrder( sortedMods );
|
saveModOrder( sortedMods );
|
||||||
|
|
||||||
|
SlipstreamConfig appConfig = ManagerFrame.this.appConfig;
|
||||||
|
|
||||||
|
if ( ManagerFrame.this.getExtendedState() == JFrame.NORMAL ) {
|
||||||
|
Rectangle managerBounds = ManagerFrame.this.getBounds();
|
||||||
|
int dividerLoc = splitPane.getDividerLocation();
|
||||||
|
String geometry = String.format( "x,%d;y,%d;w,%d;h,%d;divider,%d", managerBounds.x, managerBounds.y, managerBounds.width, managerBounds.height, dividerLoc );
|
||||||
|
appConfig.setProperty( "manager_geometry", geometry );
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
appConfig.writeConfig();
|
||||||
|
}
|
||||||
|
catch ( IOException f ) {
|
||||||
|
log.error( String.format( "Error writing config to \"%s\".", appConfig.getConfigFile() ), f );
|
||||||
|
}
|
||||||
|
|
||||||
System.exit( 0 );
|
System.exit( 0 );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -329,9 +348,44 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
this.setMinimumSize( new Dimension( 300, modActionsPanel.getPreferredSize().height+90 ) );
|
this.setMinimumSize( new Dimension( 300, modActionsPanel.getPreferredSize().height+90 ) );
|
||||||
this.setLocationRelativeTo(null);
|
this.setLocationRelativeTo(null);
|
||||||
|
|
||||||
|
setGeometryFromConfig();
|
||||||
|
|
||||||
showAboutInfo();
|
showAboutInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setGeometryFromConfig() {
|
||||||
|
String geometry = appConfig.getProperty( "manager_geometry" );
|
||||||
|
if ( geometry != null ) {
|
||||||
|
int[] xywh = new int[4];
|
||||||
|
int dividerLoc = -1;
|
||||||
|
Matcher m = Pattern.compile( "([^;,]+),(\\d+)" ).matcher( geometry );
|
||||||
|
while ( m.find() ) {
|
||||||
|
if ( m.group(1).equals( "x" ) )
|
||||||
|
xywh[0] = Integer.parseInt( m.group(2) );
|
||||||
|
else if ( m.group(1).equals( "y" ) )
|
||||||
|
xywh[1] = Integer.parseInt( m.group(2) );
|
||||||
|
else if ( m.group(1).equals( "w" ) )
|
||||||
|
xywh[2] = Integer.parseInt( m.group(2) );
|
||||||
|
else if ( m.group(1).equals( "h" ) )
|
||||||
|
xywh[3] = Integer.parseInt( m.group(2) );
|
||||||
|
else if ( m.group(1).equals( "divider" ) )
|
||||||
|
dividerLoc = Integer.parseInt( m.group(2) );
|
||||||
|
}
|
||||||
|
boolean badGeometry = false;
|
||||||
|
for ( int n : xywh ) {
|
||||||
|
if ( n <= 0 ) {
|
||||||
|
badGeometry = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !badGeometry && dividerLoc > 0 ) {
|
||||||
|
Rectangle newBounds = new Rectangle( xywh[0], xywh[1], xywh[2], xywh[3] );
|
||||||
|
ManagerFrame.this.setBounds( newBounds );
|
||||||
|
splitPane.setDividerLocation( dividerLoc );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extra initialization that must be called after the constructor.
|
* Extra initialization that must be called after the constructor.
|
||||||
* This must be called on the Swing event thread (use invokeLater()).
|
* This must be called on the Swing event thread (use invokeLater()).
|
||||||
|
@ -365,7 +419,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't update if the user doesn't want to.
|
// Don't update if the user doesn't want to.
|
||||||
String updatesAllowed = config.getProperty( "update_catalog", "false" );
|
String updatesAllowed = appConfig.getProperty( "update_catalog", "false" );
|
||||||
if ( !updatesAllowed.equals("true") ) needNewCatalog = false;
|
if ( !updatesAllowed.equals("true") ) needNewCatalog = false;
|
||||||
|
|
||||||
if ( needNewCatalog ) {
|
if ( needNewCatalog ) {
|
||||||
|
@ -487,7 +541,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
modFileHashes.clear();
|
modFileHashes.clear();
|
||||||
localModsTableModel.removeAllItems();
|
localModsTableModel.removeAllItems();
|
||||||
|
|
||||||
boolean allowZip = config.getProperty( "allow_zip", "false" ).equals( "true" );
|
boolean allowZip = appConfig.getProperty( "allow_zip", "false" ).equals( "true" );
|
||||||
File[] modFiles = modsDir.listFiles( new ModFileFilter( allowZip ) );
|
File[] modFiles = modsDir.listFiles( new ModFileFilter( allowZip ) );
|
||||||
|
|
||||||
List<ModFileInfo> unsortedMods = new ArrayList<ModFileInfo>();
|
List<ModFileInfo> unsortedMods = new ArrayList<ModFileInfo>();
|
||||||
|
@ -585,7 +639,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File datsDir = new File( config.getProperty( "ftl_dats_path" ) );
|
File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) );
|
||||||
|
|
||||||
BackedUpDat dataDat = new BackedUpDat();
|
BackedUpDat dataDat = new BackedUpDat();
|
||||||
dataDat.datFile = new File( datsDir, "data.dat" );
|
dataDat.datFile = new File( datsDir, "data.dat" );
|
||||||
|
@ -683,7 +737,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
|
|
||||||
File extractDir = extractChooser.getSelectedFile();
|
File extractDir = extractChooser.getSelectedFile();
|
||||||
|
|
||||||
File datsDir = new File( config.getProperty( "ftl_dats_path" ) );
|
File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) );
|
||||||
File dataDatFile = new File( datsDir, "data.dat" );
|
File dataDatFile = new File( datsDir, "data.dat" );
|
||||||
File resDatFile = new File( datsDir, "resource.dat" );
|
File resDatFile = new File( datsDir, "resource.dat" );
|
||||||
File[] datFiles = new File[] {dataDatFile, resDatFile};
|
File[] datFiles = new File[] {dataDatFile, resDatFile};
|
||||||
|
@ -693,7 +747,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
extractDlg.setVisible( true );
|
extractDlg.setVisible( true );
|
||||||
}
|
}
|
||||||
else if ( source == sandboxMenuItem ) {
|
else if ( source == sandboxMenuItem ) {
|
||||||
File datsDir = new File( config.getProperty( "ftl_dats_path" ) );
|
File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) );
|
||||||
File dataDatFile = new File( datsDir, "data.dat" );
|
File dataDatFile = new File( datsDir, "data.dat" );
|
||||||
|
|
||||||
ModXMLSandbox sandboxFrame = new ModXMLSandbox( dataDatFile );
|
ModXMLSandbox sandboxFrame = new ModXMLSandbox( dataDatFile );
|
||||||
|
@ -738,9 +792,9 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
private class SpawnGameTask implements Runnable {
|
private class SpawnGameTask implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String neverRunFtl = config.getProperty( "never_run_ftl", "false" );
|
String neverRunFtl = appConfig.getProperty( "never_run_ftl", "false" );
|
||||||
if ( !neverRunFtl.equals("true") ) {
|
if ( !neverRunFtl.equals("true") ) {
|
||||||
File datsDir = new File( config.getProperty( "ftl_dats_path" ) );
|
File datsDir = new File( appConfig.getProperty( "ftl_dats_path" ) );
|
||||||
|
|
||||||
File exeFile = FTLUtilities.findGameExe( datsDir );
|
File exeFile = FTLUtilities.findGameExe( datsDir );
|
||||||
if ( exeFile != null ) {
|
if ( exeFile != null ) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue