Support exiling and retrieving multiple for Planar Conquest

This commit is contained in:
drdev
2016-04-07 21:29:02 +00:00
parent 8f05205a6a
commit d6c0861663
4 changed files with 204 additions and 41 deletions

View File

@@ -532,6 +532,16 @@ public abstract class ItemManager<T extends InventoryItem> extends FContainer im
updateView(false, items); updateView(false, items);
} }
public void addItemsFlat(Iterable<T> itemsToAdd) {
pool.addAllFlat(itemsToAdd);
if (isUnfiltered()) {
for (T item : itemsToAdd) {
model.addItem(item, 1);
}
}
updateView(false, itemsToAdd);
}
public void setItems(Iterable<Entry<T, Integer>> items) { public void setItems(Iterable<Entry<T, Integer>> items) {
pool.clear(); pool.clear();
model.clear(); model.clear();
@@ -560,6 +570,18 @@ public abstract class ItemManager<T extends InventoryItem> extends FContainer im
updateView(false, itemsToSelect); updateView(false, itemsToSelect);
} }
public void removeItemsFlat(Iterable<T> itemsToRemove) {
final Iterable<T> itemsToSelect = currentView == listView ? getSelectedItems() : null;
pool.removeAllFlat(itemsToRemove);
if (isUnfiltered()) {
for (T item : itemsToRemove) {
model.removeItem(item, 1);
}
}
updateView(false, itemsToSelect);
}
public void removeAllItems() { public void removeAllItems() {
pool.clear(); pool.clear();
model.clear(); model.clear();

View File

@@ -120,17 +120,21 @@ public abstract class ItemView<T extends InventoryItem> {
protected abstract void onRefresh(); protected abstract void onRefresh();
protected void fixSelection(final Iterable<T> itemsToSelect, final int backupIndexToSelect, final float scrollValueToRestore) { protected void fixSelection(final Iterable<T> itemsToSelect, final int backupIndexToSelect, final float scrollValueToRestore) {
if (itemsToSelect == null) { if (itemsToSelect == null) {
if (maxSelections <= 1 || minSelections > 0) { if (itemManager.getMultiSelectMode()) { //if in multi-select mode, clear selection
setSelectedIndex(0, false); //select first item if no items to select
}
else { //if in multi-select mode, clear selection instead
setSelectedIndex(-1, false); setSelectedIndex(-1, false);
} }
else { //otherwise select first item if no items to select
setSelectedIndex(0, false);
}
setScrollValue(0); //ensure scrolled to top setScrollValue(0); //ensure scrolled to top
} }
else { else {
if (!setSelectedItems(itemsToSelect)) { if (!setSelectedItems(itemsToSelect)) {
setSelectedIndex(backupIndexToSelect); setSelectedIndex(backupIndexToSelect);
if (itemManager.getMultiSelectMode()) { //in multi-select mode, clear selection after scrolling into view
setSelectedIndex(-1, false);
}
} }
} }
} }
@@ -245,8 +249,7 @@ public abstract class ItemView<T extends InventoryItem> {
} }
protected void onSelectionChange() { protected void onSelectionChange() {
final int index = getSelectedIndex(); if (getSelectedIndex() != -1 || itemManager.getMultiSelectMode()) {
if (index != -1) {
if (itemManager.getSelectionChangedHandler() != null) { if (itemManager.getSelectionChangedHandler() != null) {
itemManager.getSelectionChangedHandler().handleEvent(new FEvent(itemManager, FEventType.CHANGE)); itemManager.getSelectionChangedHandler().handleEvent(new FEvent(itemManager, FEventType.CHANGE));
} }

View File

@@ -1,8 +1,10 @@
package forge.screens.planarconquest; package forge.screens.planarconquest;
import java.util.Collection;
import java.util.Map.Entry; import java.util.Map.Entry;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import forge.FThreads; import forge.FThreads;
import forge.assets.FImage; import forge.assets.FImage;
@@ -34,12 +36,62 @@ import forge.toolbox.FEvent.FEventHandler;
public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionScreen> { public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionScreen> {
private final FLabel lblShards = add(new FLabel.Builder().font(ConquestAEtherScreen.LABEL_FONT).parseSymbols().build()); private final FLabel lblShards = add(new FLabel.Builder().font(ConquestAEtherScreen.LABEL_FONT).parseSymbols().build());
private final FLabel lblInfo = add(new FLabel.Builder().font(FSkinFont.get(11)).build()); private final FLabel lblInfo = add(new FLabel.Builder().font(FSkinFont.get(11)).build());
private final FLabel btnExileMultiple = add(new FLabel.ButtonBuilder().font(ConquestAEtherScreen.LABEL_FONT).parseSymbols().build());
public ConquestCollectionScreen() { public ConquestCollectionScreen() {
super("", ConquestMenu.getMenu(), new CollectionTab[] { super("", ConquestMenu.getMenu(), new CollectionTab[] {
new CollectionTab("Collection", FSkinImage.SPELLBOOK), new CollectionTab("Collection", FSkinImage.SPELLBOOK),
new CollectionTab("Exile", FSkinImage.EXILE) new CollectionTab("Exile", FSkinImage.EXILE)
}); });
btnExileMultiple.setVisible(false); //hide unless in multi-select mode
btnExileMultiple.setCommand(new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
final ConquestData model = FModel.getConquest().getModel();
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
if (getSelectedPage() == tabPages[0]) {
int value = 0;
final Collection<PaperCard> cards = getCollectionTab().list.getSelectedItems();
for (PaperCard card : cards) {
value += ConquestUtil.getShardValue(card, CQPref.AETHER_BASE_EXILE_VALUE);
}
if (model.exileCards(cards, value)) {
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
updateShards();
getCollectionTab().list.removeItemsFlat(cards);
getExileTab().list.addItemsFlat(cards);
updateTabCaptions();
}
});
}
}
else {
int cost = 0;
final Collection<PaperCard> cards = getExileTab().list.getSelectedItems();
for (PaperCard card : cards) {
cost += ConquestUtil.getShardValue(card, CQPref.AETHER_BASE_RETRIEVE_COST);
}
if (model.retrieveCardsFromExile(cards, cost)) {
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
updateShards();
getCollectionTab().list.addItemsFlat(cards);
getExileTab().list.removeItemsFlat(cards);
updateTabCaptions();
}
});
}
}
}
});
}
});
} }
@Override @Override
@@ -83,6 +135,38 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
getExileTab().updateCaption(); getExileTab().updateCaption();
} }
private void updateExileButtonCaption() {
String action;
CQPref baseValuePref;
Collection<PaperCard> cards;
if (getSelectedPage() == tabPages[0]) {
action = "Exile";
baseValuePref = CQPref.AETHER_BASE_EXILE_VALUE;
cards = getCollectionTab().list.getSelectedItems();
}
else {
action = "Retrieve";
baseValuePref = CQPref.AETHER_BASE_RETRIEVE_COST;
cards = getExileTab().list.getSelectedItems();
}
int count = cards.size();
String caption = action;
if (count > 0) {
if (count > 1) {
caption += " " + count + " cards";
}
int total = 0;
for (PaperCard card : cards) {
total += ConquestUtil.getShardValue(card, baseValuePref);
}
caption += " for {AE}" + total;
}
btnExileMultiple.setText(caption);
btnExileMultiple.setEnabled(count > 0);
}
private CollectionTab getCollectionTab() { private CollectionTab getCollectionTab() {
return (CollectionTab)tabPages[0]; return (CollectionTab)tabPages[0];
} }
@@ -104,6 +188,9 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
lblInfo.setBounds(x + labelWidth, y, w - labelWidth, labelHeight); lblInfo.setBounds(x + labelWidth, y, w - labelWidth, labelHeight);
y += labelHeight; y += labelHeight;
super.doLayout(y, width, height); super.doLayout(y, width, height);
float buttonHeight = tabHeader.getHeight() - 2 * ItemFilter.PADDING;
btnExileMultiple.setBounds(x, height - buttonHeight - ItemFilter.PADDING, w, buttonHeight);
} }
private static class CollectionTab extends TabPage<ConquestCollectionScreen> { private static class CollectionTab extends TabPage<ConquestCollectionScreen> {
@@ -125,7 +212,15 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
protected void doLayout(float width, float height) { protected void doLayout(float width, float height) {
list.setBounds(0, 0, width, height); list.setBounds(0, 0, width, height);
} }
@Override
public boolean fling(float velocityX, float velocityY) {
if (list.getMultiSelectMode()) {
return false; //prevent changing tabs while in multi-select mode
}
return super.fling(velocityX, velocityY);
}
private class CollectionManager extends CardManager { private class CollectionManager extends CardManager {
public CollectionManager(String caption0) { public CollectionManager(String caption0) {
super(false); super(false);
@@ -143,7 +238,7 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
FThreads.invokeInBackgroundThread(new Runnable() { FThreads.invokeInBackgroundThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (model.retrieveCardFromExile(card, cost)) { if (model.retrieveCardsFromExile(ImmutableList.of(card), cost)) {
FThreads.invokeInEdtLater(new Runnable() { FThreads.invokeInEdtLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -167,7 +262,7 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
FThreads.invokeInBackgroundThread(new Runnable() { FThreads.invokeInBackgroundThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (model.exileCard(card, value)) { if (model.exileCards(ImmutableList.of(card), value)) {
FThreads.invokeInEdtLater(new Runnable() { FThreads.invokeInEdtLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -187,6 +282,14 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
menu.addItem(item); menu.addItem(item);
} }
}); });
setSelectionChangedHandler(new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
if (getMultiSelectMode()) {
parentScreen.updateExileButtonCaption();
}
}
});
} }
@Override @Override
@@ -199,8 +302,14 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
@Override @Override
protected void onCardLongPress(int index, Entry<PaperCard, Integer> value, float x, float y) { protected void onCardLongPress(int index, Entry<PaperCard, Integer> value, float x, float y) {
toggleMultiSelectMode(index); toggleMultiSelectMode(index);
//hide tabs and show Exile/Retrieve button while in multi-select mode
boolean multiSelectMode = getMultiSelectMode(); boolean multiSelectMode = getMultiSelectMode();
if (multiSelectMode) {
parentScreen.updateExileButtonCaption();
}
parentScreen.btnExileMultiple.setVisible(multiSelectMode);
parentScreen.tabHeader.setVisible(!multiSelectMode);
} }
} }

View File

@@ -35,6 +35,7 @@ import forge.util.gui.SOptionPane;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -256,34 +257,51 @@ public final class ConquestData {
return exiledCards; return exiledCards;
} }
public boolean exileCard(PaperCard card, int value) { public boolean exileCards(Collection<PaperCard> cards, int value) {
final String title = "Exile Card"; int count = cards.size();
if (planeswalker == card) { if (count == 0) { return false; }
SOptionPane.showMessageDialog("Current planeswalker cannot be exiled.", title, SOptionPane.INFORMATION_ICON);
return false; String title = count == 1 ? "Exile Card" : "Exile " + count + " Cards";
} String cardStr = (count == 1 ? "card" : "cards");
String commandersUsingCard = "";
ConquestCommander commanderBeingExiled = null; List<ConquestCommander> commandersBeingExiled = null;
for (ConquestCommander commander : commanders) {
if (commander.getCard() == card) { String message = "Exile the following " + cardStr + " to receive {AE}" + value + "?\n";
if (!commander.getDeck().getMain().isEmpty()) { for (PaperCard card : cards) {
SOptionPane.showMessageDialog("Cannot exile a commander with a defined deck.", title, SOptionPane.INFORMATION_ICON); if (planeswalker == card) {
return false; SOptionPane.showMessageDialog("Current planeswalker cannot be exiled.", title, SOptionPane.INFORMATION_ICON);
return false;
}
String commandersUsingCard = "";
for (ConquestCommander commander : commanders) {
if (commander.getCard() == card) {
if (!commander.getDeck().getMain().isEmpty()) {
SOptionPane.showMessageDialog("Cannot exile a commander with a defined deck.", title, SOptionPane.INFORMATION_ICON);
return false;
}
if (commandersBeingExiled == null) {
commandersBeingExiled = new ArrayList<ConquestCommander>();
}
commandersBeingExiled.add(commander); //cache commander to make it easier to remove later
}
if (commander.getDeck().getMain().contains(card)) {
commandersUsingCard += "\n" + commander.getName();
} }
commanderBeingExiled = commander; //cache commander to make it easier to remove later
} }
if (commander.getDeck().getMain().contains(card)) {
commandersUsingCard += "\n" + commander.getName(); if (!commandersUsingCard.isEmpty()) {
SOptionPane.showMessageDialog(card.getName() + " is in use by the following commanders and cannot be exiled:\n" + commandersUsingCard, title, SOptionPane.INFORMATION_ICON);
return false;
} }
message += "\n" + card.getName();
} }
if (!commandersUsingCard.isEmpty()) {
SOptionPane.showMessageDialog("Card is in use by the following commanders and cannot be exiled:\n" + commandersUsingCard, title, SOptionPane.INFORMATION_ICON); if (SOptionPane.showConfirmDialog(message, title, "OK", "Cancel")) {
return false; if (exiledCards.addAll(cards)) {
} if (commandersBeingExiled != null) {
if (SOptionPane.showConfirmDialog("Exile the following card to receive {AE}" + value + "?\n\n" + card.getName(), title, "OK", "Cancel")) { commanders.removeAll(commandersBeingExiled);
if (exiledCards.add(card)) {
if (commanderBeingExiled != null) {
commanders.remove(commanderBeingExiled);
} }
rewardAEtherShards(value); rewardAEtherShards(value);
saveData(); saveData();
@@ -293,16 +311,27 @@ public final class ConquestData {
return false; return false;
} }
public boolean retrieveCardFromExile(PaperCard card, int cost) { public boolean retrieveCardsFromExile(Collection<PaperCard> cards, int cost) {
final String title = "Retrieve Card"; int count = cards.size();
if (count == 0) { return false; }
String title = count == 1 ? "Retrieve Card" : "Retrieve " + count + " Cards";
String cardStr = (count == 1 ? "card" : "cards");
if (aetherShards < cost) { if (aetherShards < cost) {
SOptionPane.showMessageDialog("Not enough shards to retrieve card.", title, SOptionPane.INFORMATION_ICON); SOptionPane.showMessageDialog("Not enough shards to retrieve " + cardStr + ".", title, SOptionPane.INFORMATION_ICON);
return false; return false;
} }
if (SOptionPane.showConfirmDialog("Spend {AE}" + cost + " to retrieve the following card from exile?\n\n" + card.getName(), title, "OK", "Cancel")) {
if (exiledCards.remove(card)) { String message = "Spend {AE}" + cost + " to retrieve the following " + cardStr + " from exile?\n";
if (card.getRules().canBeCommander()) { //add back commander for card if needed for (PaperCard card : cards) {
commanders.add(new ConquestCommander(card)); message += "\n" + card.getName();
}
if (SOptionPane.showConfirmDialog(message, title, "OK", "Cancel")) {
if (exiledCards.removeAll(cards)) {
for (PaperCard card : cards) {
if (card.getRules().canBeCommander()) { //add back commander for card if needed
commanders.add(new ConquestCommander(card));
}
} }
spendAEtherShards(cost); spendAEtherShards(cost);
saveData(); saveData();