- 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.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@@ -5643,6 +5644,32 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
} }
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} */ /** {@inheritDoc} */
@Override @Override
public final boolean equals(final Object o) { public final boolean equals(final Object o) {

View File

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

View File

@@ -1,9 +1,9 @@
package forge.card.ability.effects; package forge.card.ability.effects;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import forge.Card; import forge.Card;
import forge.CardUtil; import forge.CardUtil;
import forge.card.MagicColor; import forge.card.MagicColor;
@@ -26,7 +26,8 @@ public class ManaReflectedEffect extends SpellEffect {
AbilityManaPart ma = sa.getManaPart(); AbilityManaPart ma = sa.getManaPart();
sa.setUndoable(sa.isAbility() && sa.isUndoable()); 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); final List<Player> tgtPlayers = getTargetPlayers(sa);
for (final Player player : tgtPlayers) { for (final Player player : tgtPlayers) {
@@ -61,7 +62,7 @@ public class ManaReflectedEffect extends SpellEffect {
* a {@link forge.game.player.Player} object. * a {@link forge.game.player.Player} object.
* @return a {@link java.lang.String} 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 // Calculate generated mana here for stack description and resolving
final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("Amount"), sa) : 1; 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 java.util.List;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardUtil; import forge.CardUtil;
import forge.Singletons; import forge.Singletons;
@@ -39,7 +38,7 @@ import forge.util.Expressions;
* TODO: Write javadoc for this type. * 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; private ReplacementLayer layer = ReplacementLayer.None;
@@ -439,4 +438,25 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
public void setLayer(ReplacementLayer layer0) { public void setLayer(ReplacementLayer layer0) {
this.layer = 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 org.apache.commons.lang.StringUtils;
import forge.Card; import forge.Card;
import forge.GameEntity; import forge.GameEntity;
import forge.Singletons; import forge.Singletons;
import forge.card.SpellManaCost; import forge.card.SpellManaCost;
@@ -48,7 +47,7 @@ import forge.game.player.Player;
* @author Forge * @author Forge
* @version $Id$ * @version $Id$
*/ */
public abstract class SpellAbility implements ISpellAbility { public abstract class SpellAbility implements ISpellAbility, Comparable<SpellAbility> {
// choices for constructor isPermanent argument // choices for constructor isPermanent argument
private String description = ""; private String description = "";
@@ -1782,4 +1781,25 @@ public abstract class SpellAbility implements ISpellAbility {
} }
return true; 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); untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED);
if (untappedCreats.size() != 0) { if (untappedCreats.size() != 0) {
final ArrayList<Object> choices = new ArrayList<Object>(); final List<Card> choices = new ArrayList<Card>();
for (final Card c : untappedCreats) { for (final Card c : untappedCreats) {
choices.add(c); choices.add(c);
} }
choices.add("DONE");
ArrayList<String> usableColors = new ArrayList<String>(); ArrayList<String> usableColors = new ArrayList<String>();
ManaCostBeingPaid newCost = new ManaCostBeingPaid(originalCost.toString()); ManaCostBeingPaid newCost = new ManaCostBeingPaid(originalCost.toString());
Object tapForConvoke = null; Card tapForConvoke = null;
if (sa.getActivatingPlayer().isHuman()) { if (sa.getActivatingPlayer().isHuman()) {
tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(), tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(),
choices); choices);
@@ -195,7 +194,7 @@ public class GameActionPlay {
// Probably along with deciding how many creatures to // Probably along with deciding how many creatures to
// tap // tap
} }
while ((tapForConvoke != null) && (tapForConvoke instanceof Card) && (untappedCreats.size() != 0)) { while (tapForConvoke != null && untappedCreats.size() != 0) {
final Card workingCard = (Card) tapForConvoke; final Card workingCard = (Card) tapForConvoke;
usableColors = CardUtil.getConvokableColors(workingCard, newCost); usableColors = CardUtil.getConvokableColors(workingCard, newCost);

View File

@@ -34,7 +34,7 @@ import forge.item.CardPrinted;
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
public class GameFormat { public class GameFormat implements Comparable<GameFormat> {
private final String name; private final String name;
// contains allowed sets, when empty allows all sets // 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 sideboard = deck.get(DeckSection.Sideboard);
CardPool main = deck.get(DeckSection.Main); CardPool main = deck.get(DeckSection.Main);
// + deck.getSideboard().countAll()
int deckMinSize = Math.min(main.countAll(), gameType.getDecksFormat().getMainRange().getMinimumInteger()); int deckMinSize = Math.min(main.countAll(), gameType.getDecksFormat().getMainRange().getMinimumInteger());
//IntRange sbRange = gameType.getDecksFormat().getSideRange();
int sideboardSize = sideboard.countAll();
CardPool newSb = new CardPool(); CardPool newSb = new CardPool();
List<CardPrinted> newMain = null; List<CardPrinted> newMain = null;
while (newMain == null || newMain.size() < deckMinSize) { 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); 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); 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.clear();
newSb.addAll(main); newSb.addAll(main);
newSb.addAll(sideboard); newSb.addAll(sideboard);
for(CardPrinted c : newMain) for(CardPrinted c : newMain) {
newSb.remove(c); newSb.remove(c);
}
Deck res = (Deck) deck.copyTo(deck.getName()); Deck res = (Deck)deck.copyTo(deck.getName());
res.getMain().clear(); res.getMain().clear();
res.getMain().add(newMain); res.getMain().add(newMain);
CardPool resSb = res.getOrCreate(DeckSection.Sideboard); 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.FocusEvent;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import javax.swing.JDialog; import javax.swing.JDialog;
@@ -21,7 +25,7 @@ import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import com.google.common.base.Function; import com.google.common.collect.Lists;
import forge.Card; import forge.Card;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
@@ -42,41 +46,141 @@ import forge.item.CardPrinted;
// Single Arrows in between left box and right box for ordering // Single Arrows in between left box and right box for ordering
// Multi Arrows for moving everything in order // Multi Arrows for moving everything in order
// Up/down arrows on the right of the right box for swapping // 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") @SuppressWarnings("serial")
public class DualListBox<T> extends FPanel { public class DualListBox<T extends Comparable<? super T>> extends FPanel {
private FList sourceList; 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 final int targetRemainingSources;
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 boolean sideboardingMode = false; private boolean sideboardingMode = false;
private boolean showCard = true; private boolean showCard = true;
public DualListBox(int remainingObjects, String label, List<T> sourceElements, List<T> destElements, public DualListBox(int remainingSources, String label, List<T> sourceElements, List<T> destElements,
Card referenceCard) { boolean startSorted, Comparator<T> sortComparator) {
this.remainingObjects = remainingObjects; targetRemainingSources = remainingSources;
initScreen(); sourceListModel = new UnsortedListModel<T>();
orderedLabel.setText(label); 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 (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); addDestinationElements(destElements);
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@@ -86,7 +190,12 @@ public class DualListBox<T> extends FPanel {
} }
}); });
} }
if (sourceElements != null && !sourceElements.isEmpty()) { if (sourceElements != null && !sourceElements.isEmpty()) {
if (startSorted) {
sourceElements = Lists.newArrayList(sourceElements);
Collections.sort(sourceElements, sortComparator);
}
addSourceElements(sourceElements); addSourceElements(sourceElements);
SwingUtilities.invokeLater(new Runnable() { 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) { public void setSideboardMode( boolean isSideboardMode) {
this(remainingObjects, label, sourceElements, destElements, referenceCard); sideboardingMode = isSideboardMode;
this.sideboardingMode = isSideboardDialog;
if (sideboardingMode) { if (sideboardingMode) {
addAllButton.setVisible(false); addAllButton.setVisible(false);
removeAllButton.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() { public void clearSourceListModel() {
sourceListModel.clear(); 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() { list.getModel().addListDataListener(new ListDataListener() {
int callCount = 0; int callCount = 0;
@Override @Override
@@ -276,157 +408,19 @@ public class DualListBox<T> extends FPanel {
}); });
} }
private void initScreen() { private void _addAll() {
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() {
addDestinationElements(sourceListModel); addDestinationElements(sourceListModel);
clearSourceListModel(); clearSourceListModel();
setButtonState(); _setButtonState();
} }
private class AddAllListener implements ActionListener { private void _removeAll() {
@Override
public void actionPerformed(ActionEvent e) {
addAll();
setButtonState();
}
}
private class RemoveAllListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
addSourceElements(destListModel); addSourceElements(destListModel);
clearDestinationListModel(); clearDestinationListModel();
setButtonState(); _setButtonState();
}
} }
public void setButtonState() { private void _setButtonState() {
if (sideboardingMode) { if (sideboardingMode) {
removeAllButton.setVisible(false); removeAllButton.setVisible(false);
addAllButton.setVisible(false); addAllButton.setVisible(false);
@@ -434,15 +428,11 @@ public class DualListBox<T> extends FPanel {
orderedLabel.setText(String.format("Main Deck (%d):", destListModel.getSize())); orderedLabel.setText(String.format("Main Deck (%d):", destListModel.getSize()));
} }
if (remainingObjects != -1) { if (targetRemainingSources != -1) {
okButton.setEnabled(sourceListModel.getSize() == remainingObjects); 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 { } else {
autoButton.setEnabled(false); autoButton.setEnabled(false);
} }
@@ -453,27 +443,11 @@ public class DualListBox<T> extends FPanel {
addAllButton.setEnabled(sourceListModel.getSize() != 0); addAllButton.setEnabled(sourceListModel.getSize() != 0);
} }
private void finishOrdering() { private void _finish() {
System.out.println("Attempting to finish.");
this.setVisible(false); this.setVisible(false);
Container grandpa = this.getParent().getParent(); Container grandpa = this.getParent().getParent();
JDialog dialog = (JDialog) grandpa.getParent(); JDialog dialog = (JDialog) grandpa.getParent();
dialog.dispose(); 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; package forge.gui;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.util.ArrayList; import java.util.Arrays;
import java.util.Collection; import java.util.Comparator;
import java.util.List; import java.util.List;
import javax.swing.JDialog; import javax.swing.JDialog;
@@ -14,6 +14,7 @@ import javax.swing.event.ListSelectionListener;
import forge.Card; import forge.Card;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
import forge.item.CardPrinted;
import forge.item.InventoryItem; import forge.item.InventoryItem;
/** /**
@@ -21,116 +22,22 @@ import forge.item.InventoryItem;
* *
*/ */
public class GuiChoose { public class GuiChoose {
public static <T extends Comparable<? super T>> T oneOrNone(String message, List<T> choices, boolean sort, Comparator<T> sortComparator) {
/**
* 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) {
if ((choices == null) || (choices.size() == 0)) { if ((choices == null) || (choices.size() == 0)) {
return null; 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); return choice.isEmpty() ? null : choice.get(0);
} // getChoiceOptional(String,T...) }
public static <T extends Comparable<? super T>> T oneOrNone(String message, List<T> choices) {
// returned Object will never be null return oneOrNone(message, choices, false, null);
/** }
* <p> public static <T extends Comparable<? super T>> T oneOrNone(String message, T[] choices) {
* getChoice. if ((choices == null)) { return null; }
* </p> return oneOrNone(message, Arrays.asList(choices));
*
* @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> 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. * Presents a list of choices where the player must choose exactly *amount* options.
* @param message * @param message
* the message to display to the player. * the message to display to the player.
@@ -140,58 +47,80 @@ public class GuiChoose {
* the amount of options that must be chosen. * the amount of options that must be chosen.
* @return * @return
*/ */
public static <T> List<T> amount(final String message, final T[] choices, final int amount) { public static <T extends Comparable<? super T>> List<T> amount(String message, List<T> choices, int amt, boolean sort, Comparator<T> sortComparator) {
if ((choices == null) || (choices.length == 0) || choices.length < amount) { if (null == choices || 0 == choices.size() || 0 == amt) {
return null; return null;
} }
final List<T> choice = _getChoices(message, amt, amt, choices, sort, sortComparator);
return GuiChoose.getChoices(message, amount, amount, choices); 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) { public static <T extends Comparable<? super T>> T one(String message, List<T> choices, boolean sort, Comparator<T> sortComparator) {
if ((choices == null) || (choices.size() == 0) || choices.size() < amount) { List<T> choice = amount(message, choices, 1, sort, sortComparator);
if (null == choice || choice.isEmpty()) {
return null; 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 // returned Object will never be null
/** private static <T extends Comparable<? super T>> List<T> _getChoices(String message, int min, int max, List<T> choices,
* <p> boolean sort, Comparator<T> sortComparator) {
* getChoices. return _getChoices(new ListChooser<T>(message, min, max, choices, sort, sortComparator));
* </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(ListChooser<T> c) {
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) {
final JList list = c.getJList(); final JList list = c.getJList();
list.addListSelectionListener(new ListSelectionListener() { list.addListSelectionListener(new ListSelectionListener() {
@Override @Override
public void valueChanged(final ListSelectionEvent ev) { public void valueChanged(final ListSelectionEvent ev) {
if (list.getSelectedValue() instanceof Card) { if (list.getSelectedValue() instanceof Card) {
CMatchUI.SINGLETON_INSTANCE.setCard((Card) list.getSelectedValue()); CMatchUI.SINGLETON_INSTANCE.setCard((Card) list.getSelectedValue());
GuiUtils.clearPanelSelections(); GuiUtils.clearPanelSelections();
GuiUtils.setPanelSelection((Card) list.getSelectedValue()); GuiUtils.setPanelSelection((Card) list.getSelectedValue());
} }
@@ -200,21 +129,31 @@ public class GuiChoose {
} }
} }
}); });
c.show(); c.show();
GuiUtils.clearPanelSelections(); GuiUtils.clearPanelSelections();
return c.getSelectedValues(); 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, public static <T extends Comparable<? super T>> List<T> order(String title, String top, int remainingObjects,
final List<T> sourceChoices, List<T> destChoices, Card referenceCard, boolean sideboardingMode) { 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. // An input box for handling the order of choices.
final JFrame frame = new JFrame(); 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.setLayout(new BorderLayout());
frame.setSize(dual.getPreferredSize()); frame.setSize(dual.getPreferredSize());
@@ -229,10 +168,12 @@ public class GuiChoose {
dialog.setLocationRelativeTo(null); dialog.setLocationRelativeTo(null);
dialog.pack(); dialog.pack();
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
if (referenceCard != null) { if (referenceCard != null) {
CMatchUI.SINGLETON_INSTANCE.setCard(referenceCard); CMatchUI.SINGLETON_INSTANCE.setCard(referenceCard);
// MARKED FOR UPDATE // MARKED FOR UPDATE
} }
dialog.setVisible(true); dialog.setVisible(true);
List<T> objects = dual.getOrderedList(); List<T> objects = dual.getOrderedList();
@@ -241,6 +182,4 @@ public class GuiChoose {
GuiUtils.clearPanelSelections(); GuiUtils.clearPanelSelections();
return objects; return objects;
} }
} }

View File

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

View File

@@ -545,19 +545,18 @@ public class QuestWinLose extends ControlWinLose {
if (qData.getFormat() == null) { if (qData.getFormat() == null) {
final List<GameFormat> formats = new ArrayList<GameFormat>(); 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()) { for (GameFormat f : Singletons.getModel().getFormats()) {
formats.add(f); formats.add(f);
if (f.toString().equals(prefferedFormat)) { if (f.toString().equals(preferredFormat)) {
index = i; pref = f;
} }
i++;
} }
final ListChooser<GameFormat> ch = new ListChooser<GameFormat>("Choose bonus booster format", 1, 1, formats); final ListChooser<GameFormat> ch = new ListChooser<GameFormat>("Choose bonus booster format", 1, 1, formats, true, null);
ch.show(index); ch.show(pref);
final GameFormat selected = ch.getSelectedValue(); final GameFormat selected = ch.getSelectedValue();
Singletons.getModel().getQuestPreferences().setPreference(QPref.BOOSTER_FORMAT, selected.toString()); 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. * 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 name;
private final String dir; private final String dir;
private final GameFormatQuest format; 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; package forge.gui;
import java.util.Arrays;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@@ -13,7 +15,7 @@ public class ListChooserTest {
*/ */
@Test(groups = { "UnitTest", "fast" }, timeOut = 1000, enabled = false) @Test(groups = { "UnitTest", "fast" }, timeOut = 1000, enabled = false)
public void listChooserTest1() { 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()); System.out.println(c.show());
for (final String s : c.getSelectedValues()) { for (final String s : c.getSelectedValues()) {
System.out.println(s); System.out.println(s);