Synchronized inputs: check if input has already been called 'done' and accept clicks only if it was not.

InputPayManaBase descendants: showMessage may be safely executed after input is dismissed (select card leads to re-check of requirements and may result in done() call, so showMessage is undesired, but it was already planned)
InputProliferate moved to separate file
Reverted 20840
This commit is contained in:
Maxmtg
2013-04-06 08:15:42 +00:00
parent 53a2ef4ee9
commit 8d4c82d330
18 changed files with 165 additions and 137 deletions

1
.gitattributes vendored
View File

@@ -13902,6 +13902,7 @@ src/main/java/forge/control/input/InputPayManaOfCostPayment.java -text
src/main/java/forge/control/input/InputPayManaSimple.java svneol=native#text/plain src/main/java/forge/control/input/InputPayManaSimple.java svneol=native#text/plain
src/main/java/forge/control/input/InputPayManaX.java -text src/main/java/forge/control/input/InputPayManaX.java -text
src/main/java/forge/control/input/InputPayment.java -text src/main/java/forge/control/input/InputPayment.java -text
src/main/java/forge/control/input/InputProliferate.java -text
src/main/java/forge/control/input/InputSelectCards.java -text src/main/java/forge/control/input/InputSelectCards.java -text
src/main/java/forge/control/input/InputSelectCardsFromList.java -text src/main/java/forge/control/input/InputSelectCardsFromList.java -text
src/main/java/forge/control/input/InputSelectMany.java -text src/main/java/forge/control/input/InputSelectMany.java -text

View File

