Add "Auto" button for automatically paying a mana cost

Code cleanup
This commit is contained in:
drdev
2013-12-02 03:07:19 +00:00
parent dcb9553807
commit 0b6be04428
14 changed files with 247 additions and 166 deletions

View File

@@ -12,8 +12,8 @@ import forge.util.ThreadUtil;
*
*/
public class FThreads {
private FThreads() { } // no instances supposed
/** Checks if calling method uses event dispatch thread.
* Exception thrown if method is on "wrong" thread.
* A boolean is passed to indicate if the method must be EDT or not.
@@ -22,11 +22,11 @@ public class FThreads {
* @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT
*/
public static void assertExecutedByEdt(final boolean mustBeEDT) {
if (isGuiThread() != mustBeEDT ) {
if (isGuiThread() != mustBeEDT) {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
final String methodName = trace[2].getClassName() + "." + trace[2].getMethodName();
String modalOperator = mustBeEDT ? " must be" : " may not be";
throw new IllegalStateException( methodName + modalOperator + " accessed from the event dispatch thread.");
throw new IllegalStateException(methodName + modalOperator + " accessed from the event dispatch thread.");
}
}
@@ -42,10 +42,12 @@ public class FThreads {
* TODO: Write javadoc for this method.
*/
public static void invokeInEdtNowOrLater(Runnable proc) {
if( isGuiThread() )
if (isGuiThread()) {
proc.run();
else
}
else {
invokeInEdtLater(proc);
}
}
/**
@@ -64,20 +66,20 @@ public class FThreads {
if (SwingUtilities.isEventDispatchThread()) {
// Just run in the current thread.
proc.run();
} else {
}
else {
try {
SwingUtilities.invokeAndWait(proc);
} catch (final InterruptedException exn) {
}
catch (final InterruptedException exn) {
throw new RuntimeException(exn);
} catch (final InvocationTargetException exn) {
}
catch (final InvocationTargetException exn) {
throw new RuntimeException(exn);
}
}
}
/**
* TODO: Write javadoc for this method.
* @return
@@ -86,16 +88,16 @@ public class FThreads {
return SwingUtilities.isEventDispatchThread();
}
public static void delayInEDT(int milliseconds, final Runnable inputUpdater) {
Runnable runInEdt = new Runnable() {
@Override public void run() {
@Override
public void run() {
FThreads.invokeInEdtNowOrLater(inputUpdater);
}
};
ThreadUtil.delay(milliseconds, runInEdt);
}
public static String debugGetCurrThreadId() {
return isGuiThread() ? "EDT" : Thread.currentThread().getName();
}
@@ -103,28 +105,30 @@ public class FThreads {
public static String prependThreadId(String message) {
return debugGetCurrThreadId() + " > " + message;
}
public static void dumpStackTrace(PrintStream stream) {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
stream.printf("%s > %s called from %s%n", debugGetCurrThreadId(), trace[2].getClassName()+"."+trace[2].getMethodName(), trace[3].toString());
int i = 0;
for(StackTraceElement se : trace) {
if(i<2) i++;
else stream.println(se.toString());
}
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
stream.printf("%s > %s called from %s%n", debugGetCurrThreadId(),
trace[2].getClassName() + "." + trace[2].getMethodName(), trace[3].toString());
int i = 0;
for (StackTraceElement se : trace) {
if (i<2) { i++; }
else { stream.println(se.toString()); }
}
}
public static String debugGetStackTraceItem(int depth, boolean shorter) {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
String lastItem = trace[depth].toString();
if( shorter ) {
if (shorter) {
int lastPeriod = lastItem.lastIndexOf('.');
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
lastPeriod = lastItem.lastIndexOf('.', lastPeriod-1);
lastItem = lastItem.substring(lastPeriod+1);
return String.format("%s > from %s", debugGetCurrThreadId(), lastItem);
}
return String.format("%s > %s called from %s", debugGetCurrThreadId(), trace[2].getClassName()+"."+trace[2].getMethodName(), lastItem);
return String.format("%s > %s called from %s", debugGetCurrThreadId(),
trace[2].getClassName() + "." + trace[2].getMethodName(), lastItem);
}
public static String debugGetStackTraceItem(int depth) {

View File

@@ -47,9 +47,17 @@ import forge.util.maps.MapOfLists;
*
*/
public class ComputerUtilMana {
private final static boolean DEBUG_MANA_PAYMENT = false;
public static boolean canPayManaCost(ManaCostBeingPaid cost, final SpellAbility sa, final Player ai) {
cost = new ManaCostBeingPaid(cost); //check copy of cost so it doesn't modify the exist cost being paid
return payManaCost(cost, sa, ai, true, 0, true);
}
public static boolean payManaCost(ManaCostBeingPaid cost, final SpellAbility sa, final Player ai) {
return payManaCost(cost, sa, ai, false, 0, true);
}
public static boolean canPayManaCost(final SpellAbility sa, final Player ai, final int extraMana) {
return payManaCost(sa, ai, true, extraMana, true);
}

View File

@@ -50,7 +50,7 @@ import forge.util.maps.MapToAmount;
/**
* <p>
* ManaCost class.
* ManaCostBeingPaid class.
* </p>
*
* @author Forge
@@ -62,45 +62,49 @@ public class ManaCostBeingPaid {
private ManaCostShard nextShard = null;
private int remainingShards = 0;
private boolean hasSentX = false;
public ManaCostBeingPaidIterator() {
public ManaCostBeingPaidIterator() {
mch = unpaidShards.keySet().iterator();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public ManaCostShard next() {
if (remainingShards == 0)
if (remainingShards == 0) {
throw new UnsupportedOperationException("All shards were depleted, call hasNext()");
}
remainingShards--;
return nextShard;
}
@Override
public boolean hasNext() {
if ( remainingShards > 0 ) return true;
if ( !hasSentX ) {
if ( nextShard != ManaCostShard.X && cntX > 0) {
if (remainingShards > 0) { return true; }
if (!hasSentX) {
if (nextShard != ManaCostShard.X && cntX > 0) {
nextShard = ManaCostShard.X;
remainingShards = cntX;
return true;
} else
}
else {
hasSentX = true;
}
}
if ( !mch.hasNext() ) return false;
if (!mch.hasNext()) { return false; }
nextShard = mch.next();
if ( nextShard == ManaCostShard.COLORLESS )
if (nextShard == ManaCostShard.COLORLESS) {
return this.hasNext(); // skip colorless
}
remainingShards = unpaidShards.get(nextShard);
return true;
}
@Override
public int getTotalColorlessCost() {
Integer c = unpaidShards.get(ManaCostShard.COLORLESS);
@@ -110,15 +114,25 @@ public class ManaCostBeingPaid {
// holds Mana_Part objects
// ManaPartColor is stored before ManaPartColorless
private final MapToAmount<ManaCostShard> unpaidShards = new EnumMapToAmount<ManaCostShard>(ManaCostShard.class);
private final MapToAmount<ManaCostShard> unpaidShards;
private final String sourceRestriction;
private byte sunburstMap = 0;
private int cntX = 0;
private final String sourceRestriction;
/**
* Copy constructor
* @param manaCostBeingPaid
*/
public ManaCostBeingPaid(ManaCostBeingPaid manaCostBeingPaid) {
unpaidShards = new EnumMapToAmount<ManaCostShard>(manaCostBeingPaid.unpaidShards);
sourceRestriction = manaCostBeingPaid.sourceRestriction;
sunburstMap = manaCostBeingPaid.sunburstMap;
cntX = manaCostBeingPaid.cntX;
}
// manaCost can be like "0", "3", "G", "GW", "10", "3 GW", "10 GW"
// or "split hybrid mana" like "2/G 2/G", "2/B 2/B 2/B"
// "GW" can be paid with either G or W
/**
* <p>
* Constructor for ManaCost.
@@ -134,9 +148,11 @@ public class ManaCostBeingPaid {
public ManaCostBeingPaid(ManaCost manaCost) {
this(manaCost, null);
}
public ManaCostBeingPaid(ManaCost manaCost, String srcRestriction) {
unpaidShards = new EnumMapToAmount<ManaCostShard>(ManaCostShard.class);
sourceRestriction = srcRestriction;
if( manaCost == null ) return;
if (manaCost == null) { return; }
for (ManaCostShard shard : manaCost.getShards()) {
if (shard == ManaCostShard.X) {
cntX++;
@@ -163,7 +179,6 @@ public class ManaCostBeingPaid {
return sunburstMap;
}
public final boolean containsPhyrexianMana() {
for (ManaCostShard shard : unpaidShards.keySet()) {
if (shard.isPhyrexian()) {
@@ -175,32 +190,36 @@ public class ManaCostBeingPaid {
public final boolean payPhyrexian() {
ManaCostShard phy = null;
for(ManaCostShard mcs : unpaidShards.keySet()) {
if( mcs.isPhyrexian() ) {
for (ManaCostShard mcs : unpaidShards.keySet()) {
if (mcs.isPhyrexian()) {
phy = mcs;
break;
}
}
if (phy == null )
if (phy == null) {
return false;
}
decreaseShard(phy, 1);
return true;
}
// takes a Short Color and returns true if it exists in the mana cost.
// Easier for split costs
public final boolean needsColor(final byte colorMask) {
for (ManaCostShard shard : unpaidShards.keySet()) {
if (shard == ManaCostShard.COLORLESS)
if (shard == ManaCostShard.COLORLESS) {
continue;
}
if (shard.isOr2Colorless()) {
if ((shard.getColorMask() & colorMask) != 0 )
if ((shard.getColorMask() & colorMask) != 0) {
return true;
} else if (shard.canBePaidWithManaOfColor(colorMask))
}
}
else if (shard.canBePaidWithManaOfColor(colorMask)) {
return true;
}
}
return false;
}
@@ -224,10 +243,9 @@ public class ManaCostBeingPaid {
return false;
}
public final boolean isPaid() {
return unpaidShards.isEmpty();
} // isPaid()
}
/**
* <p>
@@ -242,18 +260,20 @@ public class ManaCostBeingPaid {
List<String> unused = new ArrayList<String>(4);
for (String manaPart : TextUtil.split(mana, ' ')) {
if (StringUtils.isNumeric(manaPart)) {
for(int i = Integer.parseInt(manaPart); i > 0; i--) {
for (int i = Integer.parseInt(manaPart); i > 0; i--) {
boolean wasNeeded = this.payMana("1");
if(!wasNeeded) {
if (!wasNeeded) {
unused.add(Integer.toString(i));
break;
}
}
} else {
}
else {
String color = MagicColor.toShortString(manaPart);
boolean wasNeeded = this.payMana(color);
if(!wasNeeded)
if (!wasNeeded) {
unused.add(color);
}
}
}
return unused.isEmpty() ? null : StringUtils.join(unused, ' ');
@@ -305,7 +325,8 @@ public class ManaCostBeingPaid {
}
Predicate<ManaCostShard> predCanBePaid = new Predicate<ManaCostShard>() {
@Override public boolean apply(ManaCostShard ms) {
@Override
public boolean apply(ManaCostShard ms) {
return ms.canBePaidWithManaOfColor(colorMask);
}
};
@@ -328,11 +349,12 @@ public class ManaCostBeingPaid {
}
Predicate<ManaCostShard> predCanBePaid = new Predicate<ManaCostShard>() {
@Override public boolean apply(ManaCostShard ms) {
@Override
public boolean apply(ManaCostShard ms) {
return canBePaidWith(ms, mana);
}
};
return tryPayMana(mana.getColorCode(), Iterables.filter(unpaidShards.keySet(), predCanBePaid));
}
@@ -351,12 +373,12 @@ public class ManaCostBeingPaid {
if (choice == null) {
return false;
}
decreaseShard(choice, 1);
if (choice.isOr2Colorless() && choice.getColorMask() != colorMask ) {
if (choice.isOr2Colorless() && choice.getColorMask() != colorMask) {
this.increaseColorlessMana(1);
}
this.sunburstMap |= colorMask;
return true;
}
@@ -386,7 +408,7 @@ public class ManaCostBeingPaid {
if (shard.isSnow() && !mana.isSnow()) {
return false;
}
byte color = mana.getColorCode();
return shard.canBePaidWithManaOfColor(color);
}
@@ -395,7 +417,8 @@ public class ManaCostBeingPaid {
for (ManaCostShard shard : extra.getShards()) {
if (shard == ManaCostShard.X) {
cntX++;
} else {
}
else {
increaseShard(shard, 1);
}
}
@@ -406,9 +429,11 @@ public class ManaCostBeingPaid {
for (ManaCostShard shard : subThisManaCost.getShards()) {
if (shard == ManaCostShard.X) {
cntX--;
} else if (unpaidShards.containsKey(shard)) {
}
else if (unpaidShards.containsKey(shard)) {
decreaseShard(shard, 1);
} else {
}
else {
decreaseColorlessMana(1);
}
}
@@ -484,7 +509,7 @@ public class ManaCostBeingPaid {
}
return cmc;
}
public ManaCost toManaCost() {
return new ManaCost(new ManaCostBeingPaidIterator());
}
@@ -493,20 +518,19 @@ public class ManaCostBeingPaid {
return cntX;
}
public final List<ManaCostShard> getUnpaidShards() {
public final List<ManaCostShard> getUnpaidShards() {
List<ManaCostShard> result = new ArrayList<ManaCostShard>();
for(Entry<ManaCostShard, Integer> kv : unpaidShards.entrySet()) {
for(int i = kv.getValue().intValue(); i > 0; i--) {
for (Entry<ManaCostShard, Integer> kv : unpaidShards.entrySet()) {
for (int i = kv.getValue().intValue(); i > 0; i--) {
result.add(kv.getKey());
}
}
for(int i = cntX; i > 0; i--) {
for (int i = cntX; i > 0; i--) {
result.add(ManaCostShard.X);
}
return result;
}
/**
* <p>
* removeColorlessMana.
@@ -524,7 +548,6 @@ public class ManaCostBeingPaid {
final Card originalCard = sa.getSourceCard();
final SpellAbility spell = sa;
if (sa.isXCost() && !originalCard.isCopiedSpell()) {
originalCard.setXManaCostPaid(0);
}
@@ -544,7 +567,8 @@ public class ManaCostBeingPaid {
pc.getGame().getAction().exile(c);
}
}
} else if (spell.getSourceCard().hasKeyword("Convoke")) {
}
else if (spell.getSourceCard().hasKeyword("Convoke")) {
adjustCostByConvoke(sa, spell);
}
} // isSpell
@@ -565,9 +589,11 @@ public class ManaCostBeingPaid {
for (final StaticAbility stAb : staticAbilities) {
if (stAb.getMapParams().get("Mode").equals("RaiseCost")) {
raiseAbilities.add(stAb);
} else if (stAb.getMapParams().get("Mode").equals("ReduceCost")) {
}
else if (stAb.getMapParams().get("Mode").equals("ReduceCost")) {
reduceAbilities.add(stAb);
} else if (stAb.getMapParams().get("Mode").equals("SetCost")) {
}
else if (stAb.getMapParams().get("Mode").equals("SetCost")) {
setAbilities.add(stAb);
}
}
@@ -601,27 +627,29 @@ public class ManaCostBeingPaid {
String chosenColor = null;
if (sa.getActivatingPlayer().isHuman()) {
workingCard = GuiChoose.oneOrNone("Tap for Convoke? " + toString(), untappedCreats);
if( null == workingCard )
if (null == workingCard) {
break; // that means "I'm done"
}
List<String> usableColors = getConvokableColors(workingCard);
if ( !usableColors.isEmpty() ) {
if (!usableColors.isEmpty()) {
chosenColor = usableColors.size() == 1 ? usableColors.get(0) : GuiChoose.one("Convoke for which color?", usableColors);
}
} else {
}
}
else {
// TODO: AI to choose a creature to tap would go here
// Probably along with deciding how many creatures to tap
break;
}
untappedCreats.remove(workingCard);
if ( null == chosenColor )
if (null == chosenColor) {
continue;
}
else if (chosenColor.equals("colorless")) {
decreaseColorlessMana(1);
} else {
}
else {
decreaseShard(ManaCostShard.valueOf(MagicColor.fromName(chosenColor)), 1);
}
@@ -640,7 +668,6 @@ public class ManaCostBeingPaid {
for (final Card c : sa.getTappedForConvoke()) {
c.setTapped(true);
}
}
/**
@@ -654,14 +681,15 @@ public class ManaCostBeingPaid {
*/
private List<String> getConvokableColors(final Card cardToConvoke) {
final ArrayList<String> usableColors = new ArrayList<String>();
if (getColorlessManaAmount() > 0) {
usableColors.add("colorless");
}
ColorSet cs = CardUtil.getColors(cardToConvoke);
for(byte color : MagicColor.WUBRG) {
if( cs.hasAnyColor(color))
for (byte color : MagicColor.WUBRG) {
if (cs.hasAnyColor(color)) {
usableColors.add(MagicColor.toLongString(color));
}
}
return usableColors;
}
@@ -684,7 +712,8 @@ public class ManaCostBeingPaid {
if (!toSacList.isEmpty()) {
toSac = toSacList.get(0);
} else {
}
else {
return;
}

View File

@@ -76,13 +76,10 @@ import forge.util.TextUtil;
* Handles phase skips for now.
*/
public class PlayerControllerHuman extends PlayerController {
public PlayerControllerHuman(Game game0, Player p, LobbyPlayer lp) {
super(game0, p, lp);
}
public boolean isUiSetToSkipPhase(final Player turn, final PhaseType phase) {
return !CMatchUI.SINGLETON_INSTANCE.stopAtPhase(turn, phase);
}

View File

@@ -280,7 +280,9 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
* a {@link forge.game.spellability.SpellAbility} object.
*/
public final void add(final SpellAbility sp) {
FThreads.assertExecutedByEdt(false);
if (!sp.isManaAbility()) { //allow adding mana abilities on EDT
FThreads.assertExecutedByEdt(false);
}
SpellAbilityStackInstance si = null;
final Card source = sp.getSourceCard();
Player activator = sp.getActivatingPlayer();

View File

@@ -8,6 +8,7 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils;
import forge.FThreads;
import forge.ai.ComputerUtilMana;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.card.mana.ManaCostShard;
@@ -109,7 +110,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
boolean canUseColorless = manaCost.isAnyPartPayableWith((byte)0);
List<SpellAbility> abilities = new ArrayList<SpellAbility>();
// you can't remove unneeded abilities inside a for(am:abilities) loop :(
// you can't remove unneeded abilities inside a for (am:abilities) loop :(
final String typeRes = manaCost.getSourceRestriction();
if (StringUtils.isNotBlank(typeRes) && !card.isType(typeRes)) {
@@ -193,7 +194,6 @@ public abstract class InputPayMana extends InputSyncronizedBase {
game.getAction().invoke(proc);
}
/**
* <p>
* canMake. color is like "G", returns "Green".
@@ -272,16 +272,52 @@ public abstract class InputPayMana extends InputSyncronizedBase {
return bPaid;
}
protected boolean supportAutoPay() {
return true;
}
/** {@inheritDoc} */
@Override
protected void onOk() {
if (supportAutoPay()) {
//use AI utility to automatically pay mana cost if possible
ComputerUtilMana.payManaCost(manaCost, saPaidFor, player);
this.showMessage();
}
}
protected void updateButtons() {
if (supportAutoPay()) {
ButtonUtil.setButtonText("Auto", "Cancel");
}
ButtonUtil.enableOnlyCancel();
}
protected final void updateMessage() {
if (supportAutoPay() && ComputerUtilMana.canPayManaCost(manaCost, saPaidFor, player)) {
ButtonUtil.enableAllFocusOk(); //enabled Auto button if mana cost can be paid
}
showMessage(getMessage());
}
/** {@inheritDoc} */
@Override
protected final void onStop() {
if (supportAutoPay()) {
ButtonUtil.reset();
}
}
/** {@inheritDoc} */
@Override
public void showMessage() {
if (isFinished()) { return; }
ButtonUtil.enableOnlyCancel();
updateButtons();
onStateChanged();
}
protected void onStateChanged() {
if(isAlreadyPaid()) {
if (isAlreadyPaid()) {
done();
stop();
}
@@ -297,11 +333,11 @@ public abstract class InputPayMana extends InputSyncronizedBase {
protected void onManaAbilityPaid() {} // some inputs overload it
protected abstract void done();
protected abstract void updateMessage();
protected abstract String getMessage();
@Override
public String toString() {
return String.format("PayManaBase %s left", manaCost.toString() );
return String.format("PayManaBase %s left", manaCost.toString());
}
public boolean isPaid() { return bPaid; }

View File

@@ -102,11 +102,9 @@ public class InputPayManaExecuteCommands extends InputPayMana {
this.stop();
}
/* (non-Javadoc)
* @see forge.control.input.InputPayManaBase#updateMessage()
*/
/** {@inheritDoc} */
@Override
protected void updateMessage() {
protected String getMessage() {
final StringBuilder msg = new StringBuilder(this.message + "Pay Mana Cost: " + this.manaCost);
if (this.phyLifeToLose > 0) {
msg.append(" (");
@@ -117,6 +115,6 @@ public class InputPayManaExecuteCommands extends InputPayMana {
if (this.manaCost.containsPhyrexianMana()) {
msg.append("\n(Click on your life total to pay life for phyrexian mana.)");
}
showMessage(msg.toString());
return msg.toString();
}
}

View File

@@ -6,7 +6,6 @@ import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
public class InputPayManaOfCostPayment extends InputPayMana {
public InputPayManaOfCostPayment(ManaCostBeingPaid cost, SpellAbility spellAbility) {
super(spellAbility);
manaCost = cost;
@@ -39,7 +38,8 @@ public class InputPayManaOfCostPayment extends InputPayMana {
stop();
}
protected void updateMessage() {
@Override
protected String getMessage() {
final String displayMana = manaCost.toString(false);
final StringBuilder msg = new StringBuilder("Pay Mana Cost: " + displayMana);
@@ -53,6 +53,6 @@ public class InputPayManaOfCostPayment extends InputPayMana {
msg.append("\n(Click on your life total to pay life for phyrexian mana.)");
}
showMessage(msg.toString());
return msg.toString();
}
}

View File

@@ -22,7 +22,6 @@ import forge.game.card.Card;
import forge.game.mana.ManaCostBeingPaid;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.view.ButtonUtil;
//pays the cost of a card played from the player's hand
//the card is removed from the players hand if the cost is paid
@@ -102,7 +101,7 @@ public class InputPayManaSimple extends InputPayMana {
public final void showMessage() {
if (isFinished()) { return; }
ButtonUtil.enableOnlyCancel();
updateButtons();
if (this.manaCost.isPaid() && !new ManaCostBeingPaid(this.originalManaCost).isPaid()) {
this.done();
@@ -117,7 +116,7 @@ public class InputPayManaSimple extends InputPayMana {
* @see forge.control.input.InputPayManaBase#updateMessage()
*/
@Override
protected void updateMessage() {
protected String getMessage() {
final StringBuilder msg = new StringBuilder("Pay Mana Cost: " + this.manaCost.toString());
if (this.phyLifeToLose > 0) {
msg.append(" (");
@@ -130,6 +129,6 @@ public class InputPayManaSimple extends InputPayMana {
}
// has its own variant of checkIfPaid
showMessage(msg.toString());
return msg.toString();
}
}

View File

@@ -55,6 +55,11 @@ public class InputPayManaX extends InputPayMana {
return !canceled && (xPaid > 0 || xCanBe0);
}
@Override
protected boolean supportAutoPay() {
return false;
}
@Override
public void showMessage() {
if (isFinished()) { return; }
@@ -63,7 +68,7 @@ public class InputPayManaX extends InputPayMana {
}
@Override
protected void updateMessage() {
protected String getMessage() {
StringBuilder msg = new StringBuilder("Pay X Mana Cost for ");
msg.append(saPaidFor.getSourceCard().getName()).append("\n").append(this.xPaid);
msg.append(" Paid so far.");
@@ -79,7 +84,7 @@ public class InputPayManaX extends InputPayMana {
ButtonUtil.enableAllFocusOk();
}
showMessage(msg.toString());
return msg.toString();
}
@Override

View File

@@ -6,14 +6,14 @@ import forge.FThreads;
import forge.Singletons;
import forge.error.BugReporter;
public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized {
public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized {
private static final long serialVersionUID = 8756177361251703052L;
private final CountDownLatch cdlDone;
public InputSyncronizedBase() {
cdlDone = new CountDownLatch(1);
}
public void awaitLatchRelease() {
FThreads.assertExecutedByEdt(false);
try{
@@ -22,17 +22,26 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn
BugReporter.reportException(e);
}
}
public final void relaseLatchWhenGameIsOver() {
cdlDone.countDown();
}
protected final void stop() {
// ensure input won't accept any user actions.
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { setFinished(); } });
// thread irrelevant
protected final void stop() {
onStop();
// ensure input won't accept any user actions.
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
setFinished();
}
});
// thread irrelevant
Singletons.getControl().getInputQueue().removeInput(InputSyncronizedBase.this);
cdlDone.countDown();
}
protected void onStop() { }
}

View File

@@ -4,7 +4,6 @@ import java.util.EnumMap;
import java.util.Map;
/**
* TODO: Write javadoc for this type.
*
@@ -12,7 +11,6 @@ import java.util.Map;
public class EnumMapToAmount<T extends Enum<T>> extends EnumMap<T, Integer> implements MapToAmount<T> {
private static final long serialVersionUID = -4749796492075359368L;
public EnumMapToAmount(Class<T> keyType) {
super(keyType);
}
@@ -32,15 +30,17 @@ public class EnumMapToAmount<T extends Enum<T>> extends EnumMap<T, Integer> impl
@Override
public void add(T item, int amount) {
if (amount <= 0) return; // throw an exception maybe?
if (amount <= 0) { return; } // throw an exception maybe?
Integer cur = get(item);
int newVal = cur == null ? amount : amount + cur.intValue();
put(item, Integer.valueOf(newVal));
}
@Override
public void addAll(Iterable<T> item) {
for(T i : item) add(i, 1);
public void addAll(Iterable<T> items) {
for (T i : items) {
add(i, 1);
}
}
@Override
@@ -48,39 +48,39 @@ public class EnumMapToAmount<T extends Enum<T>> extends EnumMap<T, Integer> impl
return substract(item, 1);
}
@Override
public boolean substract(T item, int amount) {
Integer cur = get(item);
if( cur == null ) return false;
if (cur == null) { return false; }
int newVal = cur.intValue() - amount;
if(newVal > 0)
if (newVal > 0) {
put(item, Integer.valueOf(newVal));
else
}
else {
remove(item);
}
return true;
}
@Override
public void substractAll(Iterable<T> item) {
for(T i : item) substract(i);
public void substractAll(Iterable<T> items) {
for (T i : items) {
substract(i);
}
}
@Override
public int countAll() {
int c = 0;
for(java.util.Map.Entry<T, Integer> kv : this.entrySet()) {
for (java.util.Map.Entry<T, Integer> kv : this.entrySet()) {
c += kv.getValue().intValue();
}
return c;
}
@Override
public int count(T item) {
Integer cur = get(item);
return cur == null ? 0 : cur.intValue();
}
}

View File

@@ -9,10 +9,10 @@ import java.util.Map;
public interface MapToAmount<K> extends Map<K, Integer> {
void add(K item);
void add(K item, int amount);
void addAll(Iterable<K> item);
void addAll(Iterable<K> items);
boolean substract(K item);
boolean substract(K item, int amount);
void substractAll(Iterable<K> item);
void substractAll(Iterable<K> items);
int countAll();
int count(K item); // just unboxes and returns zero instead of null
}

View File

@@ -86,34 +86,33 @@ public abstract class CardPanelContainer extends JPanel {
* @param scrollPane
* a {@link javax.swing.JScrollPane} object.
*/
public CardPanelContainer(final JScrollPane scrollPane) {
public CardPanelContainer(final JScrollPane scrollPane) {
this.scrollPane = scrollPane;
this.setOpaque(true);
setupMouseListeners();
this.setOpaque(true);
setupMouseListeners();
}
private void setupMouseListeners() {
private void setupMouseListeners() {
final MouseMotionListener mml = setupMotionMouseListener();
setupMouseListener(mml);
setupMouseWheelListener();
setupMouseWheelListener();
}
private void setupMouseWheelListener() {
this.addMouseWheelListener(new MouseWheelListener() {
this.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
final CardPanel hitPanel = CardPanelContainer.this.getCardPanel(e.getX(), e.getY());
final CardPanel hitPanel = CardPanelContainer.this.getCardPanel(e.getX(), e.getY());
if (hitPanel != null) {
if (e.getWheelRotation() < 0) {
if (e.getWheelRotation() < 0) {
CardZoomer.SINGLETON_INSTANCE.doMouseWheelZoom(hitPanel.getCard());
}
}
}
});
}
});
}
private void setupMouseListener(final MouseMotionListener mml) {
this.addMouseListener(new MouseAdapter() {
private final boolean[] buttonsDown = new boolean[4];
@@ -181,13 +180,10 @@ public abstract class CardPanelContainer extends JPanel {
CardPanelContainer.this.mouseOutPanel(evt);
}
});
}
private MouseMotionListener setupMotionMouseListener() {
private MouseMotionListener setupMotionMouseListener() {
final MouseMotionListener mml = new MouseMotionListener() {
@Override
public void mouseDragged(final MouseEvent evt) {
if (CardZoomer.SINGLETON_INSTANCE.isZoomerOpen() || !SwingUtilities.isLeftMouseButton(evt)) {
@@ -229,7 +225,7 @@ public abstract class CardPanelContainer extends JPanel {
@Override
public void mouseMoved(final MouseEvent evt) {
final CardPanel hitPanel = CardPanelContainer.this.getCardPanel(evt.getX(), evt.getY());
final CardPanel hitPanel = CardPanelContainer.this.getCardPanel(evt.getX(), evt.getY());
if (CardPanelContainer.this.hoveredPanel == hitPanel) { // no big change
return;
@@ -246,7 +242,7 @@ public abstract class CardPanelContainer extends JPanel {
CardPanelContainer.this.hoveredPanel.setSelected(true);
CardPanelContainer.this.mouseOver(hitPanel, evt);
}
// System.err.format("%d %d over %s%n", evt.getX(), evt.getY(), hitPanel == null ? null : hitPanel.getCard().getName());
}
};
@@ -348,8 +344,6 @@ public abstract class CardPanelContainer extends JPanel {
CardPanelContainer.this.remove(fromPanel);
CardPanelContainer.this.invalidate();
CardPanelContainer.this.repaint();
}
/**
@@ -590,12 +584,12 @@ public abstract class CardPanelContainer extends JPanel {
// the already-hovered card, though, since we cannot tell the difference between that and clicking
// on the hovered card when the app already has focus.
CardPanel p = getCardPanel(e.getX(), e.getY());
// if cursor has jumped, for example via the above alt-tabbing example, fix the card hover highlight
if (null != hoveredPanel && p != hoveredPanel) {
mouseOut(hoveredPanel, e);
}
return (null == p || p != hoveredPanel) ? null : p.getGameCard();
}