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);
}
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) {
pool.clear();
model.clear();
@@ -560,6 +570,18 @@ public abstract class ItemManager<T extends InventoryItem> extends FContainer im
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() {
pool.clear();
model.clear();

View File

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

View File

@@ -1,8 +1,10 @@
package forge.screens.planarconquest;
import java.util.Collection;
import java.util.Map.Entry;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import forge.FThreads;
import forge.assets.FImage;
@@ -34,12 +36,62 @@ import forge.toolbox.FEvent.FEventHandler;
public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionScreen> {
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 btnExileMultiple = add(new FLabel.ButtonBuilder().font(ConquestAEtherScreen.LABEL_FONT).parseSymbols().build());
public ConquestCollectionScreen() {
super("", ConquestMenu.getMenu(), new CollectionTab[] {
new CollectionTab("Collection", FSkinImage.SPELLBOOK),
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
@@ -83,6 +135,38 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
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() {
return (CollectionTab)tabPages[0];
}
@@ -104,6 +188,9 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
lblInfo.setBounds(x + labelWidth, y, w - labelWidth, labelHeight);
y += labelHeight;
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> {
@@ -125,7 +212,15 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
protected void doLayout(float width, float 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 {
public CollectionManager(String caption0) {
super(false);
@@ -143,7 +238,7 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
if (model.retrieveCardFromExile(card, cost)) {
if (model.retrieveCardsFromExile(ImmutableList.of(card), cost)) {
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
@@ -167,7 +262,7 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
if (model.exileCard(card, value)) {
if (model.exileCards(ImmutableList.of(card), value)) {
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
@@ -187,6 +282,14 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
menu.addItem(item);
}
});
setSelectionChangedHandler(new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
if (getMultiSelectMode()) {
parentScreen.updateExileButtonCaption();
}
}
});
}
@Override
@@ -199,8 +302,14 @@ public class ConquestCollectionScreen extends TabPageScreen<ConquestCollectionSc
@Override
protected void onCardLongPress(int index, Entry<PaperCard, Integer> value, float x, float y) {
toggleMultiSelectMode(index);
//hide tabs and show Exile/Retrieve button while in multi-select mode
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.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -256,34 +257,51 @@ public final class ConquestData {
return exiledCards;
}
public boolean exileCard(PaperCard card, int value) {
final String title = "Exile Card";
if (planeswalker == card) {
SOptionPane.showMessageDialog("Current planeswalker cannot be exiled.", title, SOptionPane.INFORMATION_ICON);
return false;
}
String commandersUsingCard = "";
ConquestCommander commanderBeingExiled = null;
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;
public boolean exileCards(Collection<PaperCard> cards, int value) {
int count = cards.size();
if (count == 0) { return false; }
String title = count == 1 ? "Exile Card" : "Exile " + count + " Cards";
String cardStr = (count == 1 ? "card" : "cards");
List<ConquestCommander> commandersBeingExiled = null;
String message = "Exile the following " + cardStr + " to receive {AE}" + value + "?\n";
for (PaperCard card : cards) {
if (planeswalker == card) {
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);
return false;
}
if (SOptionPane.showConfirmDialog("Exile the following card to receive {AE}" + value + "?\n\n" + card.getName(), title, "OK", "Cancel")) {
if (exiledCards.add(card)) {
if (commanderBeingExiled != null) {
commanders.remove(commanderBeingExiled);
if (SOptionPane.showConfirmDialog(message, title, "OK", "Cancel")) {
if (exiledCards.addAll(cards)) {
if (commandersBeingExiled != null) {
commanders.removeAll(commandersBeingExiled);
}
rewardAEtherShards(value);
saveData();
@@ -293,16 +311,27 @@ public final class ConquestData {
return false;
}
public boolean retrieveCardFromExile(PaperCard card, int cost) {
final String title = "Retrieve Card";
public boolean retrieveCardsFromExile(Collection<PaperCard> cards, int cost) {
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) {
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;
}
if (SOptionPane.showConfirmDialog("Spend {AE}" + cost + " to retrieve the following card from exile?\n\n" + card.getName(), title, "OK", "Cancel")) {
if (exiledCards.remove(card)) {
if (card.getRules().canBeCommander()) { //add back commander for card if needed
commanders.add(new ConquestCommander(card));
String message = "Spend {AE}" + cost + " to retrieve the following " + cardStr + " from exile?\n";
for (PaperCard card : cards) {
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);
saveData();