- add framework for sorting lists presented to the user for choice selection

- no existing behavior is changed -- callers have to make the explicit choice to sort
- allow left-right arrow keys to switch lists when choosing order
- sort sideboard
This commit is contained in:
myk
2013-02-17 01:36:07 +00:00
parent cada9a602a
commit a4be491c46
14 changed files with 414 additions and 450 deletions

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
@@ -85,7 +86,7 @@ public class Card extends GameEntity implements Comparable<Card> {
private int uniqueNumber;
private final Map<CardCharacteristicName, CardCharacteristics> characteristicsMap
= new EnumMap<CardCharacteristicName, CardCharacteristics>(CardCharacteristicName.class);
= new EnumMap<CardCharacteristicName, CardCharacteristics>(CardCharacteristicName.class);
private CardCharacteristicName curCharacteristics = CardCharacteristicName.Original;
private CardCharacteristicName preTFDCharacteristic = CardCharacteristicName.Original;
@@ -5642,6 +5643,32 @@ public class Card extends GameEntity implements Comparable<Card> {
return 0;
}
}
private static Comparator<Card> _nameComparator = new Comparator<Card>() {
@Override
public int compare(Card me, Card other) {
if (me == other) {
return 0;
}
if (null == other) {
return 1;
}
if (me.getName() == other.getName()) {
return 0;
}
if (null == me.getName()) {
return -1;
}
return me.getName().compareTo(other.getName());
}
};
/**
* For sorting lists of cards by name instead of by id
*/
public static final Comparator<Card> getNameComparator() {
return _nameComparator;
}
/** {@inheritDoc} */
@Override

View File

