From ca7b1309002181bf087a7eae48695e8174428a25 Mon Sep 17 00:00:00 2001 From: "Jamin W. Collins" Date: Fri, 23 Nov 2018 09:21:16 -0700 Subject: [PATCH 1/3] stop passing manaCost around, it's a class attribute Signed-off-by: Jamin W. Collins --- .../src/main/java/forge/match/input/InputPayMana.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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..07acf233a6a 100644 --- a/forge-gui/src/main/java/forge/match/input/InputPayMana.java +++ b/forge-gui/src/main/java/forge/match/input/InputPayMana.java @@ -105,7 +105,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 +114,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 +165,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; From c9c95db7162bd21bf87d7876e192b5dde41a6b4d Mon Sep 17 00:00:00 2001 From: "Jamin W. Collins" Date: Fri, 23 Nov 2018 09:29:15 -0700 Subject: [PATCH 2/3] use floating dialog for mana payment during spell cast Signed-off-by: Jamin W. Collins --- .../java/forge/match/input/InputPayMana.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) 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 07acf233a6a..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 @@ -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; } From 74ae604fe7c573f89bd6df62a95ad05e3f03b328 Mon Sep 17 00:00:00 2001 From: "Jamin W. Collins" Date: Fri, 23 Nov 2018 09:37:53 -0700 Subject: [PATCH 3/3] use nested menus for folder filter The existing folder filter UI can easily fill a users screen, listing one full path per line. With this change, only one level of directories are shown for each menu level. Signed-off-by: Jamin W. Collins --- .../java/forge/itemmanager/DeckManager.java | 67 ++++++++++++++++--- 1 file changed, 56 insertions(+), 11 deletions(-) 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);