From b97f3960ecc231033801c1fde663dbcaccbea74d Mon Sep 17 00:00:00 2001 From: myk Date: Mon, 11 Mar 2013 21:31:10 +0000 Subject: [PATCH] add pic import options --- .../java/forge/gui/DialogMigrateProfile.java | 111 ++++++++++++------ .../forge/gui/MigrationSourceAnalyzer.java | 87 ++++++++++++-- 2 files changed, 149 insertions(+), 49 deletions(-) diff --git a/src/main/java/forge/gui/DialogMigrateProfile.java b/src/main/java/forge/gui/DialogMigrateProfile.java index 7b5fe676096..a4444ee67cd 100644 --- a/src/main/java/forge/gui/DialogMigrateProfile.java +++ b/src/main/java/forge/gui/DialogMigrateProfile.java @@ -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> selection : _selections.values()) { - FCheckBox cb = selection.getLeft(); - Map 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 checkCancel = new Callable() { - @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 { private final Map _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>> 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 diff --git a/src/main/java/forge/gui/MigrationSourceAnalyzer.java b/src/main/java/forge/gui/MigrationSourceAnalyzer.java index bf0150e649a..a3f71039bb2 100644 --- a/src/main/java/forge/gui/MigrationSourceAnalyzer.java +++ b/src/main/java/forge/gui/MigrationSourceAnalyzer.java @@ -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> _opDb; - private final Callable _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> opDb, Callable 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; } }