diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java b/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java index 9843f97c683..2bc3df3459f 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java @@ -147,27 +147,72 @@ public final class DeckManager extends ItemManager implements IHasGam return new DeckSearchFilter(this); } + private Map buildHierarchy(String path) { + if (path.startsWith("/")) { + path = path.substring(1); + } + Map hierarchy = new HashMap(); + String[] components = path.split("/", 2); + Map value = new HashMap(); + if (components.length > 1) { + value = buildHierarchy(components[1]); + } + hierarchy.put("/" + components[0], value); + return hierarchy; + } + + // borrowed from: https://stackoverflow.com/a/46052477 + private void merge(Map mapLeft, Map mapRight) { + // go over all the keys of the right map + for (String key : mapRight.keySet()) { + // if the left map already has this key, merge the maps that are behind that key + if (mapLeft.containsKey(key)) { + merge(mapLeft.get(key), mapRight.get(key)); + } else { + // otherwise just add the map under that key + mapLeft.put(key, mapRight.get(key)); + } + } + } + + private void buildNestedMenu(Map tree, JMenu menu, String parentPath) { + if (tree.size() > 0) { + for (final Object key : tree.keySet()) { + String fullPath = key.toString(); + if (parentPath != null) { + fullPath = parentPath + key.toString(); + } + String finalFullPath = fullPath; + GuiUtils.addMenuItem(menu, key.toString(), null, new Runnable() { + @Override + public void run() { + addFilter(new DeckFolderFilter(DeckManager.this, finalFullPath)); + } + }, true); + Map value = (Map) tree.get(key); + if (value.size() > 0) { + final JMenu submenu = GuiUtils.createMenu(key.toString()); + buildNestedMenu(value, submenu, finalFullPath); + menu.add(submenu); + } + } + } + } + @Override protected void buildAddFilterMenu(final JMenu menu) { GuiUtils.addSeparator(menu); //separate from current search item - final SortedSet folders = new TreeSet(); + Map hierarchy = new HashMap(); for (final Entry deckEntry : getPool()) { final String path = deckEntry.getKey().getPath(); if (StringUtils.isNotEmpty(path)) { //don't include root folder as option - folders.add(path); + merge(hierarchy, buildHierarchy(path)); } } final JMenu folder = GuiUtils.createMenu("Folder"); - if (folders.size() > 0) { - for (final String f : folders) { - GuiUtils.addMenuItem(folder, f, null, new Runnable() { - @Override - public void run() { - addFilter(new DeckFolderFilter(DeckManager.this, f)); - } - }, true); - } + if (hierarchy.size() > 0) { + buildNestedMenu(hierarchy, folder, null); } else { folder.setEnabled(false); diff --git a/forge-gui/src/main/java/forge/match/input/InputPayMana.java b/forge-gui/src/main/java/forge/match/input/InputPayMana.java index 6fcaca649eb..c0cdd42e0fc 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPayMana.java +++ b/forge-gui/src/main/java/forge/match/input/InputPayMana.java @@ -71,20 +71,21 @@ public abstract class InputPayMana extends InputSyncronizedBase { @Override protected boolean onCardSelected(final Card card, final List otherCardsToSelect, final ITriggerEvent triggerEvent) { - if (otherCardsToSelect != null) { - for (Card c : otherCardsToSelect) { - for (SpellAbility sa : c.getManaAbilities()) { - if (sa.canPlay()) { - delaySelectCards.add(c); - break; - } - } + if (card.getManaAbilities().size() == 1) { + activateManaAbility(card, card.getManaAbilities().get(0)); + } else { + SpellAbilityView spellAbilityView; + HashMap spellAbilityViewMap = new HashMap<>(); + for (SpellAbility sa : card.getManaAbilities()) { + spellAbilityViewMap.put(sa.getView(), sa); + } + List choices = new ArrayList<>(spellAbilityViewMap.keySet()); + spellAbilityView = getController().getGui().getAbilityToPlay(card.getView(), choices, triggerEvent); + if (spellAbilityView != null) { + activateManaAbility(card, spellAbilityViewMap.get(spellAbilityView)); } } - if (!card.getManaAbilities().isEmpty() && activateManaAbility(card, manaCost)) { - return true; - } - return activateDelayedCard(); + return true; } @Override @@ -105,7 +106,7 @@ public abstract class InputPayMana extends InputSyncronizedBase { delaySelectCards.clear(); //clear delayed cards if mana cost already paid return false; } - if (activateManaAbility(delaySelectCards.poll(), manaCost)) { + if (activateManaAbility(delaySelectCards.poll())) { return true; } return activateDelayedCard(); @@ -114,7 +115,7 @@ public abstract class InputPayMana extends InputSyncronizedBase { @Override public boolean selectAbility(final SpellAbility ab) { if (ab != null && ab.isManaAbility()) { - return activateManaAbility(ab.getHostCard(), manaCost, ab); + return activateManaAbility(ab.getHostCard(), ab); } return false; } @@ -165,10 +166,10 @@ public abstract class InputPayMana extends InputSyncronizedBase { } } - protected boolean activateManaAbility(final Card card, ManaCostBeingPaid manaCost) { - return activateManaAbility(card, manaCost, null); + protected boolean activateManaAbility(final Card card) { + return activateManaAbility(card, null); } - protected boolean activateManaAbility(final Card card, ManaCostBeingPaid manaCost, SpellAbility chosenAbility) { + protected boolean activateManaAbility(final Card card, SpellAbility chosenAbility) { if (locked) { System.err.print("Should wait till previous call to playAbility finishes."); return false; @@ -231,7 +232,7 @@ public abstract class InputPayMana extends InputSyncronizedBase { } } - if (abilitiesMap.isEmpty() || (chosenAbility != null && !abilitiesMap.containsKey(chosenAbility))) { + if (abilitiesMap.isEmpty() || (chosenAbility != null && !abilitiesMap.containsKey(chosenAbility.getView()))) { return false; }