add in remaining gui elements for migration dialog

This commit is contained in:
myk
2013-03-11 11:34:35 +00:00
parent be8326438d
commit 0e0cc50173
3 changed files with 86 additions and 35 deletions

View File

@@ -25,12 +25,14 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.swing.JComboBox;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JProgressBar; import javax.swing.JProgressBar;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
@@ -95,27 +97,27 @@ public class DialogMigrateProfile {
" where to find your data.</html>").build()); " where to find your data.</html>").build());
blurbPanel.add(new FLabel.Builder().text( blurbPanel.add(new FLabel.Builder().text(
"<html><b>Remember, your data won't be available until you complete this step!</b></html>").build(), "growx"); "<html><b>Remember, your data won't be available until you complete this step!</b></html>").build(), "growx");
p.add(blurbPanel, "gap 10 10 20 20"); p.add(blurbPanel, "gap 10 10 20 0");
} }
// import source widgets // import source widgets
JPanel importSourcePanel = new JPanel(new MigLayout("insets 0, gap 5")); JPanel importSourcePanel = new JPanel(new MigLayout("insets 0, gap 10"));
importSourcePanel.setOpaque(false); importSourcePanel.setOpaque(false);
importSourcePanel.add(new FLabel.Builder().text("Import from:").build()); importSourcePanel.add(new FLabel.Builder().text("Import from:").build());
boolean emptySrcDir = StringUtils.isEmpty(srcDir); boolean emptySrcDir = StringUtils.isEmpty(srcDir);
FTextField txfSrc = new FTextField.Builder().readonly(!emptySrcDir).build(); FTextField txfSrc = new FTextField.Builder().readonly(!emptySrcDir).build();
importSourcePanel.add(txfSrc, "gap 5, pushx"); importSourcePanel.add(txfSrc, "pushx, growx");
if (!emptySrcDir) { if (!emptySrcDir) {
File srcDirFile = new File(srcDir); File srcDirFile = new File(srcDir);
txfSrc.setText(srcDirFile.getAbsolutePath()); txfSrc.setText(srcDirFile.getAbsolutePath());
} }
importSourcePanel.add(new FLabel.ButtonBuilder().text("Choose directory...").enabled(emptySrcDir).build(), "h pref+8!, w pref+12!"); importSourcePanel.add(new FLabel.ButtonBuilder().text("Choose directory...").enabled(emptySrcDir).build(), "h pref+8!, w pref+12!");
p.add(importSourcePanel, "growx"); p.add(importSourcePanel, "gaptop 20, growx");
// prepare import selection panel // prepare import selection panel
_selectionPanel = new JPanel(); _selectionPanel = new JPanel();
_selectionPanel.setOpaque(false); _selectionPanel.setOpaque(false);
p.add(_selectionPanel, "growx"); p.add(_selectionPanel, "growx, h 100%, gaptop 10");
// action button widgets // action button widgets
final Runnable cleanup = new Runnable() { final Runnable cleanup = new Runnable() {
@@ -138,16 +140,16 @@ public class DialogMigrateProfile {
} }
}; };
JPanel southPanel = new JPanel(new MigLayout("gap 20, ax center")); JPanel southPanel = new JPanel(new MigLayout("ax center"));
southPanel.setOpaque(false); southPanel.setOpaque(false);
southPanel.add(_btnStart, "center, w 40%, h pref+12!"); southPanel.add(_btnStart, "center, w 40%, h pref+12!");
southPanel.add(btnCancel, "center, w 40%, h pref+12!"); southPanel.add(btnCancel, "center, w 40%, h pref+12!");
p.add(southPanel, "dock south"); p.add(southPanel, "growx");
JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel(); JPanel overlay = FOverlay.SINGLETON_INSTANCE.getPanel();
overlay.setLayout(new MigLayout("insets 0, gap 0, wrap, ax center, ay center")); overlay.setLayout(new MigLayout("insets 0, gap 0, wrap, ax center, ay center"));
overlay.add(p, "w 700!"); overlay.add(p, "w 800::80%, h 800::90%");
SOverlayUtils.showOverlay(); SOverlayUtils.showOverlay();
// focus cancel button // focus cancel button
@@ -161,6 +163,10 @@ public class DialogMigrateProfile {
private enum OpType { private enum OpType {
CONSTRUCTED_DECK, CONSTRUCTED_DECK,
DRAFT_DECK,
PLANAR_DECK,
SCHEME_DECK,
SEALED_DECK,
UNKNOWN_DECK, UNKNOWN_DECK,
GAUNTLET_DATA, GAUNTLET_DATA,
QUEST_DATA, QUEST_DATA,
@@ -171,6 +177,11 @@ public class DialogMigrateProfile {
private final Map<OpType, Pair<FCheckBox, ? extends Set<Pair<File, File>>>> _selections = private final Map<OpType, Pair<FCheckBox, ? extends Set<Pair<File, File>>>> _selections =
new HashMap<DialogMigrateProfile.OpType, Pair<FCheckBox, ? extends Set<Pair<File, File>>>>(); new HashMap<DialogMigrateProfile.OpType, Pair<FCheckBox, ? extends Set<Pair<File, File>>>>();
ChangeListener _selectionChangeListener = new ChangeListener() {
@Override public void stateChanged(ChangeEvent arg0) { _updateUI(); }
};
private final JComboBox _unknownDeckCombo;
private final FCheckBox _moveCheckbox; private final FCheckBox _moveCheckbox;
private final FTextArea _operationLog; private final FTextArea _operationLog;
private final JProgressBar _progressBar; private final JProgressBar _progressBar;
@@ -179,28 +190,45 @@ public class DialogMigrateProfile {
_selectionPanel.removeAll(); _selectionPanel.removeAll();
_selectionPanel.setLayout(new MigLayout("insets 0, gap 5, wrap")); _selectionPanel.setLayout(new MigLayout("insets 0, gap 5, wrap"));
ChangeListener changeListener = new ChangeListener() { JPanel cbPanel = new JPanel(new MigLayout("insets 0, gap 5"));
@Override public void stateChanged(ChangeEvent arg0) { _updateUI(); } cbPanel.setOpaque(false);
};
// add known deck checkboxes // add deck selections
JPanel knownDeckPanel = new JPanel(new MigLayout("insets 0, gap 5, wrap")); JPanel knownDeckPanel = new JPanel(new MigLayout("insets 0, gap 5, wrap 2"));
knownDeckPanel.setOpaque(false); knownDeckPanel.setOpaque(false);
knownDeckPanel.add(new FLabel.Builder().text("Decks").build()); knownDeckPanel.add(new FLabel.Builder().text("Decks").build(), "wrap");
FCheckBox constructed = new FCheckBox(); _addSelectionWidget(knownDeckPanel, forced, OpType.CONSTRUCTED_DECK, "Constructed decks");
constructed.setName("Constructed decks"); _addSelectionWidget(knownDeckPanel, forced, OpType.DRAFT_DECK, "Draft decks");
constructed.addChangeListener(changeListener); _addSelectionWidget(knownDeckPanel, forced, OpType.PLANAR_DECK, "Planar decks");
_selections.put(OpType.CONSTRUCTED_DECK, Pair.of(constructed, new HashSet<Pair<File, File>>())); _addSelectionWidget(knownDeckPanel, forced, OpType.SCHEME_DECK, "Scheme decks");
_addSelectionWidget(knownDeckPanel, forced, OpType.SEALED_DECK, "Sealed decks");
// add unknown deck combobox _addSelectionWidget(knownDeckPanel, forced, OpType.UNKNOWN_DECK, "Unknown decks");
JPanel unknownDeckPanel = new JPanel(new MigLayout("insets 0, gap 5"));
unknownDeckPanel.setOpaque(false);
_unknownDeckCombo = new JComboBox();
for (String choice : Arrays.asList("Constructed", "Draft", "Planar", "Scheme", "Sealed")) {
_unknownDeckCombo.addItem(choice);
}
unknownDeckPanel.add(new FLabel.Builder().text("Treat decks of unknown type as:").build());
unknownDeckPanel.add(_unknownDeckCombo);
knownDeckPanel.add(unknownDeckPanel, "span");
cbPanel.add(knownDeckPanel, "aligny top");
// add other data elements (gauntlets, quest data) // add other data elements (gauntlets, quest data)
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.PREFERENCE_FILE, "Preference files");
cbPanel.add(dataPanel, "aligny top");
_selectionPanel.add(cbPanel, "center");
// add move/copy checkbox // add move/copy checkbox
_moveCheckbox = new FCheckBox("move files"); _moveCheckbox = new FCheckBox("move files");
_moveCheckbox.setSelected(true); _moveCheckbox.setSelected(true);
_moveCheckbox.setEnabled(!forced); _moveCheckbox.setEnabled(!forced);
_moveCheckbox.addChangeListener(changeListener); _moveCheckbox.addChangeListener(_selectionChangeListener);
_selectionPanel.add(_moveCheckbox); _selectionPanel.add(_moveCheckbox);
// add operation summary textfield // add operation summary textfield
@@ -208,7 +236,7 @@ public class DialogMigrateProfile {
_operationLog.setFocusable(true); _operationLog.setFocusable(true);
JScrollPane scroller = new JScrollPane(_operationLog); JScrollPane scroller = new JScrollPane(_operationLog);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
_selectionPanel.add(scroller, "w 100%!, h 10%!"); _selectionPanel.add(scroller, "w 600:100%:100%, h 60:100%:100%");
// add progress bar // add progress bar
_progressBar = new JProgressBar(); _progressBar = new JProgressBar();
@@ -216,8 +244,22 @@ public class DialogMigrateProfile {
_progressBar.setString("Analyzing source directory..."); _progressBar.setString("Analyzing source directory...");
_progressBar.setStringPainted(true); _progressBar.setStringPainted(true);
_selectionPanel.add(_progressBar, "w 100%!"); _selectionPanel.add(_progressBar, "w 100%!");
// set checkbox labels
_updateUI();
} }
private void _addSelectionWidget(JPanel parent, boolean forced, OpType type, String name) {
FCheckBox cb = new FCheckBox();
cb.setName(name);
cb.setSelected(true);
cb.setEnabled(!forced);
cb.addChangeListener(_selectionChangeListener);
_selections.put(type, Pair.of(cb, new HashSet<Pair<File, File>>()));
parent.add(cb);
}
// must be called from GUI event loop thread
private void _updateUI() { private void _updateUI() {
// set operation summary // set operation summary
StringBuilder log = new StringBuilder(); StringBuilder log = new StringBuilder();
@@ -247,12 +289,16 @@ public class DialogMigrateProfile {
} }
private void _disableAll() { private void _disableAll() {
for (Pair<FCheckBox, ? extends Set<Pair<File, File>>> selection : _selections.values()) {
selection.getLeft().setEnabled(false);
}
_unknownDeckCombo.setEnabled(false);
_moveCheckbox.setEnabled(false); _moveCheckbox.setEnabled(false);
} }
@Override @Override
protected Void doInBackground() throws Exception { protected Void doInBackground() throws Exception {
// TODO: analysis // TODO: analyze source path tree and populate operation sets
// ensure we ignore data that is already in the destination directory // ensure we ignore data that is already in the destination directory
return null; return null;
} }
@@ -299,22 +345,26 @@ public class DialogMigrateProfile {
_operations.addAll(selection.getRight()); _operations.addAll(selection.getRight());
} }
} }
}
@Override // set progress bar bounds
protected Void doInBackground() throws Exception {
_operationLog.setText("");
// determine total number of operations and set progress bar bounds
_progressBar.setString(_move ? "Moving files" : "Copying files"); _progressBar.setString(_move ? "Moving files" : "Copying files");
_progressBar.setMinimum(0); _progressBar.setMinimum(0);
_progressBar.setMaximum(_operations.size()); _progressBar.setMaximum(_operations.size());
_progressBar.setIndeterminate(false); _progressBar.setIndeterminate(false);
}
@Override
protected Void doInBackground() throws Exception {
// working with textbox text is thread safe
_operationLog.setText("");
// assumes all destination directories have been created // assumes all destination directories have been created
int numOps = 0; int numOps = 0;
for (Pair<File, File> op : _operations) { for (Pair<File, File> op : _operations) {
_progressBar.setValue(++numOps); final int curOpNum = ++numOps;
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() { _progressBar.setValue(curOpNum); }
});
File srcFile = op.getLeft(); File srcFile = op.getLeft();
File destFile = op.getRight(); File destFile = op.getRight();
@@ -326,7 +376,7 @@ public class DialogMigrateProfile {
srcFile.delete(); srcFile.delete();
} }
// this operation is thread safe // working with textbox text is thread safe
_operationLog.append(String.format("%s %s -> %s\n", _operationLog.append(String.format("%s %s -> %s\n",
_move ? "Moved" : "Copied", _move ? "Moved" : "Copied",
srcFile.getAbsolutePath(), destFile.getAbsolutePath())); srcFile.getAbsolutePath(), destFile.getAbsolutePath()));

View File

@@ -66,10 +66,11 @@ public class ForgeProfileProperties {
// canonicalize // canonicalize
retDir = new File(retDir).getAbsolutePath(); retDir = new File(retDir).getAbsolutePath();
if (retDir.endsWith(File.pathSeparator)) { // ensure path ends in a slash
if (File.separatorChar == retDir.charAt(retDir.length() - 1)) {
return retDir; return retDir;
} }
return retDir + File.pathSeparator; return retDir + File.separatorChar;
} }
// returns a pair <userDir, cacheDir> // returns a pair <userDir, cacheDir>

View File

@@ -138,9 +138,9 @@ public enum FView {
for (String resDir : Lists.newArrayList("decks", "gauntlet", "pics", "pics_product", "preferences", "quest/data")) { for (String resDir : Lists.newArrayList("decks", "gauntlet", "pics", "pics_product", "preferences", "quest/data")) {
File f = new File("res", resDir); File f = new File("res", resDir);
if (f.exists() && !profileDirs.contains(f)) { if (f.exists() && !profileDirs.contains(f)) {
System.out.println("pre-profile data found: " + f.getAbsolutePath()); System.out.println("profile data found in obsolete location: " + f.getAbsolutePath());
hasData = true; hasData = true;
break; // cycle through all dirs instead of breaking immediately so each dir is printed to stdout
} }
} }