@@ -1,9 +1,7 @@
package forge.card.ability.effects; package forge.card.ability.effects;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@@ -16,85 +14,11 @@ import forge.Singletons;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.input.InputSelectManyBase; import forge.control.input.InputProliferate;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
public class CountersProliferateEffect extends SpellAbilityEffect { public class CountersProliferateEffect extends SpellAbilityEffect {
/**
* TODO: Write javadoc for this type.
*
*/
public static final class InputProliferate extends InputSelectManyBase<GameEntity> {
private static final long serialVersionUID = -1779224307654698954L;
private Map<GameEntity, CounterType> chosenCounters = new HashMap<GameEntity, CounterType>();
public InputProliferate() {
super(1, Integer.MAX_VALUE);
}
@Override
protected String getMessage() {
StringBuilder sb = new StringBuilder("Choose permanents and/or players with counters on them to add one more counter of that type.");
sb.append("\n\nYou've selected so far:\n");
if( selected.isEmpty())
sb.append("(none)");
else
for(GameEntity ge : selected ) {
if( ge instanceof Player )
sb.append("* A poison counter to player ").append(ge).append("\n");
else
sb.append("* ").append(ge).append(" -> ").append(chosenCounters.get(ge)).append("counter\n");
}
return sb.toString();
}
@Override
public void selectCard(final Card card) {
if( !selectEntity(card) )
return;
if( selected.contains(card) ) {
final List<CounterType> choices = new ArrayList<CounterType>();
for (final CounterType ct : CounterType.values()) {
if (card.getCounters(ct) > 0) {
choices.add(ct);
}
}
CounterType toAdd = choices.size() == 1 ? choices.get(0) : GuiChoose.one("Select counter type", choices);
chosenCounters.put(card, toAdd);
}
refresh();
}
@Override
public void selectPlayer(final Player player) {
if( !selectEntity(player) )
return;
refresh();
}
@Override
protected boolean isValidChoice(GameEntity choice) {
if (choice instanceof Player)
return ((Player) choice).getPoisonCounters() > 0 && !choice.hasKeyword("You can't get poison counters");
if (choice instanceof Card)
return ((Card) choice).hasCounters();
return false;
}
public CounterType getCounterFor(GameEntity ge) {
return chosenCounters.get(ge);
}
}
@Override @Override
protected String getStackDescription(SpellAbility sa) { protected String getStackDescription(SpellAbility sa) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();

View File

@@ -85,7 +85,7 @@ public class CostExile extends CostPartWithList {
for (int i = 0; i < nNeeded; i++) { for (int i = 0; i < nNeeded; i++) {
if (this.typeList.size() == 0) { if (this.typeList.size() == 0) {
this.cancel(); this.onCancel();
} }
final Card c = GuiChoose.oneOrNone("Exile from " + part.getFrom(), this.typeList); final Card c = GuiChoose.oneOrNone("Exile from " + part.getFrom(), this.typeList);
@@ -97,7 +97,7 @@ public class CostExile extends CostPartWithList {
this.done(); this.done();
} }
} else { } else {
this.cancel(); this.onCancel();
break; break;
} }
} }
@@ -145,14 +145,14 @@ public class CostExile extends CostPartWithList {
final Player p = GuiChoose.oneOrNone(sb.toString(), payableZone); final Player p = GuiChoose.oneOrNone(sb.toString(), payableZone);
if (p == null) { if (p == null) {
this.cancel(); this.onCancel();
} }
typeList = CardLists.filter(list, CardPredicates.isOwner(p)); typeList = CardLists.filter(list, CardPredicates.isOwner(p));
for (int i = 0; i < nNeeded; i++) { for (int i = 0; i < nNeeded; i++) {
if (this.typeList.size() == 0) { if (this.typeList.size() == 0) {
this.cancel(); this.onCancel();
} }
final Card c = GuiChoose.oneOrNone("Exile from " + part.getFrom(), this.typeList); final Card c = GuiChoose.oneOrNone("Exile from " + part.getFrom(), this.typeList);
@@ -164,7 +164,7 @@ public class CostExile extends CostPartWithList {
this.done(); this.done();
} }
} else { } else {
this.cancel(); this.onCancel();
break; break;
} }
} }
@@ -225,7 +225,7 @@ public class CostExile extends CostPartWithList {
for (int i = 0; i < nNeeded; i++) { for (int i = 0; i < nNeeded; i++) {
if (this.saList.isEmpty()) { if (this.saList.isEmpty()) {
this.cancel(); this.onCancel();
} }
//Have to use the stack descriptions here because some copied spells have no description otherwise //Have to use the stack descriptions here because some copied spells have no description otherwise
@@ -248,7 +248,7 @@ public class CostExile extends CostPartWithList {
final SpellAbilityStackInstance si = stack.getInstanceFromSpellAbility(toExile); final SpellAbilityStackInstance si = stack.getInstanceFromSpellAbility(toExile);
stack.remove(si); stack.remove(si);
} else { } else {
this.cancel(); this.onCancel();
break; break;
} }
} }
@@ -309,7 +309,7 @@ public class CostExile extends CostPartWithList {
} }
@Override @Override
public void selectCard(final Card card) { protected void onCardSelected(Card card) {
if (this.typeList.contains(card)) { if (this.typeList.contains(card)) {
this.nExiles++; this.nExiles++;
part.executePayment(sa, card); part.executePayment(sa, card);
@@ -319,7 +319,7 @@ public class CostExile extends CostPartWithList {
this.done(); this.done();
} else if (this.typeList.size() == 0) { } else if (this.typeList.size() == 0) {
// happen // happen
this.cancel(); this.onCancel();
} else { } else {
this.showMessage(); this.showMessage();
} }
@@ -357,7 +357,7 @@ public class CostExile extends CostPartWithList {
return; return;
} }
} }
cancel(); onCancel();
} }
} }

View File