@@ -6,6 +6,7 @@ import java.util.Map;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import forge.Card;
import forge.card.ability.AbilityFactory;
@@ -50,7 +51,7 @@ public class ChooseGenericEffect extends SpellEffect {
}
SpellAbility chosenSA = null;
if (p.isHuman()) {
String choice = GuiChoose.one("Choose one", choices.values());
String choice = GuiChoose.one("Choose one", Lists.newArrayList(choices.values()));
chosenSA = AbilityFactory.getAbility(host.getSVar(choices.inverse().get(choice)), host);
} else { //Computer AI
chosenSA = AbilityFactory.getAbility(host.getSVar(sa.getParam("Choices").split(",")[0]), host);

View File

@@ -1,9 +1,9 @@
package forge.card.ability.effects;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import forge.Card;
import forge.CardUtil;
import forge.card.MagicColor;
@@ -26,7 +26,8 @@ public class ManaReflectedEffect extends SpellEffect {
AbilityManaPart ma = sa.getManaPart();
sa.setUndoable(sa.isAbility() && sa.isUndoable());
final Collection<String> colors = CardUtil.getReflectableManaColors(sa, sa, new HashSet<String>(), new ArrayList<Card>());
final List<String> colors = new ArrayList<String>(
CardUtil.getReflectableManaColors(sa, sa, new HashSet<String>(), new ArrayList<Card>()));
final List<Player> tgtPlayers = getTargetPlayers(sa);
for (final Player player : tgtPlayers) {
@@ -61,7 +62,7 @@ public class ManaReflectedEffect extends SpellEffect {
* a {@link forge.game.player.Player} object.
* @return a {@link java.lang.String} object.
*/
private static String generatedReflectedMana(final SpellAbility sa, final Collection<String> colors, final Player player) {
private static String generatedReflectedMana(final SpellAbility sa, final List<String> colors, final Player player) {
// Calculate generated mana here for stack description and resolving
final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("Amount"), sa) : 1;

View File

@@ -22,7 +22,6 @@ import java.util.HashMap;
import java.util.List;
import forge.Card;
import forge.CardLists;
import forge.CardUtil;
import forge.Singletons;
@@ -39,7 +38,7 @@ import forge.util.Expressions;
* TODO: Write javadoc for this type.
*
*/
public abstract class ReplacementEffect extends TriggerReplacementBase {
public abstract class ReplacementEffect extends TriggerReplacementBase implements Comparable<ReplacementEffect> {
private ReplacementLayer layer = ReplacementLayer.None;
@@ -439,4 +438,25 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
public void setLayer(ReplacementLayer layer0) {
this.layer = layer0;
}
/* (non-Javadoc)
* used only for ordering, just sort by card
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(ReplacementEffect other) {
if (null == other) {
return 1;
}
if (hostCard == other.hostCard) {
return 0;
}
if (null == hostCard) {
return -1;
}
if (null == other.hostCard) {
return 1;
}
return hostCard.getName().compareTo(other.hostCard.getName());
}
}

View File

@@ -26,7 +26,6 @@ import java.util.Set;
import org.apache.commons.lang.StringUtils;
import forge.Card;
import forge.GameEntity;
import forge.Singletons;
import forge.card.SpellManaCost;
@@ -48,7 +47,7 @@ import forge.game.player.Player;
* @author Forge
* @version $Id$
*/
public abstract class SpellAbility implements ISpellAbility {
public abstract class SpellAbility implements ISpellAbility, Comparable<SpellAbility> {
// choices for constructor isPermanent argument
private String description = "";
@@ -1782,4 +1781,25 @@ public abstract class SpellAbility implements ISpellAbility {
}
return true;
}
/* (non-Javadoc)
* used for ordering in lists -- we just want to group by card
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(SpellAbility other) {
if (null == other) {
return 1;
}
if (sourceCard == other.sourceCard) {
return 0;
}
if (null == sourceCard) {
return -1;
}
if (null == other.sourceCard) {
return 1;
}
return sourceCard.getName().compareTo(other.sourceCard.getName());
}
}

View File

@@ -179,14 +179,13 @@ public class GameActionPlay {
untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED);
if (untappedCreats.size() != 0) {
final ArrayList<Object> choices = new ArrayList<Object>();
final List<Card> choices = new ArrayList<Card>();
for (final Card c : untappedCreats) {
choices.add(c);
}
choices.add("DONE");
ArrayList<String> usableColors = new ArrayList<String>();
ManaCostBeingPaid newCost = new ManaCostBeingPaid(originalCost.toString());
Object tapForConvoke = null;
Card tapForConvoke = null;
if (sa.getActivatingPlayer().isHuman()) {
tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(),
choices);
@@ -195,7 +194,7 @@ public class GameActionPlay {
// Probably along with deciding how many creatures to
// tap
}
while ((tapForConvoke != null) && (tapForConvoke instanceof Card) && (untappedCreats.size() != 0)) {
while (tapForConvoke != null && untappedCreats.size() != 0) {
final Card workingCard = (Card) tapForConvoke;
usableColors = CardUtil.getConvokableColors(workingCard, newCost);

View File

@@ -34,7 +34,7 @@ import forge.item.CardPrinted;
* TODO: Write javadoc for this type.
*
*/
public class GameFormat {
public class GameFormat implements Comparable<GameFormat> {
private final String name;
// contains allowed sets, when empty allows all sets
@@ -158,4 +158,22 @@ public class GameFormat {
}
};
/* (non-Javadoc)
* just used for ordering -- comparing the name is sufficient
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(GameFormat other) {
if (null == other) {
return 1;
}
if (name == other.name) {
return 0;
}
if (null == name) {
return -1;
}
return name.compareTo(other.name);
}
}

View File

@@ -142,32 +142,28 @@ public class PlayerControllerHuman extends PlayerController {
CardPool sideboard = deck.get(DeckSection.Sideboard);
CardPool main = deck.get(DeckSection.Main);
// + deck.getSideboard().countAll()
int deckMinSize = Math.min(main.countAll(), gameType.getDecksFormat().getMainRange().getMinimumInteger());
//IntRange sbRange = gameType.getDecksFormat().getSideRange();
int sideboardSize = sideboard.countAll();
CardPool newSb = new CardPool();
List<CardPrinted> newMain = null;
while (newMain == null || newMain.size() < deckMinSize) {
if ( newMain != null ) {
if (newMain != null) {
String errMsg = String.format("Too few cards in your main deck (minimum %d), please make modifications to your deck again.", deckMinSize);
JOptionPane.showMessageDialog(null, errMsg, "Invalid deck", JOptionPane.ERROR_MESSAGE);
}
newMain = GuiChoose.order("Sideboard", "Main Deck", sideboardSize, sideboard.toFlatList(), main.toFlatList(), null, true);
newMain = GuiChoose.sideboard(sideboard.toFlatList(), main.toFlatList());
}
newSb.clear();
newSb.addAll(main);
newSb.addAll(sideboard);
for(CardPrinted c : newMain)
for(CardPrinted c : newMain) {
newSb.remove(c);
}
Deck res = (Deck) deck.copyTo(deck.getName());
Deck res = (Deck)deck.copyTo(deck.getName());
res.getMain().clear();
res.getMain().add(newMain);
CardPool resSb = res.getOrCreate(DeckSection.Sideboard);

View File

@@ -10,7 +10,11 @@ import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.JDialog;
@@ -21,7 +25,7 @@ import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import forge.Card;
import forge.card.spellability.SpellAbility;
@@ -42,41 +46,141 @@ import forge.item.CardPrinted;
// Single Arrows in between left box and right box for ordering
// Multi Arrows for moving everything in order
// Up/down arrows on the right of the right box for swapping
// Single ok button, disabled until left box is empty
// Single ok button, disabled until left box has specified number of items remaining
@SuppressWarnings("serial")
public class DualListBox<T> extends FPanel {
private FList sourceList;
public class DualListBox<T extends Comparable<? super T>> extends FPanel {
private final FList sourceList;
private final UnsortedListModel<T> sourceListModel;
private UnsortedListModel<T> sourceListModel;
private final FList destList;
private final UnsortedListModel<T> destListModel;
private FList destList;
private final FButton addButton;
private final FButton addAllButton;
private final FButton removeButton;
private final FButton removeAllButton;
private final FButton okButton;
private final FButton autoButton;
private UnsortedListModel<T> destListModel;
private final FLabel orderedLabel;
private final FLabel selectOrder;
private FButton addButton;
private FButton addAllButton;
private FButton removeButton;
private FButton removeAllButton;
private FButton okButton;
private FButton autoButton;
private FLabel orderedLabel;
private FLabel selectOrder;
private int remainingObjects = 0;
private final int targetRemainingSources;
private boolean sideboardingMode = false;
private boolean showCard = true;
public DualListBox(int remainingObjects, String label, List<T> sourceElements, List<T> destElements,
Card referenceCard) {
this.remainingObjects = remainingObjects;
initScreen();
orderedLabel.setText(label);
public DualListBox(int remainingSources, String label, List<T> sourceElements, List<T> destElements,
boolean startSorted, Comparator<T> sortComparator) {
targetRemainingSources = remainingSources;
sourceListModel = new UnsortedListModel<T>();
sourceList = new FList(sourceListModel);
destListModel = new UnsortedListModel<T>();
destList = new FList(destListModel);
setPreferredSize(new Dimension(650, 300));
setLayout(new GridLayout(0, 3));
setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME));
setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
final Runnable onAdd = new Runnable() {
@Override
public void run() {
@SuppressWarnings("unchecked")
List<T> selected = (List<T>) Arrays.asList(sourceList.getSelectedValues());
addDestinationElements(selected);
clearSourceSelected();
sourceList.validate();
_setButtonState();
}
};
final Runnable onRemove = new Runnable() {
@Override
public void run() {
@SuppressWarnings("unchecked")
List<T> selected = (List<T>) Arrays.asList(destList.getSelectedValues());
clearDestinationSelected();
addSourceElements(selected);
_setButtonState();
}
};
sourceList.addKeyListener(new KeyAdapter() {
@Override public void keyPressed(final KeyEvent e) {
_handleListKey(e, onAdd, destList);
}
});
sourceList.addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
if (MouseEvent.BUTTON1 == e.getButton() && 2 == e.getClickCount()) { onAdd.run(); }
}
});
destList.addKeyListener(new KeyAdapter() {
@Override public void keyPressed(final KeyEvent e) {
_handleListKey(e, onRemove, sourceList);
}
});
destList.addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
if (MouseEvent.BUTTON1 == e.getButton() && 2 == e.getClickCount()) { onRemove.run(); }
}
});
// Dual List control buttons
addButton = new FButton(">");
addButton.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) { onAdd.run(); } });
addAllButton = new FButton(">>");
addAllButton.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) { _addAll(); } });
removeButton = new FButton("<");
removeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { onRemove.run(); } });
removeAllButton = new FButton("<<");
removeAllButton.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) { _removeAll(); } });
// Dual List Complete Buttons
okButton = new FButton("OK");
okButton.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) { _finish(); } });
autoButton = new FButton("Auto");
autoButton.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) { _addAll(); _finish(); } });
FPanel leftPanel = new FPanel(new BorderLayout());
selectOrder = new FLabel.Builder().text("Select Order:").build();
leftPanel.setSize(300, 300);
leftPanel.add(selectOrder, BorderLayout.NORTH);
leftPanel.add(new FScrollPane(sourceList), BorderLayout.CENTER);
leftPanel.add(okButton, BorderLayout.SOUTH);
FPanel centerPanel = new FPanel(new GridLayout(6, 1));
centerPanel.setSize(50, this.getHeight());
centerPanel.add(new FPanel()); // empty panel to take up the first slot
centerPanel.add(addButton);
centerPanel.add(addAllButton);
centerPanel.add(removeButton);
centerPanel.add(removeAllButton);
orderedLabel = new FLabel.Builder().text(label).build();
FPanel rightPanel = new FPanel(new BorderLayout());
rightPanel.setSize(300, 300);
rightPanel.add(orderedLabel, BorderLayout.NORTH);
rightPanel.add(new FScrollPane(destList), BorderLayout.CENTER);
rightPanel.add(autoButton, BorderLayout.SOUTH);
add(leftPanel);
add(centerPanel);
add(rightPanel);
_addListListeners(sourceList);
_addListListeners(destList);
if (destElements != null && !destElements.isEmpty()) {
if (startSorted) {
// it would be nice if we could sort in place, but it might mess up our callers
destElements = Lists.newArrayList(destElements);
Collections.sort(destElements, sortComparator);
}
addDestinationElements(destElements);
SwingUtilities.invokeLater(new Runnable() {
@@ -86,7 +190,12 @@ public class DualListBox<T> extends FPanel {
}
});
}
if (sourceElements != null && !sourceElements.isEmpty()) {
if (startSorted) {
sourceElements = Lists.newArrayList(sourceElements);
Collections.sort(sourceElements, sortComparator);
}
addSourceElements(sourceElements);
SwingUtilities.invokeLater(new Runnable() {
@@ -96,13 +205,12 @@ public class DualListBox<T> extends FPanel {
}
});
}
this.setButtonState();
_setButtonState();
}
public DualListBox(int remainingObjects, String label, List<T> sourceElements, List<T> destElements, Card referenceCard, boolean isSideboardDialog) {
this(remainingObjects, label, sourceElements, destElements, referenceCard);
this.sideboardingMode = isSideboardDialog;
public void setSideboardMode( boolean isSideboardMode) {
sideboardingMode = isSideboardMode;
if (sideboardingMode) {
addAllButton.setVisible(false);
removeAllButton.setVisible(false);
@@ -112,6 +220,30 @@ public class DualListBox<T> extends FPanel {
}
}
private void _handleListKey (KeyEvent e, Runnable onSpace, FList arrowFocusTarget) {
switch (e.getKeyCode()) {
case KeyEvent.VK_SPACE:
onSpace.run();
break;
case KeyEvent.VK_LEFT:
case KeyEvent.VK_RIGHT:
arrowFocusTarget.requestFocusInWindow();
break;
case KeyEvent.VK_ENTER:
if (okButton.isEnabled()) {
okButton.doClick();
} else if (autoButton.isEnabled()) {
autoButton.doClick();
}
break;
default:
break;
}
}
public void clearSourceListModel() {
sourceListModel.clear();
}
@@ -197,7 +329,7 @@ public class DualListBox<T> extends FPanel {
}
}
private void addCardViewListener(final FList list) {
private void _addListListeners(final FList list) {
list.getModel().addListDataListener(new ListDataListener() {
int callCount = 0;
@Override
@@ -276,157 +408,19 @@ public class DualListBox<T> extends FPanel {
});
}
private void initScreen() {
setPreferredSize(new Dimension(650, 300));
setLayout(new GridLayout(0, 3));
setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME));
setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
sourceListModel = new UnsortedListModel<T>();
sourceList = new FList(sourceListModel);
destListModel = new UnsortedListModel<T>();
destList = new FList(destListModel);
final Runnable onAdd = new Runnable() {
@Override
public void run() {
@SuppressWarnings("unchecked")
List<T> selected = (List<T>) Arrays.asList(sourceList.getSelectedValues());
addDestinationElements(selected);
clearSourceSelected();
sourceList.validate();
setButtonState();
}
};
final Runnable onRemove = new Runnable() {
@Override
public void run() {
@SuppressWarnings("unchecked")
List<T> selected = (List<T>) Arrays.asList(destList.getSelectedValues());
clearDestinationSelected();
addSourceElements(selected);
setButtonState();
}
};
ActionListener addListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
onAdd.run();
}
};
ActionListener removeListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
onRemove.run();
}
};
final Function<KeyEvent, Void> onEnter = new Function<KeyEvent, Void>() {
@Override
public Void apply (KeyEvent e) {
if (e.getKeyCode() == 10) {
if (e.isControlDown() || e.isMetaDown()) {
autoButton.doClick();
} else {
okButton.doClick();
}
}
return null;
}
};
sourceList.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent e) {
if (e.getKeyChar() == ' ') { onAdd.run(); }
else { onEnter.apply(e); }
}
});
destList.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent e) {
if (e.getKeyChar() == ' ') { onRemove.run(); }
else { onEnter.apply(e); }
}
});
// Dual List control buttons
addButton = new FButton(">");
addButton.addActionListener(addListener);
addAllButton = new FButton(">>");
addAllButton.addActionListener(new AddAllListener());
removeButton = new FButton("<");
removeButton.addActionListener(removeListener);
removeAllButton = new FButton("<<");
removeAllButton.addActionListener(new RemoveAllListener());
// Dual List Complete Buttons
okButton = new FButton("OK");
okButton.addActionListener(new OkListener());
autoButton = new FButton("Auto");
autoButton.addActionListener(new AutoListener());
FPanel leftPanel = new FPanel(new BorderLayout());
selectOrder = new FLabel.Builder().build();
selectOrder.setText("Select Order:");
leftPanel.setSize(300, 300);
leftPanel.add(selectOrder, BorderLayout.NORTH);
leftPanel.add(new FScrollPane(sourceList), BorderLayout.CENTER);
leftPanel.add(okButton, BorderLayout.SOUTH);
FPanel centerPanel = new FPanel(new GridLayout(5, 1));
centerPanel.setSize(50, this.getHeight());
centerPanel.add(addButton);
centerPanel.add(addAllButton);
centerPanel.add(removeButton);
centerPanel.add(removeAllButton);
orderedLabel = new FLabel.Builder().build();
orderedLabel.setText("Selected Elements:");
FPanel rightPanel = new FPanel(new BorderLayout());
rightPanel.setSize(300, 300);
rightPanel.add(orderedLabel, BorderLayout.NORTH);
rightPanel.add(new FScrollPane(destList), BorderLayout.CENTER);
rightPanel.add(autoButton, BorderLayout.SOUTH);
add(leftPanel);
add(centerPanel);
add(rightPanel);
addCardViewListener(sourceList);
addCardViewListener(destList);
}
private void addAll() {
private void _addAll() {
addDestinationElements(sourceListModel);
clearSourceListModel();
setButtonState();
_setButtonState();
}
private void _removeAll() {
addSourceElements(destListModel);
clearDestinationListModel();
_setButtonState();
}
private class AddAllListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
addAll();
setButtonState();
}
}
private class RemoveAllListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
addSourceElements(destListModel);
clearDestinationListModel();
setButtonState();
}
}
public void setButtonState() {
private void _setButtonState() {
if (sideboardingMode) {
removeAllButton.setVisible(false);
addAllButton.setVisible(false);
@@ -434,15 +428,11 @@ public class DualListBox<T> extends FPanel {
orderedLabel.setText(String.format("Main Deck (%d):", destListModel.getSize()));
}
if (remainingObjects != -1) {
okButton.setEnabled(sourceListModel.getSize() == remainingObjects);
if (targetRemainingSources != -1) {
okButton.setEnabled(sourceListModel.getSize() == targetRemainingSources);
}
if (remainingObjects < 1) {
if (!sideboardingMode) {
autoButton.setEnabled(sourceListModel.getSize() != remainingObjects);
} else {
autoButton.setEnabled(false);
}
if (targetRemainingSources < 1 && !sideboardingMode) {
autoButton.setEnabled(sourceListModel.getSize() != targetRemainingSources);
} else {
autoButton.setEnabled(false);
}
@@ -453,27 +443,11 @@ public class DualListBox<T> extends FPanel {
addAllButton.setEnabled(sourceListModel.getSize() != 0);
}
private void finishOrdering() {
System.out.println("Attempting to finish.");
private void _finish() {
this.setVisible(false);
Container grandpa = this.getParent().getParent();
JDialog dialog = (JDialog) grandpa.getParent();
dialog.dispose();
}
private class OkListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
finishOrdering();
}
}
private class AutoListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
addAll();
finishOrdering();
}
}
}

View File

@@ -1,8 +1,8 @@
package forge.gui;
import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import javax.swing.JDialog;
@@ -14,6 +14,7 @@ import javax.swing.event.ListSelectionListener;
import forge.Card;
import forge.gui.match.CMatchUI;
import forge.item.CardPrinted;
import forge.item.InventoryItem;
/**
@@ -21,116 +22,22 @@ import forge.item.InventoryItem;
*
*/
public class GuiChoose {
/**
* Convenience for getChoices(message, 0, 1, choices).
*
* @param <T>
* is automatically inferred.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by
* getChoices.
* @see #getChoices(String, int, int, Object...)
*/
public static <T> T oneOrNone(final String message, final T[] choices) {
if ((choices == null) || (choices.length == 0)) {
return null;
}
final List<T> choice = GuiChoose.getChoices(message, 0, 1, choices);
return choice.isEmpty() ? null : choice.get(0);
} // getChoiceOptional(String,T...)
public static <T> T oneOrNone(final String message, final Collection<T> choices) {
public static <T extends Comparable<? super T>> T oneOrNone(String message, List<T> choices, boolean sort, Comparator<T> sortComparator) {
if ((choices == null) || (choices.size() == 0)) {
return null;
}
final List<T> choice = GuiChoose.getChoices(message, 0, 1, choices);
final List<T> choice = _getChoices(message, 0, 1, choices, sort, sortComparator);
return choice.isEmpty() ? null : choice.get(0);
} // getChoiceOptional(String,T...)
// returned Object will never be null
/**
* <p>
* getChoice.
* </p>
*
* @param <T>
* a T object.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return a T object.
*/
public static <T> T one(final String message, final T[] choices) {
final List<T> choice = GuiChoose.getChoices(message, 1, 1, choices);
assert choice.size() == 1;
return choice.get(0);
} // getChoice()
// Nothing to choose here. Code uses this to just show a card.
public static Card one(final String message, final Card singleChoice) {
List<Card> choices = new ArrayList<Card>();
choices.add(singleChoice);
return one(message, choices);
}
public static <T extends Comparable<? super T>> T oneOrNone(String message, List<T> choices) {
return oneOrNone(message, choices, false, null);
}
public static <T extends Comparable<? super T>> T oneOrNone(String message, T[] choices) {
if ((choices == null)) { return null; }
return oneOrNone(message, Arrays.asList(choices));
}
public static <T> T one(final String message, final Collection<T> choices) {
if ((choices == null) || (choices.size() == 0)) {
return null;
}
final List<T> choice = GuiChoose.getChoices(message, 1, 1, choices);
assert choice.size() == 1;
return choice.get(0);
}
// returned Object will never be null
/**
* <p>
* getChoicesOptional.
* </p>
*
* @param <T>
* a T object.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return a {@link java.util.List} object.
*/
public static <T> List<T> noneOrMany(final String message, final T[] choices) {
return GuiChoose.getChoices(message, 0, choices.length, choices);
} // getChoice()
public static <T> List<T> noneOrMany(final String message, final Collection<T> choices) {
return GuiChoose.getChoices(message, 0, choices.size(), choices);
}
// returned Object will never be null
/**
* <p>
* getChoices.
* </p>
*
* @param <T>
* a T object.
* @param message
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return a {@link java.util.List} object.
*/
public static <T> List<T> oneOrMany(final String message, final T[] choices) {
return GuiChoose.getChoices(message, 1, choices.length, choices);
} // getChoice()
//returned Object will never be null
/**
* <p>
* Presents a list of choices where the player must choose exactly *amount* options.
* @param message
* the message to display to the player.
@@ -140,58 +47,80 @@ public class GuiChoose {
* the amount of options that must be chosen.
* @return
*/
public static <T> List<T> amount(final String message, final T[] choices, final int amount) {
if ((choices == null) || (choices.length == 0) || choices.length < amount) {
public static <T extends Comparable<? super T>> List<T> amount(String message, List<T> choices, int amt, boolean sort, Comparator<T> sortComparator) {
if (null == choices || 0 == choices.size() || 0 == amt) {
return null;
}
return GuiChoose.getChoices(message, amount, amount, choices);
final List<T> choice = _getChoices(message, amt, amt, choices, sort, sortComparator);
assert choice.size() == amt;
return choice;
}
public static <T extends Comparable<? super T>> List<T> amount(String message, List<T> choices, int amt) {
return amount(message, choices, amt, false, null);
}
public static <T extends Comparable<? super T>> List<T> amount(String message, T[] choices, int amt) {
if ((choices == null)) { return null; }
return amount(message, Arrays.asList(choices), amt);
}
public static <T> List<T> amount(final String message, final Collection<T> choices, final int amount) {
if ((choices == null) || (choices.size() == 0) || choices.size() < amount) {
public static <T extends Comparable<? super T>> T one(String message, List<T> choices, boolean sort, Comparator<T> sortComparator) {
List<T> choice = amount(message, choices, 1, sort, sortComparator);
if (null == choice || choice.isEmpty()) {
return null;
}
return choice.get(0);
}
public static <T extends Comparable<? super T>> T one(String message, List<T> choices) {
return one(message, choices, false, null);
}
public static <T extends Comparable<? super T>> T one(String message, T[] choices) {
if ((choices == null)) { return null; }
return one(message, Arrays.asList(choices));
}
// Nothing to choose here. Code uses this to just show a card.
public static Card one(String message, Card singleChoice) {
List<Card> choices = Arrays.asList(singleChoice);
return one(message, choices);
}
return GuiChoose.getChoices(message, amount, amount, choices);
public static <T extends Comparable<? super T>> List<T> noneOrMany(String message, List<T> choices, boolean sort, Comparator<T> sortComparator) {
if ((choices == null) || (choices.size() == 0)) {
return null;
}
final List<T> choice = _getChoices(message, 0, choices.size(), choices, sort, sortComparator);
return choice.isEmpty() ? null : choice;
}
public static <T extends Comparable<? super T>> List<T> noneOrMany(String message, List<T> choices) {
return noneOrMany(message, choices, false, null);
}
public static <T extends Comparable<? super T>> List<T> oneOrMany(String message, List<T> choices, boolean sort, Comparator<T> sortComparator) {
if ((choices == null) || (choices.size() == 0)) {
return null;
}
final List<T> choice = _getChoices(message, 1, choices.size(), choices, sort, sortComparator);
return choice.isEmpty() ? null : choice;
}
public static <T extends Comparable<? super T>> List<T> oneOrMany(String message, List<T> choices) {
return oneOrMany(message, choices, false, null);
}
public static <T extends Comparable<? super T>> List<T> oneOrMany(String message, T[] choices) {
if ((choices == null)) { return null; }
return oneOrMany(message, Arrays.asList(choices));
}
// returned Object will never be null
/**
* <p>
* getChoices.
* </p>
*
* @param <T>
* a T object.
* @param message
* a {@link java.lang.String} object.
* @param min
* a int.
* @param max
* a int.
* @param choices
* a T object.
* @return a {@link java.util.List} object.
*/
private static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices) {
final ListChooser<T> c = new ListChooser<T>(message, null, min, max, choices);
return getChoices(c);
private static <T extends Comparable<? super T>> List<T> _getChoices(String message, int min, int max, List<T> choices,
boolean sort, Comparator<T> sortComparator) {
return _getChoices(new ListChooser<T>(message, min, max, choices, sort, sortComparator));
}
private static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices) {
final ListChooser<T> c = new ListChooser<T>(message, min, max, choices);
return getChoices(c);
}
private static <T> List<T> getChoices(final ListChooser<T> c) {
private static <T extends Comparable<? super T>> List<T> _getChoices(ListChooser<T> c) {
final JList list = c.getJList();
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(final ListSelectionEvent ev) {
if (list.getSelectedValue() instanceof Card) {
CMatchUI.SINGLETON_INSTANCE.setCard((Card) list.getSelectedValue());
GuiUtils.clearPanelSelections();
GuiUtils.setPanelSelection((Card) list.getSelectedValue());
}
@@ -200,21 +129,31 @@ public class GuiChoose {
}
}
});
c.show();
GuiUtils.clearPanelSelections();
return c.getSelectedValues();
} // getChoice()
public static <T> List<T> order(final String title, final String top, int remainingObjects,
final List<T> sourceChoices, List<T> destChoices, Card referenceCard) {
return order(title, top, remainingObjects, sourceChoices, destChoices, referenceCard, false);
}
public static <T> List<T> order(final String title, final String top, int remainingObjects,
final List<T> sourceChoices, List<T> destChoices, Card referenceCard, boolean sideboardingMode) {
public static <T extends Comparable<? super T>> List<T> order(String title, String top, int remainingObjects,
List<T> sourceChoices, List<T> destChoices, Card referenceCard, boolean sort, Comparator<T> sortComparator) {
return _order(title, top, remainingObjects, sourceChoices, destChoices, referenceCard, sort, sortComparator, false);
}
public static <T extends Comparable<? super T>> List<T> order(String title, String top, int remainingObjects,
List<T> sourceChoices, List<T> destChoices, Card referenceCard) {
return order(title, top, remainingObjects, sourceChoices, destChoices, referenceCard, false, null);
}
public static List<CardPrinted> sideboard(List<CardPrinted> sideboard, List<CardPrinted> deck) {
return _order("Sideboard", "Main Deck", sideboard.size(), sideboard, deck, null, true, null, true);
}
private static <T extends Comparable<? super T>> List<T> _order(
String title, String top, int remainingObjects, List<T> sourceChoices, List<T> destChoices,
Card referenceCard, boolean startSorted, Comparator<T> sortComparator, boolean sideboardingMode) {
// An input box for handling the order of choices.
final JFrame frame = new JFrame();
DualListBox<T> dual = new DualListBox<T>(remainingObjects, top, sourceChoices, destChoices, referenceCard, sideboardingMode);
DualListBox<T> dual = new DualListBox<T>(remainingObjects, top, sourceChoices, destChoices, startSorted, sortComparator);
dual.setSideboardMode(sideboardingMode);
frame.setLayout(new BorderLayout());
frame.setSize(dual.getPreferredSize());
@@ -229,10 +168,12 @@ public class GuiChoose {
dialog.setLocationRelativeTo(null);
dialog.pack();
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
if (referenceCard != null) {
CMatchUI.SINGLETON_INSTANCE.setCard(referenceCard);
// MARKED FOR UPDATE
}
dialog.setVisible(true);
List<T> objects = dual.getOrderedList();
@@ -241,6 +182,4 @@ public class GuiChoose {
GuiUtils.clearPanelSelections();
return objects;
}
}

View File

@@ -25,8 +25,8 @@ import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.AbstractAction;
@@ -65,7 +65,7 @@ import javax.swing.event.ListSelectionListener;
* @author Forge
* @version $Id$
*/
public class ListChooser<T> {
public class ListChooser<T extends Comparable<? super T>> {
// Data and number of choices for the list
private List<T> list;
@@ -83,68 +83,15 @@ public class ListChooser<T> {
private JOptionPane optionPane;
private Action ok, cancel;
/**
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param minChoices
* a int.
* @param maxChoices
* a int.
* @param list
* a T object.
*/
public ListChooser(final String title, final String message, final int minChoices, final int maxChoices,
final T[] list) {
this(title, message, minChoices, maxChoices, Arrays.asList(list));
}
/**
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param minChoices
* a int.
* @param maxChoices
* a int.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(final String title, final int minChoices, final int maxChoices, final Collection<T> list) {
this(title, null, minChoices, maxChoices, list);
}
/**
* <p>
* Constructor for ListChooser.
* </p>
*
* @param title
* a {@link java.lang.String} object.
* @param message
* a {@link java.lang.String} object.
* @param minChoices
* a int.
* @param maxChoices
* a int.
* @param list
* a {@link java.util.List} object.
*/
public ListChooser(final String title, final String message, final int minChoices, final int maxChoices,
final Collection<T> list) {
public ListChooser(final String title, final int minChoices, final int maxChoices,
final List<T> list, boolean startSorted, Comparator<T> sortComparator) {
this.title = title;
this.minChoices = minChoices;
this.maxChoices = maxChoices;
this.list = new ArrayList<T>(list);
if (startSorted) {
Collections.sort(this.list, sortComparator);
}
this.jList = new JList(new ChooserListModel());
this.ok = new CloseAction(JOptionPane.OK_OPTION, "OK");
this.ok.setEnabled(minChoices == 0);
@@ -160,7 +107,7 @@ public class ListChooser<T> {
this.jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
this.optionPane = new JOptionPane(new Object[] { message, new JScrollPane(this.jList) }, JOptionPane.QUESTION_MESSAGE,
this.optionPane = new JOptionPane(new JScrollPane(this.jList), JOptionPane.QUESTION_MESSAGE,
JOptionPane.DEFAULT_OPTION, null, options, options[0]);
this.jList.getSelectionModel().addListSelectionListener(new SelListener());
this.jList.addMouseListener(new DblListener());
@@ -178,7 +125,7 @@ public class ListChooser<T> {
/** @return boolean */
public synchronized boolean show() {
return this.show(0);
return show(list.get(0));
}
/**
@@ -187,7 +134,7 @@ public class ListChooser<T> {
* @param index0 index to select when shown
* @return a boolean.
*/
public synchronized boolean show(int index0) {
public synchronized boolean show(T item) {
if (this.called) {
throw new IllegalStateException("Already shown");
}
@@ -198,7 +145,11 @@ public class ListChooser<T> {
this.dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
}
this.jList.setSelectedIndex(index0);
if (list.contains(item)) {
jList.setSelectedValue(item, true);
} else {
jList.setSelectedIndex(0);
}
this.dialog.addWindowFocusListener(new WindowFocusListener() {
@Override

View File

@@ -545,19 +545,18 @@ public class QuestWinLose extends ControlWinLose {
if (qData.getFormat() == null) {
final List<GameFormat> formats = new ArrayList<GameFormat>();
String prefferedFormat = Singletons.getModel().getQuestPreferences().getPreference(QPref.BOOSTER_FORMAT);
String preferredFormat = Singletons.getModel().getQuestPreferences().getPreference(QPref.BOOSTER_FORMAT);
int index = 0, i = 0;
GameFormat pref = null;
for (GameFormat f : Singletons.getModel().getFormats()) {
formats.add(f);
if (f.toString().equals(prefferedFormat)) {
index = i;
if (f.toString().equals(preferredFormat)) {
pref = f;
}
i++;
}
final ListChooser<GameFormat> ch = new ListChooser<GameFormat>("Choose bonus booster format", 1, 1, formats);
ch.show(index);
final ListChooser<GameFormat> ch = new ListChooser<GameFormat>("Choose bonus booster format", 1, 1, formats, true, null);
ch.show(pref);
final GameFormat selected = ch.getSelectedValue();
Singletons.getModel().getQuestPreferences().setPreference(QPref.BOOSTER_FORMAT, selected.toString());

View File

@@ -30,7 +30,7 @@ import forge.util.StorageReaderFile;
* This function holds the "world info" for the current quest.
*
*/
public class QuestWorld {
public class QuestWorld implements Comparable<QuestWorld>{
private final String name;
private final String dir;
private final GameFormatQuest format;
@@ -161,4 +161,21 @@ public class QuestWorld {
}
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(QuestWorld other) {
if (null == other) {
return 1;
}
if (name == other.name) {
return 0;
}
if (null == name) {
return -1;
}
return name.compareTo(other.name);
}
}

View File

@@ -1,5 +1,7 @@
package forge.gui;
import java.util.Arrays;
import org.testng.annotations.Test;
/**
@@ -13,7 +15,7 @@ public class ListChooserTest {
*/
@Test(groups = { "UnitTest", "fast" }, timeOut = 1000, enabled = false)
public void listChooserTest1() {
final ListChooser<String> c = new ListChooser<String>("test", "choose a or b", 0, 2, new String[] {"a", "b"});
final ListChooser<String> c = new ListChooser<String>("choose a or b", 0, 2, Arrays.asList("a", "b"), false, null);
System.out.println(c.show());
for (final String s : c.getSelectedValues()) {
System.out.println(s);