add pic import options

This commit is contained in:
myk
2013-03-11 21:31:10 +00:00
parent 57020ed3b3
commit b97f3960ec
2 changed files with 149 additions and 49 deletions

View File

@@ -17,6 +17,7 @@
*/
package forge.gui;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
@@ -26,19 +27,20 @@ import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DefaultCaret;
import net.miginfocom.swing.MigLayout;
@@ -52,7 +54,6 @@ import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FOverlay;
import forge.gui.toolbox.FPanel;
import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FTextArea;
import forge.gui.toolbox.FTextField;
import forge.properties.NewConstants;
@@ -185,7 +186,7 @@ public class DialogMigrateProfile {
private final String _srcDir;
private final JComboBox _unknownDeckCombo;
private final FCheckBox _moveCheckbox;
private final FTextArea _operationLog;
private final JTextArea _operationLog;
private final JProgressBar _progressBar;
// used to ensure we only have one UI update pending at a time
@@ -223,14 +224,25 @@ public class DialogMigrateProfile {
knownDeckPanel.add(unknownDeckPanel, "span");
cbPanel.add(knownDeckPanel, "aligny top");
// add other data elements (gauntlets, quest data)
// add other userDir data elements
JPanel dataPanel = new JPanel(new MigLayout("insets 0, gap 5, wrap"));
dataPanel.setOpaque(false);
dataPanel.add(new FLabel.Builder().text("Other data").build());
_addSelectionWidget(dataPanel, forced, OpType.GAUNTLET_DATA, "Gauntlet data");
_addSelectionWidget(dataPanel, forced, OpType.QUEST_DATA, "Quest saves");
_addSelectionWidget(dataPanel, forced, OpType.GAUNTLET_DATA, "Gauntlet data");
_addSelectionWidget(dataPanel, forced, OpType.QUEST_DATA, "Quest saves");
_addSelectionWidget(dataPanel, forced, OpType.PREFERENCE_FILE, "Preference files");
cbPanel.add(dataPanel, "aligny top");
// add cacheDir data elements
JPanel cachePanel = new JPanel(new MigLayout("insets 0, gap 5, wrap 2"));
cachePanel.setOpaque(false);
cachePanel.add(new FLabel.Builder().text("Cached data").build());
_addSelectionWidget(cachePanel, forced, OpType.DEFAULT_CARD_PIC, "Default card pics");
_addSelectionWidget(cachePanel, forced, OpType.SET_CARD_PIC, "Set-specific card pics");
_addSelectionWidget(cachePanel, forced, OpType.TOKEN_PIC, "Card token pics");
_addSelectionWidget(cachePanel, forced, OpType.QUEST_PIC, "Quest-related pics");
_addSelectionWidget(cachePanel, forced, OpType.DB_FILE, "Database files");
cbPanel.add(cachePanel, "aligny top");
_selectionPanel.add(cbPanel, "center");
// add move/copy checkbox
@@ -241,8 +253,15 @@ public class DialogMigrateProfile {
_selectionPanel.add(_moveCheckbox);
// add operation summary textfield
_operationLog = new FTextArea();
_operationLog.setFocusable(true);
_operationLog = new JTextArea();
_operationLog.setFont(new Font("Monospaced", Font.PLAIN, 10));
_operationLog.setOpaque(false);
_operationLog.setWrapStyleWord(true);
_operationLog.setLineWrap(true);
_operationLog.setEditable(false);
// autoscroll to bottom when we append text
DefaultCaret caret = (DefaultCaret)_operationLog.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
JScrollPane scroller = new JScrollPane(_operationLog);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
_selectionPanel.add(scroller, "w 600:100%:100%, h 60:100%:100%");
@@ -274,15 +293,15 @@ public class DialogMigrateProfile {
StringBuilder log = new StringBuilder();
int totalOps = 0;
for (Pair<FCheckBox, ? extends Map<File, File>> selection : _selections.values()) {
FCheckBox cb = selection.getLeft();
Map<File, File> ops = selection.getRight();
FCheckBox cb = selection.getLeft();
int numOps = selection.getRight().size();
if (cb.isSelected()) {
totalOps += ops.size();
totalOps += numOps;
}
// update checkbox text with new totals
cb.setText(String.format("%s (%d)", cb.getName(), ops.size()));
cb.setText(String.format("%s (%d)", cb.getName(), numOps));
}
log.append(_moveCheckbox.isSelected() ? "Moving" : "Copying");
log.append(" ").append(totalOps).append(" files\n\n");
@@ -301,7 +320,6 @@ public class DialogMigrateProfile {
}
}
_operationLog.setText(log.toString());
_uiUpdateAck = true;
}
@@ -320,46 +338,64 @@ public class DialogMigrateProfile {
selections.put(entry.getKey(), entry.getValue().getRight());
}
Callable<Boolean> checkCancel = new Callable<Boolean>() {
@Override public Boolean call() { return _cancel; }
MigrationSourceAnalyzer.AnalysisCallback cb = new MigrationSourceAnalyzer.AnalysisCallback() {
@Override
public boolean checkCancel() { return _cancel; }
@Override
public void addOp(OpType type, File src, File dest) {
_selections.get(type).getRight().put(src, dest);
}
};
final MigrationSourceAnalyzer msa = new MigrationSourceAnalyzer(_srcDir, selections, checkCancel);
final MigrationSourceAnalyzer msa = new MigrationSourceAnalyzer(_srcDir, cb);
final int numFilesToAnalyze = msa.getNumFilesToAnalyze();
final Timer timer = new Timer(500, null);
timer.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent arg0) {
if (_cancel) {
timer.stop();
return;
}
// timers run in the gui event loop, so it's ok to interact with widgets
_progressBar.setValue(msa.getNumFilesAnalyzed());
// only update if we don't already have an update pending. we may not be prompt in
// updating sometimes, but that's ok
if (!_uiUpdateAck) { return; }
_uiUpdateAck = false;
_stateChangedListener.stateChanged(null);
}
});
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
if (_cancel) { return; }
_progressBar.setMaximum(numFilesToAnalyze);
_progressBar.setValue(0);
_progressBar.setIndeterminate(false);
// start update timer
final Timer timer = new Timer(500, null);
timer.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent arg0) {
if (_cancel) {
timer.stop();
return;
}
_progressBar.setValue(msa.getNumFilesAnalyzed());
// only update if we don't already have an update pending. we may not be prompt in
// updating sometimes, but that's ok
if (!_uiUpdateAck) { return; }
_uiUpdateAck = false;
_stateChangedListener.stateChanged(null);
}
});
timer.start();
}
});
msa.doAnalysis();
timer.stop();
return null;
}
// executes in gui event loop thread
@Override
protected void done() {
if (_cancel) { return; }
_progressBar.setValue(_progressBar.getMaximum());
_progressBar.setString("Analysis complete");
_btnStart.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent arg0) {
_btnStart.removeActionListener(this);
@@ -378,12 +414,12 @@ public class DialogMigrateProfile {
private class _Importer extends SwingWorker<Void, Void> {
private final Map<File, File> _operations;
private final FTextArea _operationLog;
private final JProgressBar _progressBar;
private final boolean _move;
private final JTextArea _operationLog;
private final JProgressBar _progressBar;
private final boolean _move;
public _Importer(Map<OpType, Pair<FCheckBox, ? extends Map<File, File>>> selections, JComboBox unknownDeckCombo,
FTextArea operationLog, JProgressBar progressBar, boolean move) {
JTextArea operationLog, JProgressBar progressBar, boolean move) {
_operationLog = operationLog;
_progressBar = progressBar;
_move = move;
@@ -418,7 +454,6 @@ public class DialogMigrateProfile {
_progressBar.setString(_move ? "Moving files" : "Copying files");
_progressBar.setMinimum(0);
_progressBar.setMaximum(_operations.size());
_progressBar.setIndeterminate(false);
}
@Override

View File

@@ -18,8 +18,8 @@
package forge.gui;
import java.io.File;
import java.util.Map;
import java.util.concurrent.Callable;
import forge.properties.NewConstants;
public class MigrationSourceAnalyzer {
public static enum OpType {
@@ -29,22 +29,34 @@ public class MigrationSourceAnalyzer {
SCHEME_DECK,
SEALED_DECK,
UNKNOWN_DECK,
DEFAULT_CARD_PIC,
SET_CARD_PIC,
TOKEN_PIC,
QUEST_PIC,
GAUNTLET_DATA,
QUEST_DATA,
PREFERENCE_FILE
PREFERENCE_FILE,
DB_FILE
}
private final String _source;
private final Map<OpType, Map<File, File>> _opDb;
private final Callable<Boolean> _checkCancel;
public static interface AnalysisCallback {
boolean checkCancel();
void addOp(OpType type, File src, File dest);
}
private final File _source;
private final AnalysisCallback _cb;
private final int _numFilesToAnalyze;
private int _numFilesToAnalyze;
private int _numFilesAnalyzed;
public MigrationSourceAnalyzer(String source, Map<OpType, Map<File, File>> opDb, Callable<Boolean> checkCancel) {
_source = source;
_opDb = opDb;
_checkCancel = checkCancel;
public MigrationSourceAnalyzer(String source, AnalysisCallback cb) {
_source = new File(source);
_cb = cb;
System.out.println("counting source files");
_numFilesToAnalyze = _countFiles(_source);
System.out.println("done counting source files: " + _numFilesToAnalyze);
}
public int getNumFilesToAnalyze() { return _numFilesToAnalyze; }
@@ -53,5 +65,58 @@ public class MigrationSourceAnalyzer {
public void doAnalysis() {
// TODO: analyze source path tree and populate operation sets
// ensure we ignore data that is already in the destination directory
_analyzeResDir(_source);
}
private void _analyzeResDir(File resRoot) {
for (File file : resRoot.listFiles()) {
if (_cb.checkCancel()) { return; }
if ("pics".equals(file.getName())) {
_analyzePicsDir(file);
}
// ignore other files
if (file.isFile()) {
++_numFilesAnalyzed;
}
if (file.isDirectory()) {
_numFilesAnalyzed += _countFiles(file);
}
}
}
private void _analyzePicsDir(File picsRoot) {
System.out.println("found pics dir: " + picsRoot);
for (File file : picsRoot.listFiles()) {
if (_cb.checkCancel()) { return; }
System.out.println("analyzing dir entry: " + file.getAbsolutePath());
if (file.isFile()) {
++_numFilesAnalyzed;
// TODO: correct filename
_cb.addOp(OpType.DEFAULT_CARD_PIC, file, new File(NewConstants.CACHE_CARD_PICS_DIR, file.getName()));
}
if (file.isDirectory()) {
// skip set pics for now
_numFilesAnalyzed += _countFiles(file);
}
}
}
private int _countFiles(File directory) {
int count = 0;
for (File file : directory.listFiles()) {
if (_cb.checkCancel()) { return 0; }
if (file.isFile()) {
++count;
}
if (file.isDirectory()) {
count += _countFiles(file);
}
}
return count;
}
}