Refactored modorder as modsTableState

This commit is contained in:
Vhati 2013-11-22 00:15:24 -05:00
parent 1a5bf935df
commit e25799a78e
3 changed files with 110 additions and 47 deletions

View file

@ -79,6 +79,7 @@ import net.vhati.modmanager.ui.SlipstreamConfigDialog;
import net.vhati.modmanager.ui.Statusbar;
import net.vhati.modmanager.ui.StatusbarMouseListener;
import net.vhati.modmanager.ui.table.ChecklistTablePanel;
import net.vhati.modmanager.ui.table.ListState;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -94,7 +95,7 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
private File backupDir = new File( "./backup/" );
private File modsDir = new File( "./mods/" );
private File modorderFile = new File( modsDir, "modorder.txt" );
private File modsTableStateFile = new File( modsDir, "modorder.txt" );
private File metadataFile = new File( backupDir, "cached_metadata.json" );
@ -260,8 +261,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
public void windowClosed( WindowEvent e ) {
// dispose() was called.
List<ModFileInfo> sortedMods = modsTablePanel.getAllItems();
saveModOrder( sortedMods );
ListState<ModFileInfo> tableState = getCurrentModsTableState();
saveModsTableState( tableState );
SlipstreamConfig appConfig = ManagerFrame.this.appConfig;
@ -395,7 +396,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
ManagerInitThread initThread = new ManagerInitThread( this,
new SlipstreamConfig( appConfig ),
modorderFile,
modsDir,
modsTableStateFile,
metadataFile,
catalogFile,
catalogETagFile,
@ -409,48 +411,60 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
/**
* Returns a mod list with names sorted in a preferred order.
*
* Mods not mentioned in the name list appear at the end, alphabetically.
* Returns a ListState describing content in the mods table.
*/
private List<ModFileInfo> reorderMods( List<ModFileInfo> unsortedMods, List<String> preferredOrder ) {
List<ModFileInfo> sortedMods = new ArrayList<ModFileInfo>();
public ListState<ModFileInfo> getCurrentModsTableState() {
ListState<ModFileInfo> tableState = new ListState<ModFileInfo>();
for ( ModFileInfo modFileInfo : modsTablePanel.getAllItems() ) {
tableState.addItem( modFileInfo );
}
return tableState;
}
/**
* Synchronizes a mods table state with a pool of available items.
*
* Items in the table that also are in the pool are unchanged.
* Items in the table that aren't in the pool are pruned.
* Items in the pool that weren't in the table are appended in ascending
* order.
*
* @param tableState an existing state to amend
* @param unsortedMods the pool of currently available local mods
*/
public void amendModsTableState( ListState<ModFileInfo> tableState, List<ModFileInfo> unsortedMods ) {
List<ModFileInfo> availableMods = new ArrayList<ModFileInfo>( unsortedMods );
Collections.sort( availableMods );
if ( preferredOrder != null ) {
for ( String name : preferredOrder ) {
Iterator<ModFileInfo> it = availableMods.iterator();
while ( it.hasNext() ) {
ModFileInfo modFileInfo = it.next();
if ( modFileInfo.getName().equals( name ) ) {
it.remove();
sortedMods.add( modFileInfo );
break;
for ( ModFileInfo modFileInfo : availableMods ) {
if ( !tableState.containsItem( modFileInfo ) ) {
tableState.addItem( modFileInfo );
}
}
for ( ModFileInfo modFileInfo : tableState.getItems() ) {
if ( !availableMods.contains( modFileInfo ) ) {
tableState.removeItem( modFileInfo );
}
}
sortedMods.addAll( availableMods );
return sortedMods;
}
private void saveModOrder( List<ModFileInfo> sortedMods ) {
private void saveModsTableState( ListState<ModFileInfo> tableState ) {
BufferedWriter bw = null;
try {
FileOutputStream os = new FileOutputStream( modorderFile );
FileOutputStream os = new FileOutputStream( modsTableStateFile );
bw = new BufferedWriter(new OutputStreamWriter( os, Charset.forName("UTF-8") ));
for ( ModFileInfo modFileInfo : sortedMods ) {
for ( ModFileInfo modFileInfo : tableState.getItems() ) {
bw.write( modFileInfo.getName() );
bw.write( "\r\n" );
}
bw.flush();
}
catch ( IOException e ) {
log.error( String.format( "Error writing \"%s\".", modorderFile.getName() ), e );
log.error( String.format( "Error writing \"%s\".", modsTableStateFile.getName() ), e );
}
finally {
try {if (bw != null) bw.close();}
@ -460,9 +474,10 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
/**
* Clears and syncs the mods list with mods/ dir, then starts a new hash thread.
* Clears and syncs the mods list with mods/ dir, then starts a new hash
* thread.
*/
public void rescanMods( List<String> preferredOrder ) {
public void rescanMods( ListState<ModFileInfo> tableState ) {
managerLock.lock();
try {
scanning = true;
@ -484,9 +499,9 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
ModFileInfo modFileInfo = new ModFileInfo( f );
unsortedMods.add( modFileInfo );
}
amendModsTableState( tableState, unsortedMods );
List<ModFileInfo> sortedMods = reorderMods( unsortedMods, preferredOrder );
for ( ModFileInfo modFileInfo : sortedMods ) {
for ( ModFileInfo modFileInfo : tableState.getItems() ) {
modsTablePanel.getTableModel().addItem( modFileInfo );
}
@ -732,12 +747,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
setStatusText( "" );
if ( rescanMenuItem.isEnabled() == false ) return;
List<String> preferredOrder = new ArrayList<String>();
for ( ModFileInfo modFileInfo : modsTablePanel.getAllItems() ) {
preferredOrder.add( modFileInfo.getName() );
}
rescanMods( preferredOrder );
ListState<ModFileInfo> tableState = getCurrentModsTableState();
rescanMods( tableState );
}
else if ( source == extractDatsMenuItem ) {
setStatusText( "" );

View file

@ -17,11 +17,13 @@ import javax.swing.SwingUtilities;
import net.vhati.modmanager.core.AutoUpdateInfo;
import net.vhati.modmanager.core.ModDB;
import net.vhati.modmanager.core.ModFileInfo;
import net.vhati.modmanager.core.SlipstreamConfig;
import net.vhati.modmanager.json.JacksonAutoUpdateReader;
import net.vhati.modmanager.json.JacksonCatalogReader;
import net.vhati.modmanager.json.URLFetcher;
import net.vhati.modmanager.ui.ManagerFrame;
import net.vhati.modmanager.ui.table.ListState;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -41,7 +43,8 @@ public class ManagerInitThread extends Thread {
private final ManagerFrame frame;
private final SlipstreamConfig appConfig;
private final File modorderFile;
private final File modsDir;
private final File modsTableStateFile;
private final File metadataFile;
private final File catalogFile;
private final File catalogETagFile;
@ -49,10 +52,11 @@ public class ManagerInitThread extends Thread {
private final File appUpdateETagFile;
public ManagerInitThread( ManagerFrame frame, SlipstreamConfig appConfig, File modorderFile, File metadataFile, File catalogFile, File catalogETagFile, File appUpdateFile, File appUpdateETagFile ) {
public ManagerInitThread( ManagerFrame frame, SlipstreamConfig appConfig, File modsDir, File modsTableStateFile, File metadataFile, File catalogFile, File catalogETagFile, File appUpdateFile, File appUpdateETagFile ) {
this.frame = frame;
this.appConfig = appConfig;
this.modorderFile = modorderFile;
this.modsDir = modsDir;
this.modsTableStateFile = modsTableStateFile;
this.metadataFile = metadataFile;
this.catalogFile = catalogFile;
this.catalogETagFile = catalogETagFile;
@ -79,14 +83,14 @@ public class ManagerInitThread extends Thread {
if ( cachedDB != null ) frame.setLocalModDB( cachedDB );
}
final List<String> preferredOrder = loadModOrder();
final ListState<ModFileInfo> tableState = loadModsTableState();
Lock managerLock = frame.getLock();
managerLock.lock();
try {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { frame.rescanMods( preferredOrder ); }
public void run() { frame.rescanMods( tableState ); }
});
// Wait until notified that "mods/" has been scanned.
@ -167,28 +171,37 @@ public class ManagerInitThread extends Thread {
/**
* Reads modorder.txt and returns a list of mod names in preferred order.
*/
private List<String> loadModOrder() {
List<String> result = new ArrayList<String>();
private ListState<ModFileInfo> loadModsTableState() {
List<String> fileNames = new ArrayList<String>();
BufferedReader br = null;
try {
FileInputStream is = new FileInputStream( modorderFile );
FileInputStream is = new FileInputStream( modsTableStateFile );
br = new BufferedReader(new InputStreamReader( is, Charset.forName("UTF-8") ));
String line;
while ( (line = br.readLine()) != null ) {
result.add( line );
fileNames.add( line );
}
}
catch ( FileNotFoundException e ) {
}
catch ( IOException e ) {
log.error( String.format( "Error reading \"%s\".", modorderFile.getName() ), e );
log.error( String.format( "Error reading \"%s\".", modsTableStateFile.getName() ), e );
fileNames.clear();
}
finally {
try {if ( br != null ) br.close();}
catch ( Exception e ) {}
}
ListState<ModFileInfo> result = new ListState<ModFileInfo>();
for ( String fileName : fileNames ) {
File modFile = new File( modsDir, fileName );
ModFileInfo modFileInfo = new ModFileInfo( modFile );
result.addItem( modFileInfo );
}
return result;
}

View file

@ -0,0 +1,39 @@
package net.vhati.modmanager.ui.table;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* An implementation-agnostic model to pass between the GUI thread and the
* (de)serializer.
*/
public class ListState<T> {
protected List<T> items = new ArrayList<T>();
public ListState() {
}
public void addItem( T item ) {
items.add( item );
}
/**
* Returns a new list containing items in this state.
*/
public List<T> getItems() {
return new ArrayList<T>( items );
}
public void removeItem( T item ) {
items.remove( item );
}
public boolean containsItem( T item ) {
return items.contains( item );
}
}