@@ -87,7 +87,7 @@ public class CostPutCounter extends CostPartWithList {
} }
@Override @Override
public void selectCard(final Card card) { protected void onCardSelected(Card card) {
if (this.typeList.contains(card)) { if (this.typeList.contains(card)) {
this.nPut++; this.nPut++;
costPutCounter.executePayment(sa, card); costPutCounter.executePayment(sa, card);

View File

@@ -93,8 +93,11 @@ public class CostRemoveCounter extends CostPartWithList {
ButtonUtil.enableOnlyCancel(); ButtonUtil.enableOnlyCancel();
} }
/* (non-Javadoc)
* @see forge.control.input.InputSyncronizedBase#onCardSelected(forge.Card)
*/
@Override @Override
public void selectCard(final Card card) { protected void onCardSelected(Card card) {
if (this.typeList.contains(card)) { if (this.typeList.contains(card)) {
if (card.getCounters(costRemoveCounter.getCounter()) > 0) { if (card.getCounters(costRemoveCounter.getCounter()) > 0) {
this.nRemove++; this.nRemove++;
@@ -132,7 +135,6 @@ public class CostRemoveCounter extends CostPartWithList {
* @param payment * @param payment
*/ */
public InputPayCostRemoveCounterFrom(CostRemoveCounter costRemoveCounter, String type, SpellAbility sa, int nNeeded) { public InputPayCostRemoveCounterFrom(CostRemoveCounter costRemoveCounter, String type, SpellAbility sa, int nNeeded) {
this.costRemoveCounter = costRemoveCounter; this.costRemoveCounter = costRemoveCounter;
this.type = type; this.type = type;
this.sa = sa; this.sa = sa;
@@ -151,14 +153,11 @@ public class CostRemoveCounter extends CostPartWithList {
for (int i = 0; i < nNeeded; i++) { for (int i = 0; i < nNeeded; i++) {
if (this.typeList.isEmpty()) { if (this.typeList.isEmpty()) {
this.cancel(); this.onCancel();
} }
final Card o = GuiChoose.oneOrNone("Remove counter(s) from a card in " + costRemoveCounter.getZone(), this.typeList); final Card card = GuiChoose.oneOrNone("Remove counter(s) from a card in " + costRemoveCounter.getZone(), this.typeList);
if (card != null) {
if (o != null) {
final Card card = o;
if (card.getCounters(costRemoveCounter.getCounter()) > 0) { if (card.getCounters(costRemoveCounter.getCounter()) > 0) {
this.nRemove++; this.nRemove++;
costRemoveCounter.executePayment(sa, card); costRemoveCounter.executePayment(sa, card);
@@ -174,7 +173,7 @@ public class CostRemoveCounter extends CostPartWithList {
} }
} }
} else { } else {
this.cancel(); this.onCancel();
break; break;
} }
} }

View File

@@ -20,17 +20,13 @@ abstract class InputPayCostBase extends InputSyncronizedBase implements InputPay
private static final long serialVersionUID = -2967434867139585579L; private static final long serialVersionUID = -2967434867139585579L;
boolean bPaid = false; boolean bPaid = false;
@Override
final public void selectButtonCancel() {
this.cancel();
}
final protected void done() { final protected void done() {
bPaid = true; bPaid = true;
this.stop(); this.stop();
} }
final public void cancel() { @Override
final protected void onCancel() {
this.stop(); this.stop();
} }

View File

@@ -45,9 +45,10 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
this.saPaidFor = saToPayFor; this.saPaidFor = saToPayFor;
} }
/** {@inheritDoc} */
@Override @Override
public void selectCard(final Card card) { protected void onCardSelected(Card card) {
if (card.getManaAbility().isEmpty() || card.isInZone(ZoneType.Hand)) { if (card.getManaAbility().isEmpty() || card.isInZone(ZoneType.Hand)) {
SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE); SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE);
return; return;
@@ -245,7 +246,6 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
if (!skipExpress) { if (!skipExpress) {
// express Mana Choice // express Mana Choice
final ArrayList<SpellAbility> colorMatches = new ArrayList<SpellAbility>(); final ArrayList<SpellAbility> colorMatches = new ArrayList<SpellAbility>();
for (final SpellAbility am : abilities) { for (final SpellAbility am : abilities) {
AbilityManaPart m = am.getManaPart(); AbilityManaPart m = am.getManaPart();
if (am.getApi() == ApiType.ManaReflected) { if (am.getApi() == ApiType.ManaReflected) {

View File

@@ -108,19 +108,17 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectButtonCancel() { protected final void onCancel() {
Singletons.getControl().getPlayer().getManaPool().refundManaPaid(this.saPaidFor, true); Singletons.getControl().getPlayer().getManaPool().refundManaPaid(this.saPaidFor, true);
bPaid = false; bPaid = false;
this.stop(); this.stop();
} }
/** {@inheritDoc} */
@Override
public final void selectButtonOK() {}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void showMessage() { public final void showMessage() {
if ( isFinished() ) return;
ButtonUtil.enableOnlyCancel(); ButtonUtil.enableOnlyCancel();
final StringBuilder msg = new StringBuilder(this.message + "Pay Mana Cost: " + this.manaCost); final StringBuilder msg = new StringBuilder(this.message + "Pay Mana Cost: " + this.manaCost);
if (this.phyLifeToLose > 0) { if (this.phyLifeToLose > 0) {

View File

@@ -48,13 +48,15 @@ public class InputPayManaOfCostPayment extends InputPayManaBase {
} }
@Override @Override
public void selectButtonCancel() { protected void onCancel() {
handleConvokedCards(true); handleConvokedCards(true);
stop(); stop();
} }
@Override @Override
public void showMessage() { public void showMessage() {
if ( isFinished() ) return; //
ButtonUtil.enableOnlyCancel(); ButtonUtil.enableOnlyCancel();
final String displayMana = manaCost.toString().replace("X", "").trim(); final String displayMana = manaCost.toString().replace("X", "").trim();

View File

@@ -106,7 +106,7 @@ public class InputPayManaSimple extends InputPayManaBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectButtonCancel() { protected final void onCancel() {
handleConvokedCards(true); handleConvokedCards(true);
this.resetManaCost(); this.resetManaCost();
@@ -119,6 +119,8 @@ public class InputPayManaSimple extends InputPayManaBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void showMessage() { public final void showMessage() {
if( isFinished() ) return;
ButtonUtil.enableOnlyCancel(); ButtonUtil.enableOnlyCancel();
final StringBuilder msg = new StringBuilder("Pay Mana Cost: " + this.manaCost.toString()); final StringBuilder msg = new StringBuilder("Pay Mana Cost: " + this.manaCost.toString());

View File

@@ -39,6 +39,8 @@ public class InputPayManaX extends InputPayManaBase {
@Override @Override
public void showMessage() { public void showMessage() {
if( isFinished() ) return;
// only cancel if partially paid an X value // only cancel if partially paid an X value
// or X is 0, and x can't be 0 // or X is 0, and x can't be 0
if (!isPaid()) { if (!isPaid()) {
@@ -57,9 +59,8 @@ public class InputPayManaX extends InputPayManaBase {
showMessage(msg.toString()); showMessage(msg.toString());
} }
// selectCard
@Override @Override
public void selectCard(final Card card) { protected void onCardSelected(Card card) {
// don't allow here the cards that produce only wrong colors // don't allow here the cards that produce only wrong colors
activateManaAbility(card, this.colorX.isEmpty() ? this.manaCost : new ManaCostBeingPaid(this.colorX)); activateManaAbility(card, this.colorX.isEmpty() ? this.manaCost : new ManaCostBeingPaid(this.colorX));
} }
@@ -77,12 +78,12 @@ public class InputPayManaX extends InputPayManaBase {
} }
@Override @Override
public void selectButtonCancel() { protected final void onCancel() {
this.stop(); this.stop();
} }
@Override @Override
public void selectButtonOK() { protected final void onOk() {
done(); done();
} }

View File

@@ -0,0 +1,84 @@
package forge.control.input;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import forge.Card;
import forge.CounterType;
import forge.GameEntity;
import forge.game.player.Player;
import forge.gui.GuiChoose;
/**
* TODO: Write javadoc for this type.
*
*/
public final class InputProliferate extends InputSelectManyBase<GameEntity> {
private static final long serialVersionUID = -1779224307654698954L;
private Map<GameEntity, CounterType> chosenCounters = new HashMap<GameEntity, CounterType>();
public InputProliferate() {
super(1, Integer.MAX_VALUE);
}
@Override
protected String getMessage() {
StringBuilder sb = new StringBuilder("Choose permanents and/or players with counters on them to add one more counter of that type.");
sb.append("\n\nYou've selected so far:\n");
if( selected.isEmpty())
sb.append("(none)");
else
for(GameEntity ge : selected ) {
if( ge instanceof Player )
sb.append("* A poison counter to player ").append(ge).append("\n");
else
sb.append("* ").append(ge).append(" -> ").append(chosenCounters.get(ge)).append("counter\n");
}
return sb.toString();
}
@Override
protected void onCardSelected(Card card) {
if( !selectEntity(card) )
return;
if( selected.contains(card) ) {
final List<CounterType> choices = new ArrayList<CounterType>();
for (final CounterType ct : CounterType.values()) {
if (card.getCounters(ct) > 0) {
choices.add(ct);
}
}
CounterType toAdd = choices.size() == 1 ? choices.get(0) : GuiChoose.one("Select counter type", choices);
chosenCounters.put(card, toAdd);
}
refresh();
}
@Override
public void selectPlayer(final Player player) {
if( !selectEntity(player) )
return;
refresh();
}
@Override
protected boolean isValidChoice(GameEntity choice) {
if (choice instanceof Player)
return ((Player) choice).getPoisonCounters() > 0 && !choice.hasKeyword("You can't get poison counters");
if (choice instanceof Card)
return ((Card) choice).hasCounters();
return false;
}
public CounterType getCounterFor(GameEntity ge) {
return chosenCounters.get(ge);
}
}

View File

@@ -11,7 +11,7 @@ public abstract class InputSelectCards extends InputSelectManyBase<Card> {
} }
@Override @Override
public final void selectCard(final Card c) { protected void onCardSelected(Card c) {
if ( !selectEntity(c) ) if ( !selectEntity(c) )
return; return;

View File

@@ -74,7 +74,7 @@ public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyn
} }
@Override @Override
public final void selectButtonCancel() { protected final void onCancel() {
bCancelled = true; bCancelled = true;
this.stop(); this.stop();
} }
@@ -90,7 +90,7 @@ public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyn
} }
@Override @Override
public final void selectButtonOK() { protected final void onOk() {
this.stop(); this.stop();
} }

View File

@@ -89,19 +89,19 @@ public final class InputSelectTargets extends InputSyncronizedBase {
} }
@Override @Override
public void selectButtonCancel() { protected final void onCancel() {
bCancel = true; bCancel = true;
this.done(); this.done();
} }
@Override @Override
public void selectButtonOK() { protected final void onOk() {
bOk = true; bOk = true;
this.done(); this.done();
} }
@Override @Override
public void selectCard(final Card card) { protected final void onCardSelected(Card card) {
if (!tgt.isUniqueTargets() && targetDepth.containsKey(card)) { if (!tgt.isUniqueTargets() && targetDepth.containsKey(card)) {
return; return;
} }

View File

@@ -2,6 +2,7 @@ package forge.control.input;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import forge.Card;
import forge.FThreads; import forge.FThreads;
import forge.error.BugReporter; import forge.error.BugReporter;
import forge.game.player.Player; import forge.game.player.Player;
@@ -9,6 +10,7 @@ import forge.game.player.Player;
public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized { public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized {
private static final long serialVersionUID = 8756177361251703052L; private static final long serialVersionUID = 8756177361251703052L;
private boolean finished = false;
private final CountDownLatch cdlDone; private final CountDownLatch cdlDone;
public InputSyncronizedBase(Player player) { public InputSyncronizedBase(Player player) {
@@ -28,6 +30,32 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn
@Override @Override
protected void afterStop() { protected void afterStop() {
finished = true;
cdlDone.countDown(); cdlDone.countDown();
} }
@Override
public final void selectButtonCancel() {
if( finished ) return;
onCancel();
}
@Override
public final void selectButtonOK() {
if( finished ) return;
onOk();
}
@Override
public final void selectCard(Card c) {
if( finished ) return;
onCardSelected(c);
}
protected final boolean isFinished() { return finished; }
protected void onCardSelected(Card c) {}
protected void onCancel() {}
protected void onOk() {}
} }

View File

@@ -88,19 +88,15 @@ public class GuiChoose {
} }
public static <T> List<T> noneOrMany(final String message, final Collection<T> choices) { public static <T> List<T> noneOrMany(final String message, final Collection<T> choices) {
return GuiChoose.getChoices(message, 0, choices.size(), choices, null); return GuiChoose.getChoices(message, 0, choices.size(), choices);
} }
// returned Object will never be null // returned Object will never be null
public static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices) { public static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices) {
return getChoices(message, min, max, Arrays.asList(choices), null); return getChoices(message, min, max, Arrays.asList(choices));
}
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices) {
return getChoices(message, min, max, choices, null);
} }
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices,final T selected) { public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices) {
if (null == choices || choices.isEmpty()) { if (null == choices || choices.isEmpty()) {
if (0 == min) { if (0 == min) {
return new ArrayList<T>(); return new ArrayList<T>();
@@ -128,12 +124,7 @@ public class GuiChoose {
} }
} }
}); });
c.show();
if(selected != null)
c.show(selected);
else
c.show();
GuiUtils.clearPanelSelections(); GuiUtils.clearPanelSelections();
return c.getSelectedValues(); return c.getSelectedValues();
} }

View File

@@ -560,8 +560,10 @@ public class QuestWinLose extends ControlWinLose {
} }
Collections.sort(formats); Collections.sort(formats);
final ListChooser<GameFormat> ch = new ListChooser<GameFormat>("Choose bonus booster format", 1, 1, formats);
ch.show(pref);
final GameFormat selected = GuiChoose.getChoices("Choose bonus booster format", 1, 1, formats, pref).get(0); //ch.getSelectedValue(); final GameFormat selected = ch.getSelectedValue();
Singletons.getModel().getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected.toString()); Singletons.getModel().getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected.toString());
cardsWon = qData.getCards().addCards(selected.getFilterPrinted()); cardsWon = qData.getCards().addCards(selected.getFilterPrinted());