From d56cecdba46b25f41fdfa00c5ba155f670315e94 Mon Sep 17 00:00:00 2001 From: drdev Date: Mon, 16 Dec 2013 09:10:40 +0000 Subject: [PATCH] Integrate filters into ItemManager --- .gitattributes | 1 + .../src/main/java/forge/util/Aggregates.java | 7 + .../src/main/java/forge/util/TextUtil.java | 27 +- .../forge/gui/deckeditor/CDeckEditorUI.java | 7 +- .../deckeditor/controllers/ACEditorBase.java | 78 +++ .../deckeditor/controllers/CCardCatalog.java | 541 ------------------ .../deckeditor/controllers/CCurrentDeck.java | 66 +-- .../gui/deckeditor/controllers/CDeckgen.java | 30 +- .../controllers/CEditorCommander.java | 21 +- .../controllers/CEditorConstructed.java | 16 +- .../controllers/CEditorDraftingProcess.java | 24 +- .../controllers/CEditorLimited.java | 6 +- .../controllers/CEditorPreferences.java | 14 - .../deckeditor/controllers/CEditorQuest.java | 11 +- .../controllers/CEditorQuestCardShop.java | 74 +-- .../controllers/CEditorVariant.java | 8 +- .../controllers/CProbabilities.java | 9 +- .../gui/deckeditor/views/VCardCatalog.java | 226 +------- .../gui/deckeditor/views/VCurrentDeck.java | 177 +----- .../forge/gui/deckeditor/views/VDeckgen.java | 18 +- .../deckeditor/views/VEditorPreferences.java | 9 - .../gui/deckeditor/views/VProbabilities.java | 10 +- .../java/forge/gui/toolbox/FComboBox.java | 3 - .../forge/gui/toolbox/FComboBoxWrapper.java | 5 + .../main/java/forge/gui/toolbox/FLabel.java | 23 +- .../main/java/forge/gui/toolbox/FSkin.java | 4 + .../java/forge/gui/toolbox/FTextField.java | 64 ++- .../java/forge/gui/toolbox/LayoutHelper.java | 41 +- .../gui/toolbox/itemmanager/CardManager.java | 18 +- .../itemmanager/InventoryItemManager.java | 11 +- .../gui/toolbox/itemmanager/ItemManager.java | 247 ++++++-- .../gui/toolbox/itemmanager/SFilterUtil.java | 40 +- .../toolbox/itemmanager/SItemManagerIO.java | 1 - .../toolbox/itemmanager/SItemManagerUtil.java | 42 +- .../itemmanager/filters/CardCMCFilter.java | 22 +- .../itemmanager/filters/CardColorFilter.java | 82 ++- .../itemmanager/filters/CardFormatFilter.java | 123 +++- .../itemmanager/filters/CardPowerFilter.java | 22 +- .../filters/CardQuestWorldFilter.java | 54 +- .../itemmanager/filters/CardSearchFilter.java | 104 +++- .../itemmanager/filters/CardSetFilter.java | 39 +- .../filters/CardToughnessFilter.java | 22 +- .../itemmanager/filters/CardTypeFilter.java | 45 +- .../itemmanager/filters/ItemFilter.java | 271 +++++++-- .../itemmanager/filters/ListLabelFilter.java | 66 ++- .../itemmanager/filters/StatTypeFilter.java | 89 +++ .../itemmanager/filters/TextSearchFilter.java | 89 ++- .../filters/ToggleButtonsFilter.java | 85 ++- .../itemmanager/filters/ValueRangeFilter.java | 111 +++- .../toolbox/itemmanager/table/ItemTable.java | 56 +- .../java/forge/gui/workshop/CWorkshopUI.java | 2 - .../controllers/CWorkshopCatalog.java | 520 +---------------- .../gui/workshop/views/VWorkshopCatalog.java | 180 +----- 53 files changed, 1653 insertions(+), 2208 deletions(-) create mode 100644 forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/StatTypeFilter.java diff --git a/.gitattributes b/.gitattributes index b10cd2ade3c..7d2e32a73cf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15482,6 +15482,7 @@ forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardToughnessFilte forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardTypeFilter.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ItemFilter.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ListLabelFilter.java -text +forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/StatTypeFilter.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/TextSearchFilter.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ToggleButtonsFilter.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ValueRangeFilter.java -text diff --git a/forge-core/src/main/java/forge/util/Aggregates.java b/forge-core/src/main/java/forge/util/Aggregates.java index ab025c89125..b5a21fc3e4d 100644 --- a/forge-core/src/main/java/forge/util/Aggregates.java +++ b/forge-core/src/main/java/forge/util/Aggregates.java @@ -123,6 +123,13 @@ public class Aggregates { return uniques.values(); } + public static final int uniqueCount(final Iterable source, final Function fnUniqueKey) { + final Map uniques = new Hashtable(); + for (final U c : source) { + uniques.put(fnUniqueKey.apply(c), c); + } + return uniques.size(); + } public static T itemWithMin(final Iterable source, final Function valueAccessor) { if (source == null) { return null; } diff --git a/forge-core/src/main/java/forge/util/TextUtil.java b/forge-core/src/main/java/forge/util/TextUtil.java index 8bd9cdc3b15..34f86365604 100644 --- a/forge-core/src/main/java/forge/util/TextUtil.java +++ b/forge-core/src/main/java/forge/util/TextUtil.java @@ -1,5 +1,6 @@ package forge.util; +import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -78,13 +79,13 @@ public class TextUtil { int len = input.length(); int start = 0; int idx = 1; - for (int iC = 0; iC < len; iC++ ) { + for (int iC = 0; iC < len; iC++) { char c = input.charAt(iC); - if( closePar > 0 && c == closePar && nPar > 0 ) { nPar--; } - else if( openPar > 0 && c == openPar ) nPar++; + if (closePar > 0 && c == closePar && nPar > 0) { nPar--; } + else if (openPar > 0 && c == openPar) nPar++; - if( c == delimiter && nPar == 0 && idx < maxEntries) { - if( iC > start || !skipEmpty ) { + if (c == delimiter && nPar == 0 && idx < maxEntries) { + if (iC > start || !skipEmpty) { result.add(input.subSequence(start, iC).toString()); idx++; } @@ -92,7 +93,7 @@ public class TextUtil { } } - if( len > start || !skipEmpty ) + if (len > start || !skipEmpty) result.add(input.subSequence(start, len).toString()); String[] toReturn = result.toArray(ArrayUtils.EMPTY_STRING_ARRAY); @@ -122,12 +123,20 @@ public class TextUtil { public static String buildFourColumnList(String firstLine, Iterable cAnteRemoved) { StringBuilder sb = new StringBuilder(firstLine); int i = 0; - for(PaperCard cp: cAnteRemoved) { - if ( i != 0 ) sb.append(", "); - if ( i % 4 == 0 ) sb.append("\n"); + for (PaperCard cp: cAnteRemoved) { + if (i != 0) { sb.append(", "); } + if (i % 4 == 0) { sb.append("\n"); } sb.append(cp); i++; } return sb.toString(); } + + public static boolean isPrintableChar(char c) { + Character.UnicodeBlock block = Character.UnicodeBlock.of(c); + return (!Character.isISOControl(c)) && + c != KeyEvent.CHAR_UNDEFINED && + block != null && + block != Character.UnicodeBlock.SPECIALS; + } } diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/CDeckEditorUI.java b/forge-gui/src/main/java/forge/gui/deckeditor/CDeckEditorUI.java index 66755f3a02b..5cb8d6c049e 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/CDeckEditorUI.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/CDeckEditorUI.java @@ -53,7 +53,6 @@ import forge.Singletons; import forge.deck.DeckBase; import forge.gui.GuiUtils; import forge.gui.deckeditor.controllers.ACEditorBase; -import forge.gui.deckeditor.controllers.CCardCatalog; import forge.gui.deckeditor.controllers.CEditorConstructed; import forge.gui.deckeditor.controllers.CProbabilities; import forge.gui.deckeditor.controllers.CStatistics; @@ -238,7 +237,7 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), new Runnable() { @Override public void run() { - VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().requestFocusInWindow(); + VCardCatalog.SINGLETON_INSTANCE.getItemManager().focusSearch(); } }); } @@ -331,7 +330,7 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { } else if (KeyEvent.VK_F == e.getKeyCode()) { // let ctrl/cmd-F set focus to the text filter box if (e.isControlDown() || e.isMetaDown()) { - VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().requestFocusInWindow(); + VCardCatalog.SINGLETON_INSTANCE.getItemManager().focusSearch(); } } } @@ -438,7 +437,7 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { deckTable.setWantElasticColumns(wantElastic); catView.setWantUnique(wantUnique); deckView.setWantUnique(wantUnique); - CCardCatalog.SINGLETON_INSTANCE.applyCurrentFilter(); + catView.buildFilterPredicate(); } private class _FindAsYouType extends KeyAdapter { diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/ACEditorBase.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/ACEditorBase.java index bd0e3cdfd4d..6684a5c8654 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/ACEditorBase.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/ACEditorBase.java @@ -19,12 +19,16 @@ package forge.gui.deckeditor.controllers; import javax.swing.SwingUtilities; +import forge.Command; import forge.deck.DeckBase; +import forge.gui.deckeditor.CDeckEditorUI; import forge.gui.framework.DragCell; import forge.gui.framework.FScreen; import forge.gui.framework.ICDoc; import forge.gui.framework.IVDoc; import forge.gui.framework.SRearrangingUtil; +import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FSkin; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.InventoryItem; import forge.view.FView; @@ -63,6 +67,41 @@ public abstract class ACEditorBase catalogManager; private ItemManager deckManager; + + // card transfer buttons + private final FLabel btnAdd = new FLabel.Builder() + .fontSize(14) + .text("Add card") + .tooltip("Add selected card to current deck (or double click the row or hit the spacebar)") + .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS)) + .iconScaleAuto(false).hoverable().build(); + private final FLabel btnAdd4 = new FLabel.Builder() + .fontSize(14) + .text("Add 4 of card") + .tooltip("Add up to 4 of selected card to current deck") + .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS)) + .iconScaleAuto(false).hoverable().build(); + + private final FLabel btnRemove = new FLabel.Builder() + .fontSize(14) + .text("Remove card") + .tooltip("Remove selected card from current deck (or double click the row or hit the spacebar)") + .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS)) + .iconScaleAuto(false).hoverable().build(); + + private final FLabel btnRemove4 = new FLabel.Builder() + .fontSize(14) + .text("Remove 4 of card") + .tooltip("Remove up to 4 of selected card to current deck") + .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS)) + .iconScaleAuto(false).hoverable().build(); + + private final FLabel btnCycleSection = new FLabel.Builder() + .fontSize(14) + .text("Change Section") + .tooltip("Toggle between editing the deck and the sideboard/planar/scheme/vanguard parts of this deck") + .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT)) + .iconScaleAuto(false).hoverable().build(); protected ACEditorBase(FScreen screen0) { this.screen = screen0; @@ -128,8 +167,25 @@ public abstract class ACEditorBase itemManager) { this.deckManager = itemManager; + + btnRemove.setCommand(new Command() { + @Override + public void run() { + CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, 1); + } + }); + btnRemove4.setCommand(new Command() { + @Override + public void run() { + CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, 4); + } + }); + itemManager.getPnlButtons().add(btnRemove, "w 30%!, h 30px!, gapx 5"); + itemManager.getPnlButtons().add(btnRemove4, "w 30%!, h 30px!, gapx 5"); + itemManager.getPnlButtons().add(btnCycleSection, "w 30%!, h 30px!, gapx 5"); } /** @@ -146,8 +202,24 @@ public abstract class ACEditorBase itemManager) { this.catalogManager = itemManager; + + btnAdd.setCommand(new Command() { + @Override + public void run() { + CDeckEditorUI.SINGLETON_INSTANCE.addSelectedCards(false, 1); + } + }); + btnAdd4.setCommand(new Command() { + @Override + public void run() { + CDeckEditorUI.SINGLETON_INSTANCE.addSelectedCards(false, 4); + } + }); + itemManager.getPnlButtons().add(btnAdd, "w 30%!, h 30px!, h 30px!, gapx 5"); + itemManager.getPnlButtons().add(btnAdd4, "w 30%!, h 30px!, h 30px!, gapx 5"); } /** @@ -179,4 +251,10 @@ public abstract class ACEditorBase> activePredicates = new HashSet>(); - private final Set activeFormats = new HashSet(); - private final Set activeWorlds = new HashSet(); - private final Set activeRanges = EnumSet.noneOf(RangeTypes.class); - - private boolean disableFiltering = false; - private CCardCatalog() { } @@ -82,293 +30,7 @@ public enum CCardCatalog implements ICDoc { * @see forge.gui.framework.ICDoc#initialize() */ @Override - @SuppressWarnings("serial") public void initialize() { - // Add/remove buttons (refresh analysis on add) - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd().setCommand(new Command() { - @Override - public void run() { - CDeckEditorUI.SINGLETON_INSTANCE.addSelectedCards(false, 1); - } - }); - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setCommand(new Command() { - @Override - public void run() { - CDeckEditorUI.SINGLETON_INSTANCE.addSelectedCards(false, 4); - } - }); - - final Command updateFilterCommand = new Command() { - @Override - public void run() { - if (!disableFiltering) { - applyCurrentFilter(); - } - } - }; - - for (Map.Entry entry : VCardCatalog.SINGLETON_INSTANCE.getStatLabels().entrySet()) { - final FLabel statLabel = entry.getValue(); - statLabel.setCommand(updateFilterCommand); - - //hook so right-clicking a filter in a group toggles itself off and toggles on all other filters in group - final SItemManagerUtil.StatTypes st = entry.getKey(); - final int group = st.group; - if (group > 0) { - statLabel.setRightClickCommand(new Command() { - @SuppressWarnings("incomplete-switch") - @Override - public void run() { - if (!disableFiltering) { - disableFiltering = true; - - boolean foundSelected = false; - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - if (s.group == group && s != st) { - FLabel lbl = VCardCatalog.SINGLETON_INSTANCE.getItemManager().getStatLabel(s); - if (s == StatTypes.MULTICOLOR) { - switch (st) { - case WHITE: - case BLUE: - case BLACK: - case RED: - case GREEN: - //ensure multicolor filter selected after right-clicking a color filter - if (!lbl.getSelected()) { - lbl.setSelected(true); - } - continue; - } - } - if (lbl.getSelected()) { - foundSelected = true; - lbl.setSelected(false); - } - } - } - if (!statLabel.getSelected()) { - statLabel.setSelected(true); - } - else if (!foundSelected) { - //if statLabel only label in group selected, re-select all other labels in group - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - if (s.group == group && s != st) { - FLabel lbl = VCardCatalog.SINGLETON_INSTANCE.getItemManager().getStatLabel(s); - if (!lbl.getSelected()) { - lbl.setSelected(true); - } - } - } - } - - disableFiltering = false; - applyCurrentFilter(); - } - } - }); - } - } - - VCardCatalog.SINGLETON_INSTANCE.getStatLabels().get(SItemManagerUtil.StatTypes.TOTAL).setCommand(new Command() { - private boolean lastToggle = true; - - @Override - public void run() { - disableFiltering = true; - lastToggle = !lastToggle; - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - if (SItemManagerUtil.StatTypes.TOTAL != s) { - VCardCatalog.SINGLETON_INSTANCE.getItemManager().getStatLabel(s).setSelected(lastToggle); - } - } - disableFiltering = false; - applyCurrentFilter(); - } - }); - - // assemble add restriction menu - final Command addRestrictionCommand = new Command() { - @Override - public void run() { - JPopupMenu popup = new JPopupMenu("RestrictionPopupMenu"); - GuiUtils.addMenuItem(popup, "Current text search", - KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), - new Runnable() { - @Override - public void run() { - addRestriction(buildSearchRestriction(), null, null); - } - }, canSearch()); - JMenu fmt = new JMenu("Format"); - for (final GameFormat f : Singletons.getModel().getFormats()) { - GuiUtils.addMenuItem(fmt, f.getName(), null, new Runnable() { - @Override - public void run() { - addRestriction(buildFormatRestriction(f.toString(), f, true), activeFormats, f); - } - }, !isActive(activeFormats, f)); - } - popup.add(fmt); - GuiUtils.addMenuItem(popup, "Sets...", null, new Runnable() { - @Override - public void run() { - final DialogChooseSets dialog = new DialogChooseSets(null, null, true); - dialog.setOkCallback(new Runnable() { - @Override - public void run() { - List setCodes = dialog.getSelectedSets(); - - if (setCodes.isEmpty()) { - return; - } - - StringBuilder label = new StringBuilder("Sets:"); - boolean truncated = false; - for (String code : setCodes) - { - // don't let the full label get too long - if (32 > label.length()) { - label.append(" ").append(code).append(";"); - } else { - truncated = true; - break; - } - } - - // chop off last semicolons - label.delete(label.length() - 1, label.length()); - - if (truncated) { - label.append("..."); - } - - addRestriction(buildSetRestriction(label.toString(), setCodes, dialog.getWantReprints()), null, null); - } - }); - } - }); - JMenu range = new JMenu("Value range"); - for (final RangeTypes t : RangeTypes.values()) { - GuiUtils.addMenuItem(range, t.toLabelString() + " restriction", null, new Runnable() { - @Override - public void run() { - addRestriction(buildRangeRestriction(t), activeRanges, t); - } - }, !isActive(activeRanges, t)); - } - popup.add(range); - JMenu world = new JMenu("Quest world"); - for (final QuestWorld w : Singletons.getModel().getWorlds()) { - GameFormatQuest format = w.getFormat(); - if (null == format) { - // assumes that no world other than the main world will have a null format - format = Singletons.getModel().getQuest().getMainFormat(); - } - final GameFormatQuest f = format; - GuiUtils.addMenuItem(world, w.getName(), null, new Runnable() { - @Override - public void run() { - addRestriction(buildFormatRestriction(w.getName(), f, true), activeWorlds, w); - } - }, !isActive(activeWorlds, w) && null != f); - } - popup.add(world); - popup.show(VCardCatalog.SINGLETON_INSTANCE.getBtnAddRestriction(), 0, - VCardCatalog.SINGLETON_INSTANCE.getBtnAddRestriction().getHeight()); - } - }; - FLabel btnAddRestriction = VCardCatalog.SINGLETON_INSTANCE.getBtnAddRestriction(); - btnAddRestriction.setCommand(addRestrictionCommand); - btnAddRestriction.setRightClickCommand(addRestrictionCommand); //show menu on right-click too - - VCardCatalog.SINGLETON_INSTANCE.getCbSearchMode().addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent arg0) { - applyCurrentFilter(); - } - }); - - Runnable addSearchRestriction = new Runnable() { - @Override - public void run() { - if (canSearch()) { - addRestriction(buildSearchRestriction(), null, null); - } - } - }; - - // add search restriction on ctrl-enter from either the textbox or combobox - VCardCatalog.SINGLETON_INSTANCE.getCbSearchMode().addKeyListener(new _OnCtrlEnter(addSearchRestriction)); - VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().addKeyListener(new _OnCtrlEnter(addSearchRestriction) { - private boolean keypressPending; - @Override - public void keyReleased(KeyEvent e) { - if (KeyEvent.VK_ENTER == e.getKeyCode() && 0 == e.getModifiers()) { - // set focus to table when a plain enter is typed into the text filter box - CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getCatalogManager().getTable().requestFocusInWindow(); - } else if (keypressPending) { - // do this in keyReleased instead of keyTyped since the textbox text isn't updated until the key is released - // but depend on keypressPending since otherwise we pick up hotkeys and other unwanted stuff - applyCurrentFilter(); - } - } - - @Override - public void keyPressed(KeyEvent e) { - super.keyPressed(e); - keypressPending = KeyEvent.VK_ENTER != e.getKeyCode(); - } - }); - - VCardCatalog.SINGLETON_INSTANCE.getLblName().setCommand(updateFilterCommand); - VCardCatalog.SINGLETON_INSTANCE.getLblType().setCommand(updateFilterCommand); - VCardCatalog.SINGLETON_INSTANCE.getLblText().setCommand(updateFilterCommand); - - // ensure mins can's exceed maxes and maxes can't fall below mins - for (Pair sPair : VCardCatalog.SINGLETON_INSTANCE.getSpinners().values()) { - final FSpinner min = sPair.getLeft(); - final FSpinner max = sPair.getRight(); - - min.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent arg0) { - if (Integer.parseInt(max.getValue().toString()) < - Integer.parseInt(min.getValue().toString())) - { - max.setValue(min.getValue()); - } - applyCurrentFilter(); - } - }); - - max.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent arg0) { - if (Integer.parseInt(min.getValue().toString()) > - Integer.parseInt(max.getValue().toString())) - { - min.setValue(max.getValue()); - } - applyCurrentFilter(); - } - }); - } - } - - private class _OnCtrlEnter extends KeyAdapter { - private final Runnable action; - _OnCtrlEnter(Runnable action) { - this.action = action; - } - - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == 10) { - if (e.isControlDown() || e.isMetaDown()) { - action.run(); - } - } - } } /* (non-Javadoc) @@ -377,207 +39,4 @@ public enum CCardCatalog implements ICDoc { @Override public void update() { } - - @SuppressWarnings("unchecked") - public void applyCurrentFilter() { - // The main trick here is to apply a CardPrinted predicate - // to the table. CardRules will lead to difficulties. - - List> cardPredicates = new ArrayList>(); - cardPredicates.add(Predicates.instanceOf(PaperCard.class)); - cardPredicates.add(SFilterUtil.buildColorAndTypeFilter(VCardCatalog.SINGLETON_INSTANCE.getStatLabels())); - cardPredicates.addAll(activePredicates); - - // apply current values in the range filters - for (RangeTypes t : RangeTypes.values()) { - if (activeRanges.contains(t)) { - cardPredicates.add(SFilterUtil.buildIntervalFilter(VCardCatalog.SINGLETON_INSTANCE.getSpinners(), t)); - } - } - - // get the current contents of the search box - cardPredicates.add(SFilterUtil.buildTextFilter( - VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().getText(), - 0 != VCardCatalog.SINGLETON_INSTANCE.getCbSearchMode().getSelectedIndex(), - VCardCatalog.SINGLETON_INSTANCE.getLblName().getSelected(), - VCardCatalog.SINGLETON_INSTANCE.getLblType().getSelected(), - VCardCatalog.SINGLETON_INSTANCE.getLblText().getSelected())); - - Predicate cardFilter = Predicates.and(cardPredicates); - - // show packs and decks in the card shop according to the toggle setting - // this is special-cased apart from the buildColorAndTypeFilter() above - if (VCardCatalog.SINGLETON_INSTANCE.getItemManager().getStatLabel(StatTypes.PACK).getSelected()) { - List> itemPredicates = new ArrayList>(); - itemPredicates.add(cardFilter); - itemPredicates.add(ItemPredicate.Presets.IS_PACK); - itemPredicates.add(ItemPredicate.Presets.IS_DECK); - cardFilter = Predicates.or(itemPredicates); - } - - // Apply to table - // TODO: is there really no way to make this type safe? - ACEditorBase editor = CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController(); - if (null != editor) { - ((ACEditorBase)editor).getCatalogManager().setFilterPredicate(cardFilter); - } - } - - private boolean canSearch() { - return !VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().getText().isEmpty() && - (VCardCatalog.SINGLETON_INSTANCE.getLblName().getSelected() || - VCardCatalog.SINGLETON_INSTANCE.getLblType().getSelected() || - VCardCatalog.SINGLETON_INSTANCE.getLblText().getSelected()); - } - - private boolean isActive(Set activeSet, T key) { - return activeSet.contains(key); - } - - @SuppressWarnings("serial") - private void addRestriction(Pair> restriction, final Set activeSet, final T key) { - final Predicate predicate = restriction.getRight(); - - if (null != predicate && activePredicates.contains(predicate)) { - return; - } - - VCardCatalog.SINGLETON_INSTANCE.addRestrictionWidget(restriction.getLeft(), new Command() { - @Override - public void run() { - if (null != key) { - activeSet.remove(key); - } - if (null != predicate) { - activePredicates.remove(predicate); - } - applyCurrentFilter(); - } - }); - - if (null != key) { - activeSet.add(key); - } - if (null != predicate) { - activePredicates.add(predicate); - } - - applyCurrentFilter(); - } - - private Pair> buildRangeRestriction(RangeTypes t) { - final Pair s = VCardCatalog.SINGLETON_INSTANCE.getSpinners().get(t); - s.getLeft().setValue(0); - s.getRight().setValue(10); - - // set focus to lower bound widget - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - ((JSpinner.DefaultEditor)s.getLeft().getEditor()).getTextField().requestFocusInWindow(); - } - }); - - return Pair.of(VCardCatalog.SINGLETON_INSTANCE.buildRangeRestrictionWidget(t), null); - } - - private String buildSearchRestrictionText(String text, boolean isInverse, boolean wantName, boolean wantType, boolean wantText) { - StringBuilder sb = new StringBuilder(); - sb.append(isInverse ? "Without" : "Contains"); - sb.append(": '").append(text).append("' in:"); - if (wantName) { sb.append(" name,"); } - if (wantType) { sb.append(" type,"); } - if (wantText) { sb.append(" text,"); } - sb.delete(sb.length() - 1, sb.length()); // chop off last comma - - return sb.toString(); - } - - private Pair> buildSearchRestriction() { - boolean isInverse = - VCardCatalog.SEARCH_MODE_INVERSE_INDEX == VCardCatalog.SINGLETON_INSTANCE.getCbSearchMode().getSelectedIndex(); - String text = VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().getText(); - boolean wantName = VCardCatalog.SINGLETON_INSTANCE.getLblName().getSelected(); - boolean wantType = VCardCatalog.SINGLETON_INSTANCE.getLblType().getSelected(); - boolean wantText = VCardCatalog.SINGLETON_INSTANCE.getLblText().getSelected(); - - String shortText = buildSearchRestrictionText(text, isInverse, wantName, wantType, wantText); - String fullText = null; - if (25 < text.length()) { - fullText = shortText; - shortText = buildSearchRestrictionText(text.substring(0, 22) + "...", - isInverse, wantName, wantType, wantText); - } - - VCardCatalog.SINGLETON_INSTANCE.getTxfSearch().setText(""); - - return Pair.of( - VCardCatalog.SINGLETON_INSTANCE.buildPlainRestrictionWidget(shortText, fullText), - SFilterUtil.buildTextFilter(text, isInverse, wantName, wantType, wantText)); - } - - private Pair> buildFormatRestriction(String displayName, GameFormat format, boolean allowReprints) { - CardEdition.Collection editions = Singletons.getMagicDb().getEditions(); - StringBuilder tooltip = new StringBuilder("Sets:"); - - int lastLen = 0; - int lineLen = 0; - - // use HTML tooltips so we can insert line breaks - List sets = format.getAllowedSetCodes(); - if (null == sets || sets.isEmpty()) { - tooltip.append(" All"); - } else { - for (String code : sets) { - // don't let a single line get too long - if (50 < lineLen) { - tooltip.append("
"); - lastLen += lineLen; - lineLen = 0; - } - - CardEdition edition = editions.get(code); - tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),"); - lineLen = tooltip.length() - lastLen; - } - - // chop off last comma - tooltip.delete(tooltip.length() - 1, tooltip.length()); - - if (allowReprints) { - tooltip.append("

Allowing identical cards from other sets"); - } - } - - List bannedCards = format.getBannedCardNames(); - if (null != bannedCards && !bannedCards.isEmpty()) { - tooltip.append("

Banned:"); - lastLen += lineLen; - lineLen = 0; - - for (String cardName : bannedCards) { - // don't let a single line get too long - if (50 < lineLen) { - tooltip.append("
"); - lastLen += lineLen; - lineLen = 0; - } - - tooltip.append(" ").append(cardName).append(";"); - lineLen = tooltip.length() - lastLen; - } - - // chop off last semicolon - tooltip.delete(tooltip.length() - 1, tooltip.length()); - } - tooltip.append(""); - - return Pair.of( - VCardCatalog.SINGLETON_INSTANCE.buildPlainRestrictionWidget(displayName, tooltip.toString()), - allowReprints ? format.getFilterRules() : format.getFilterPrinted()); - } - - private Pair> buildSetRestriction(String displayName, List setCodes, boolean allowReprints) { - return buildFormatRestriction(displayName, new GameFormat(null, setCodes, null), allowReprints); - } } diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java index d779d661df9..c262c505427 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java @@ -19,7 +19,6 @@ import forge.gui.deckeditor.DeckImport; import forge.gui.deckeditor.SEditorIO; import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.framework.ICDoc; -import forge.gui.toolbox.FLabel; import forge.item.InventoryItem; import forge.properties.NewConstants; @@ -75,40 +74,43 @@ public enum CCurrentDeck implements ICDoc { @Override @SuppressWarnings("serial") public void initialize() { - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnSave()) - .setCommand(new Command() { @Override - public void run() { SEditorIO.saveDeck(); } }); - - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnSaveAs()) - .setCommand(new Command() { @Override - public void run() { exportDeck(); } }); - - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies()) - .setCommand(new Command() { @Override - public void run() { printProxies(); } }); - - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnOpen()) - .setCommand(new Command() { @Override - public void run() { openDeck(); } }); - - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnNew()) - .setCommand(new Command() { @Override - public void run() { newDeck(); } }); - - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove()).setCommand(new Command() { - @Override public void run() { - CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, 1); - } }); - - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4()).setCommand(new Command() { - @Override public void run() { - CDeckEditorUI.SINGLETON_INSTANCE.removeSelectedCards(false, 4); + VCurrentDeck.SINGLETON_INSTANCE.getBtnSave().setCommand(new Command() { + @Override + public void run() { + SEditorIO.saveDeck(); + } + }); + VCurrentDeck.SINGLETON_INSTANCE.getBtnSaveAs().setCommand(new Command() { + @Override + public void run() { + exportDeck(); + } + }); + VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setCommand(new Command() { + @Override + public void run() { + printProxies(); + } + }); + VCurrentDeck.SINGLETON_INSTANCE.getBtnOpen().setCommand(new Command() { + @Override + public void run() { + openDeck(); } }); - VCurrentDeck.SINGLETON_INSTANCE.getBtnImport() - .setCommand(new Command() { @Override - public void run() { importDeck(); } }); + VCurrentDeck.SINGLETON_INSTANCE.getBtnNew().setCommand(new Command() { + @Override + public void run() { + newDeck(); + } + }); + VCurrentDeck.SINGLETON_INSTANCE.getBtnImport().setCommand(new Command() { + @Override + public void run() { + importDeck(); + } + }); } /** diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java index b661cc560bf..737c8145e57 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CDeckgen.java @@ -20,7 +20,6 @@ import forge.gui.deckeditor.CDeckEditorUI; import forge.gui.deckeditor.SEditorIO; import forge.gui.deckeditor.views.VDeckgen; import forge.gui.framework.ICDoc; -import forge.gui.toolbox.FLabel; import forge.item.PaperCard; import forge.item.InventoryItem; import forge.properties.ForgePreferences.FPref; @@ -53,21 +52,30 @@ public enum CDeckgen implements ICDoc { @SuppressWarnings("serial") @Override public void initialize() { - ((FLabel) VDeckgen.SINGLETON_INSTANCE.getBtnRandCardpool()).setCommand(new Command() { + VDeckgen.SINGLETON_INSTANCE.getBtnRandCardpool().setCommand(new Command() { @Override public void run() { newRandomConstructed(); } }); - - ((FLabel) VDeckgen.SINGLETON_INSTANCE.getBtnRandDeck2()).setCommand(new Command() { - @Override public void run() { newGenerateConstructed(2); } }); - - ((FLabel) VDeckgen.SINGLETON_INSTANCE.getBtnRandDeck3()).setCommand(new Command() { - @Override public void run() { newGenerateConstructed(3); } }); - - ((FLabel) VDeckgen.SINGLETON_INSTANCE.getBtnRandDeck5()).setCommand(new Command() { - @Override public void run() { newGenerateConstructed(5); } }); + VDeckgen.SINGLETON_INSTANCE.getBtnRandDeck2().setCommand(new Command() { + @Override + public void run() { + newGenerateConstructed(2); + } + }); + VDeckgen.SINGLETON_INSTANCE.getBtnRandDeck3().setCommand(new Command() { + @Override + public void run() { + newGenerateConstructed(3); + } + }); + VDeckgen.SINGLETON_INSTANCE.getBtnRandDeck5().setCommand(new Command() { + @Override + public void run() { + newGenerateConstructed(5); + } + }); } /* (non-Javadoc) diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorCommander.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorCommander.java index 0f1f126fc74..04b2a132332 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorCommander.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorCommander.java @@ -37,7 +37,6 @@ import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.deckeditor.views.VDeckgen; import forge.gui.framework.DragCell; import forge.gui.framework.FScreen; -import forge.gui.toolbox.FLabel; import forge.gui.toolbox.itemmanager.CardManager; import forge.gui.toolbox.itemmanager.SItemManagerIO; import forge.gui.toolbox.itemmanager.SItemManagerUtil; @@ -87,8 +86,8 @@ public final class CEditorCommander extends ACEditorBase { boolean wantUnique = SItemManagerIO.getPref(EditorPreference.display_unique_only); - this.setCatalogManager(new CardManager(VCardCatalog.SINGLETON_INSTANCE.getStatLabels(), wantUnique)); - this.setDeckManager(new CardManager(VCurrentDeck.SINGLETON_INSTANCE.getStatLabels(), wantUnique)); + this.setCatalogManager(new CardManager(wantUnique)); + this.setDeckManager(new CardManager(wantUnique)); final Supplier newCreator = new Supplier() { @Override @@ -180,26 +179,26 @@ public final class CEditorCommander extends ACEditorBase { */ @Override public void update() { - final List> lstCatalogCols = SColumnUtil.getCatalogDefaultColumns(); lstCatalogCols.remove(SColumnUtil.getColumn(ColumnName.CAT_QUANTITY)); this.getCatalogManager().getTable().setup(lstCatalogCols); this.getDeckManager().getTable().setup(SColumnUtil.getDeckDefaultColumns()); - SItemManagerUtil.resetUI(); + SItemManagerUtil.resetUI(this); - VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4().setVisible(false); - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setVisible(false); - VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(true); - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard()).setCommand(new Command() { + this.getBtnRemove4().setVisible(false); + this.getBtnAdd4().setVisible(false); + this.getBtnCycleSection().setVisible(true); + this.getBtnCycleSection().setCommand(new Command() { private static final long serialVersionUID = -9082606944024479599L; @Override public void run() { cycleEditorMode(); - } }); - + } + }); + deckGenParent = removeTab(VDeckgen.SINGLETON_INSTANCE); allDecksParent = removeTab(VAllDecks.SINGLETON_INSTANCE); diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorConstructed.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorConstructed.java index d1945f791a6..703ac213dd7 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorConstructed.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorConstructed.java @@ -33,7 +33,6 @@ import forge.gui.deckeditor.SEditorIO; import forge.gui.deckeditor.views.VCardCatalog; import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.framework.FScreen; -import forge.gui.toolbox.FLabel; import forge.gui.toolbox.itemmanager.CardManager; import forge.gui.toolbox.itemmanager.SItemManagerIO; import forge.gui.toolbox.itemmanager.SItemManagerUtil; @@ -89,8 +88,8 @@ public final class CEditorConstructed extends ACEditorBase { boolean wantUnique = SItemManagerIO.getPref(EditorPreference.display_unique_only); - this.setCatalogManager(new CardManager(VCardCatalog.SINGLETON_INSTANCE.getStatLabels(), wantUnique)); - this.setDeckManager(new CardManager(VCurrentDeck.SINGLETON_INSTANCE.getStatLabels(), wantUnique)); + this.setCatalogManager(new CardManager(wantUnique)); + this.setDeckManager(new CardManager(wantUnique)); final Supplier newCreator = new Supplier() { @Override @@ -294,15 +293,16 @@ public final class CEditorConstructed extends ACEditorBase { this.getCatalogManager().getTable().setup(lstCatalogCols); this.getDeckManager().getTable().setup(SColumnUtil.getDeckDefaultColumns()); - SItemManagerUtil.resetUI(); + SItemManagerUtil.resetUI(this); - VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(true); - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard()).setCommand(new Command() { + this.getBtnCycleSection().setVisible(true); + this.getBtnCycleSection().setCommand(new Command() { @Override public void run() { cycleEditorMode(); - } }); - + } + }); + this.controller.refreshModel(); } diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorDraftingProcess.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorDraftingProcess.java index e09de413fef..44df945eb00 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorDraftingProcess.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorDraftingProcess.java @@ -66,8 +66,8 @@ public class CEditorDraftingProcess extends ACEditorBase { public CEditorDraftingProcess() { super(FScreen.DRAFTING_PROCESS); - final CardManager catalogManager = new CardManager(VCardCatalog.SINGLETON_INSTANCE.getStatLabels(), false); - final CardManager deckManager = new CardManager(VCurrentDeck.SINGLETON_INSTANCE.getStatLabels(), false); + final CardManager catalogManager = new CardManager(false); + final CardManager deckManager = new CardManager(false); catalogManager.setAlwaysNonUnique(true); deckManager.setAlwaysNonUnique(true); @@ -252,8 +252,8 @@ public class CEditorDraftingProcess extends ACEditorBase { this.getCatalogManager().getTable().setup(SColumnUtil.getCatalogDefaultColumns()); this.getDeckManager().getTable().setup(SColumnUtil.getDeckDefaultColumns()); - ccAddLabel = VCardCatalog.SINGLETON_INSTANCE.getBtnAdd().getText(); - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd().setText("Choose Card"); + ccAddLabel = this.getBtnAdd().getText(); + this.getBtnAdd().setText("Choose Card"); if (this.getDeckManager().getPool() == null) { //avoid showing next choice or resetting pool if just switching back to Draft screen this.showChoices(this.boosterDraft.nextChoice()); @@ -264,11 +264,11 @@ public class CEditorDraftingProcess extends ACEditorBase { } //Remove buttons - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setVisible(false); - VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove().setVisible(false); - VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4().setVisible(false); + this.getBtnAdd4().setVisible(false); + this.getBtnRemove().setVisible(false); + this.getBtnRemove4().setVisible(false); - VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(false); + this.getBtnCycleSection().setVisible(false); VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(false); @@ -293,12 +293,12 @@ public class CEditorDraftingProcess extends ACEditorBase { @Override public void resetUIChanges() { //Re-rename buttons - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd().setText(ccAddLabel); + this.getBtnAdd().setText(ccAddLabel); //Re-add buttons - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setVisible(true); - VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove().setVisible(true); - VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4().setVisible(true); + this.getBtnAdd4().setVisible(true); + this.getBtnRemove().setVisible(true); + this.getBtnRemove4().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true); diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorLimited.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorLimited.java index 2f038e83d10..6caa1b5d77a 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorLimited.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorLimited.java @@ -62,8 +62,8 @@ public final class CEditorLimited extends ACEditorBase { public CEditorLimited(final IStorage deckMap0, FScreen screen0) { super(screen0); - final CardManager catalogManager = new CardManager(VCardCatalog.SINGLETON_INSTANCE.getStatLabels(), false); - final CardManager deckManager = new CardManager(VCurrentDeck.SINGLETON_INSTANCE.getStatLabels(), false); + final CardManager catalogManager = new CardManager(false); + final CardManager deckManager = new CardManager(false); catalogManager.setAlwaysNonUnique(true); deckManager.setAlwaysNonUnique(true); @@ -163,7 +163,7 @@ public final class CEditorLimited extends ACEditorBase { this.getCatalogManager().getTable().setup(SColumnUtil.getCatalogDefaultColumns()); this.getDeckManager().getTable().setup(SColumnUtil.getDeckDefaultColumns()); - SItemManagerUtil.resetUI(); + SItemManagerUtil.resetUI(this); VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setVisible(false); VCurrentDeck.SINGLETON_INSTANCE.getBtnSaveAs().setVisible(false); diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorPreferences.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorPreferences.java index 628a1265859..26314665c7e 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorPreferences.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorPreferences.java @@ -14,7 +14,6 @@ import forge.gui.toolbox.itemmanager.SItemManagerIO.EditorPreference; import forge.gui.toolbox.itemmanager.table.TableColumnInfo; import forge.gui.toolbox.itemmanager.table.SColumnUtil; import forge.gui.toolbox.itemmanager.table.SColumnUtil.ColumnName; -import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.deckeditor.views.VEditorPreferences; import forge.gui.framework.ICDoc; import forge.item.InventoryItem; @@ -90,17 +89,11 @@ public enum CEditorPreferences implements ICDoc { } // Catalog/Deck Stats - VEditorPreferences.SINGLETON_INSTANCE.getChbDeckStats().setSelected( - SItemManagerIO.getPref(EditorPreference.stats_deck)); VEditorPreferences.SINGLETON_INSTANCE.getChbCardDisplayUnique().setSelected( SItemManagerIO.getPref(EditorPreference.display_unique_only)); VEditorPreferences.SINGLETON_INSTANCE.getChbElasticColumns().setSelected( SItemManagerIO.getPref(EditorPreference.elastic_columns)); - if (!SItemManagerIO.getPref(EditorPreference.stats_deck)) { - VCurrentDeck.SINGLETON_INSTANCE.setStatsVisible(false); - } - boolean wantElastic = SItemManagerIO.getPref(EditorPreference.elastic_columns); boolean wantUnique = SItemManagerIO.getPref(EditorPreference.display_unique_only); ACEditorBase curEditor = CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController(); @@ -113,13 +106,6 @@ public enum CEditorPreferences implements ICDoc { curEditor.getDeckManager().updateView(true); } - VEditorPreferences.SINGLETON_INSTANCE.getChbDeckStats().addItemListener(new ItemListener() { - @Override public void itemStateChanged(final ItemEvent e) { - VCurrentDeck.SINGLETON_INSTANCE.setStatsVisible( - ((JCheckBox) e.getSource()).isSelected()); - SItemManagerIO.setPref(EditorPreference.stats_deck, ((JCheckBox) e.getSource()).isSelected()); - SItemManagerIO.savePreferences(CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getCatalogManager().getTable()); } }); - VEditorPreferences.SINGLETON_INSTANCE.getChbElasticColumns().addItemListener(new ItemListener() { @Override public void itemStateChanged(final ItemEvent e) { ACEditorBase curEditor = CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController(); diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuest.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuest.java index cc2263755d6..0db9f139098 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuest.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuest.java @@ -38,7 +38,6 @@ import forge.gui.deckeditor.views.VDeckgen; import forge.gui.framework.DragCell; import forge.gui.framework.FScreen; import forge.gui.home.quest.CSubmenuQuestDecks; -import forge.gui.toolbox.FLabel; import forge.gui.toolbox.itemmanager.CardManager; import forge.gui.toolbox.itemmanager.SItemManagerUtil; import forge.gui.toolbox.itemmanager.table.TableColumnInfo; @@ -98,8 +97,8 @@ public final class CEditorQuest extends ACEditorBase { this.questData = questData0; - final CardManager catalogManager = new CardManager(VCardCatalog.SINGLETON_INSTANCE.getStatLabels(), false); - final CardManager deckManager = new CardManager(VCurrentDeck.SINGLETON_INSTANCE.getStatLabels(), false); + final CardManager catalogManager = new CardManager(false); + final CardManager deckManager = new CardManager(false); catalogManager.setAlwaysNonUnique(true); deckManager.setAlwaysNonUnique(true); @@ -281,11 +280,11 @@ public final class CEditorQuest extends ACEditorBase { this.getCatalogManager().getTable().setup(columnsCatalog); this.getDeckManager().getTable().setup(columnsDeck); - SItemManagerUtil.resetUI(); + SItemManagerUtil.resetUI(this); VCurrentDeck.SINGLETON_INSTANCE.getBtnSave().setVisible(true); - VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(true); - ((FLabel) VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard()).setCommand(new Command() { + this.getBtnCycleSection().setVisible(true); + this.getBtnCycleSection().setCommand(new Command() { @Override public void run() { sideboardMode = !sideboardMode; diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuestCardShop.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuestCardShop.java index e3ee553d858..58a6d162657 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuestCardShop.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorQuestCardShop.java @@ -129,8 +129,8 @@ public final class CEditorQuestCardShop extends ACEditorBase> cardsToRemove = new LinkedList>(); @@ -513,7 +513,7 @@ public final class CEditorQuestCardShop extends ACEditorBaseSelling cards at " + formatter.format(multiPercent) + "% of their value.
" + maxSellingPrice + ""); - - VCardCatalog.SINGLETON_INSTANCE.getItemManager().getStatLabel(SItemManagerUtil.StatTypes.PACK).setVisible(true); - + + //TODO: Add filter for SItemManagerUtil.StatTypes.PACK + deckGenParent = removeTab(VDeckgen.SINGLETON_INSTANCE); allDecksParent = removeTab(VAllDecks.SINGLETON_INSTANCE); probsParent = removeTab(VProbabilities.SINGLETON_INSTANCE); @@ -558,22 +558,22 @@ public final class CEditorQuestCardShop extends ACEditorBase { this.cardPoolCondition = poolCondition; - this.setCatalogManager(new CardManager(VCardCatalog.SINGLETON_INSTANCE.getStatLabels(), true)); - this.setDeckManager(new CardManager(VCurrentDeck.SINGLETON_INSTANCE.getStatLabels(), true)); + this.setCatalogManager(new CardManager(true)); + this.setDeckManager(new CardManager(true)); final Supplier newCreator = new Supplier() { @Override @@ -158,7 +156,7 @@ public final class CEditorVariant extends ACEditorBase { this.getCatalogManager().getTable().setup(lstCatalogCols); this.getDeckManager().getTable().setup(SColumnUtil.getDeckDefaultColumns()); - SItemManagerUtil.resetUI(); + SItemManagerUtil.resetUI(this); deckGenParent = removeTab(VDeckgen.SINGLETON_INSTANCE); allDecksParent = removeTab(VAllDecks.SINGLETON_INSTANCE); diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CProbabilities.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CProbabilities.java index 9a7c321bbc8..cc73958d6a8 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CProbabilities.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CProbabilities.java @@ -12,7 +12,6 @@ import forge.deck.DeckBase; import forge.gui.deckeditor.CDeckEditorUI; import forge.gui.deckeditor.views.VProbabilities; import forge.gui.framework.ICDoc; -import forge.gui.toolbox.FLabel; import forge.item.PaperCard; import forge.item.InventoryItem; import forge.util.ItemPool; @@ -45,8 +44,12 @@ public enum CProbabilities implements ICDoc { @Override @SuppressWarnings("serial") public void initialize() { - ((FLabel) VProbabilities.SINGLETON_INSTANCE.getLblReshuffle()).setCommand( - new Command() { @Override public void run() { update(); } }); + VProbabilities.SINGLETON_INSTANCE.getLblReshuffle().setCommand(new Command() { + @Override + public void run() { + update(); + } + }); } /* (non-Javadoc) diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/views/VCardCatalog.java b/forge-gui/src/main/java/forge/gui/deckeditor/views/VCardCatalog.java index 2737500fdc3..846f632d3e2 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/views/VCardCatalog.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/views/VCardCatalog.java @@ -1,38 +1,17 @@ package forge.gui.deckeditor.views; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.JTextField; - import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang3.tuple.Pair; - -import forge.Command; -import forge.card.CardRulesPredicates; -import forge.gui.WrapLayout; import forge.gui.deckeditor.controllers.CCardCatalog; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; import forge.gui.framework.IVDoc; -import forge.gui.toolbox.FComboBoxWrapper; import forge.gui.toolbox.FLabel; -import forge.gui.toolbox.FSkin; -import forge.gui.toolbox.FSpinner; -import forge.gui.toolbox.FTextField; import forge.gui.toolbox.itemmanager.ItemManager; import forge.gui.toolbox.itemmanager.ItemManagerContainer; -import forge.gui.toolbox.itemmanager.SItemManagerUtil; import forge.item.InventoryItem; -import forge.util.TextUtil; /** * Assembles Swing components of card catalog in deck editor. @@ -43,7 +22,7 @@ import forge.util.TextUtil; public enum VCardCatalog implements IVDoc { /** */ SINGLETON_INSTANCE; - + public static final int SEARCH_MODE_INVERSE_INDEX = 1; // Fields used with interface IVDoc @@ -54,120 +33,16 @@ public enum VCardCatalog implements IVDoc { private final JPanel pnlHeader = new JPanel(new MigLayout("insets 0, gap 0, center")); private final FLabel lblTitle = new FLabel.Builder().fontSize(14).build(); - // Total and color count labels/filter toggles - private final Dimension labelSize = new Dimension(60, 24); - private final JPanel pnlStats = new JPanel(new WrapLayout(FlowLayout.LEFT)); - private final Map statLabels = - new HashMap(); - - // card transfer buttons - private final JPanel pnlAddButtons = - new JPanel(new MigLayout("insets 0, gap 0, ax center, hidemode 3")); - private final FLabel btnAdd = new FLabel.Builder() - .fontSize(14) - .text("Add card") - .tooltip("Add selected card to current deck (or double click the row or hit the spacebar)") - .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS)) - .iconScaleAuto(false).hoverable().build(); - private final FLabel btnAdd4 = new FLabel.Builder() - .fontSize(14) - .text("Add 4 of card") - .tooltip("Add up to 4 of selected card to current deck") - .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PLUS)) - .iconScaleAuto(false).hoverable().build(); - - // restriction button and search widgets - private final JPanel pnlSearch = new JPanel(new MigLayout("insets 0, gap 5px, center")); - private final FLabel btnAddRestriction = new FLabel.ButtonBuilder() - .text("Add filter") - .tooltip("Click to add custom filters to the card list") - .reactOnMouseDown().build(); - private final FComboBoxWrapper cbSearchMode = new FComboBoxWrapper(); - private final JTextField txfSearch = new FTextField.Builder().ghostText("Search").build(); - private final FLabel lblName = new FLabel.Builder().text("Name").hoverable().selectable().selected().build(); - private final FLabel lblType = new FLabel.Builder().text("Type").hoverable().selectable().selected().build(); - private final FLabel lblText = new FLabel.Builder().text("Text").hoverable().selectable().selected().build(); - private final JPanel pnlRestrictions = new JPanel(new WrapLayout(FlowLayout.LEFT, 10, 5)); - private final ItemManagerContainer itemManagerContainer = new ItemManagerContainer(); private ItemManager itemManager; - - // restriction widgets - public static enum RangeTypes { - CMC (CardRulesPredicates.LeafNumber.CardField.CMC), - POWER (CardRulesPredicates.LeafNumber.CardField.POWER), - TOUGHNESS (CardRulesPredicates.LeafNumber.CardField.TOUGHNESS); - - public final CardRulesPredicates.LeafNumber.CardField cardField; - - RangeTypes(CardRulesPredicates.LeafNumber.CardField cardField) { - this.cardField = cardField; - } - public String toLabelString() { - if (this == CMC) { return toString(); } - return TextUtil.enumToLabel(this); - } - } - - private final Map> spinners = new HashMap>(); - //========== Constructor /** */ private VCardCatalog() { - pnlStats.setOpaque(false); - - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - FLabel label = buildToggleLabel(s, SItemManagerUtil.StatTypes.TOTAL != s); - statLabels.put(s, label); - JComponent component = label; - if (SItemManagerUtil.StatTypes.TOTAL == s) { - label.setToolTipText("Total cards (click to toggle all filters)"); - } else if (SItemManagerUtil.StatTypes.PACK == s) { - // wrap in a constant-size panel so we can change its visibility without affecting layout - component = new JPanel(new MigLayout("insets 0, gap 0")); - component.setPreferredSize(labelSize); - component.setMinimumSize(labelSize); - component.setOpaque(false); - label.setVisible(false); - component.add(label); - } - pnlStats.add(component); - } - - pnlAddButtons.setOpaque(false); - pnlAddButtons.add(btnAdd, "w 30%!, h 30px!, gap 10 10 5 5"); - pnlAddButtons.add(btnAdd4, "w 30%!, h 30px!, gap 10 10 5 5"); - - pnlSearch.setOpaque(false); - pnlSearch.add(btnAddRestriction, "center, w pref+8, h pref+8"); - pnlSearch.add(txfSearch, "pushx, growx"); - cbSearchMode.addItem("in"); - cbSearchMode.addItem("not in"); - cbSearchMode.addTo(pnlSearch, "center"); - pnlSearch.add(lblName, "w pref+8, h pref+8"); - pnlSearch.add(lblType, "w pref+8, h pref+8"); - pnlSearch.add(lblText, "w pref+8, h pref+8"); - - pnlRestrictions.setOpaque(false); - pnlHeader.setOpaque(false); pnlHeader.add(lblTitle, "center, gap 0 0 10 5"); - - // fill spinner map - for (RangeTypes t : RangeTypes.values()) { - FSpinner lowerBound = new FSpinner.Builder().maxValue(10).build(); - FSpinner upperBound = new FSpinner.Builder().maxValue(10).build(); - _setupSpinner(lowerBound); - _setupSpinner(upperBound); - spinners.put(t, Pair.of(lowerBound, upperBound)); - } } - private void _setupSpinner (JSpinner spinner) { - spinner.setFocusable(false); // only the spinner text field should be focusable, not the up/down widget - } - //========== Overridden from IVDoc @Override @@ -198,20 +73,17 @@ public enum VCardCatalog implements IVDoc { @Override public void populate() { JPanel parentBody = parentCell.getBody(); - parentBody.setLayout(new MigLayout("insets 0, gap 0, wrap, hidemode 3")); - parentBody.add(pnlHeader, "w 98%!, gap 1% 1% 5 0"); - parentBody.add(pnlStats, "w 100:520:520, center"); - parentBody.add(pnlAddButtons, "w 96%!, gap 1% 1% 5 5"); - parentBody.add(pnlSearch, "w 96%, gap 1% 1%"); - parentBody.add(pnlRestrictions, "w 96%, gapleft 1%, gapright push"); - parentBody.add(itemManagerContainer, "w 98%!, h 100% - 35, gap 1% 0 0 1%"); + parentBody.setLayout(new MigLayout("insets 5, gap 0, wrap, hidemode 3")); + parentBody.add(pnlHeader, "pushx, growx"); + parentBody.add(itemManagerContainer, "push, grow"); } - + public ItemManager getItemManager() { return this.itemManager; } public void setItemManager(final ItemManager itemManager0) { + if (this.itemManager == itemManager0) { return; } this.itemManager = itemManager0; itemManagerContainer.setItemManager(itemManager0); } @@ -219,90 +91,4 @@ public enum VCardCatalog implements IVDoc { //========== Accessor/mutator methods public JPanel getPnlHeader() { return pnlHeader; } public FLabel getLblTitle() { return lblTitle; } - public JPanel getPnlAddButtons() { return pnlAddButtons; } - public FLabel getBtnAdd() { return btnAdd; } - public FLabel getBtnAdd4() { return btnAdd4; } - public FLabel getLblName() { return lblName; } - public FLabel getLblType() { return lblType; } - public FLabel getLblText() { return lblText; } - - public FLabel getBtnAddRestriction() { return btnAddRestriction; } - public FComboBoxWrapper getCbSearchMode() { return cbSearchMode; } - public JTextField getTxfSearch() { return txfSearch; } - - public Map getStatLabels() { - return statLabels; - } - public Map> getSpinners() { - return spinners; - } - - //========== Other methods - private FLabel buildToggleLabel(SItemManagerUtil.StatTypes s, boolean selectable) { - String tooltip; - if (selectable) { //construct tooltip for selectable toggle labels, indicating click and right-click behavior - String labelString = s.toLabelString(); - tooltip = labelString + " (click to toggle the filter, right-click to show only " + labelString.toLowerCase() + ")"; - } - else { tooltip = ""; } - - FLabel label = new FLabel.Builder() - .icon(s.img).iconScaleAuto(false) - .fontSize(11) - .tooltip(tooltip) - .hoverable().selectable(selectable).selected(selectable) - .build(); - - label.setPreferredSize(labelSize); - label.setMinimumSize(labelSize); - - return label; - } - - @SuppressWarnings("serial") - public void addRestrictionWidget(JComponent component, final Command onRemove) { - final JPanel pnl = new JPanel(new MigLayout("insets 2, gap 2, h 30!")); - - pnl.setOpaque(false); - FSkin.get(pnl).setMatteBorder(1, 2, 1, 2, FSkin.getColor(FSkin.Colors.CLR_TEXT)); - - pnl.add(component, "h 30!, center"); - pnl.add(new FLabel.Builder().text("X").fontSize(10).hoverable(true) - .tooltip("Remove filter").cmdClick(new Command() { - @Override - public void run() { - pnlRestrictions.remove(pnl); - refreshRestrictionWidgets(); - onRemove.run(); - } - }).build(), "top"); - - pnlRestrictions.add(pnl, "h 30!"); - refreshRestrictionWidgets(); - } - - public void refreshRestrictionWidgets() { - Container parent = pnlRestrictions.getParent(); - pnlRestrictions.validate(); - parent.validate(); - parent.repaint(); - } - - public JPanel buildRangeRestrictionWidget(RangeTypes t) { - JPanel pnl = new JPanel(new MigLayout("insets 0, gap 2")); - pnl.setOpaque(false); - - Pair s = spinners.get(t); - pnl.add(s.getLeft(), "w 45!, h 26!, center"); - pnl.add(new FLabel.Builder().text("<=").fontSize(11).build(), "h 26!, center"); - pnl.add(new FLabel.Builder().text(t.toLabelString()).fontSize(11).build(), "h 26!, center"); - pnl.add(new FLabel.Builder().text("<=").fontSize(11).build(), "h 26!, center"); - pnl.add(s.getRight(), "w 45!, h 26!, center"); - - return pnl; - } - - public FLabel buildPlainRestrictionWidget(String label, String tooltip) { - return new FLabel.Builder().text(label).tooltip(tooltip).fontSize(11).build(); - } } diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/views/VCurrentDeck.java b/forge-gui/src/main/java/forge/gui/deckeditor/views/VCurrentDeck.java index fc919c89ef6..fe70187920d 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/views/VCurrentDeck.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/views/VCurrentDeck.java @@ -1,17 +1,8 @@ package forge.gui.deckeditor.views; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; - import net.miginfocom.swing.MigLayout; -import forge.gui.WrapLayout; import forge.gui.deckeditor.controllers.CCurrentDeck; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; @@ -22,7 +13,6 @@ import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FTextField; import forge.gui.toolbox.itemmanager.ItemManager; import forge.gui.toolbox.itemmanager.ItemManagerContainer; -import forge.gui.toolbox.itemmanager.SItemManagerUtil; import forge.item.InventoryItem; @@ -41,7 +31,7 @@ public enum VCurrentDeck implements IVDoc { // Other fields - private final JLabel btnSave = new FLabel.Builder() + private final FLabel btnSave = new FLabel.Builder() .fontSize(14) .tooltip("Save (in default directory)") .iconInBackground(true) @@ -49,7 +39,7 @@ public enum VCurrentDeck implements IVDoc { .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVE)) .text(" ").hoverable(true).build(); - private final JLabel btnExport = new FLabel.Builder() + private final FLabel btnExport = new FLabel.Builder() .fontSize(14) .tooltip("Save As") .iconInBackground(true) @@ -57,7 +47,7 @@ public enum VCurrentDeck implements IVDoc { .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVEAS)) .text(" ").hoverable(true).build(); - private final JLabel btnLoad = new FLabel.Builder() + private final FLabel btnLoad = new FLabel.Builder() .fontSize(14) .tooltip("Load") .iconInBackground(true) @@ -65,7 +55,7 @@ public enum VCurrentDeck implements IVDoc { .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_OPEN)) .text(" ").hoverable(true).build(); - private final JLabel btnNew = new FLabel.Builder() + private final FLabel btnNew = new FLabel.Builder() .fontSize(14) .tooltip("New Deck") .iconInBackground(true) @@ -73,7 +63,7 @@ public enum VCurrentDeck implements IVDoc { .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_NEW)) .text(" ").hoverable(true).build(); - private final JLabel btnPrintProxies = new FLabel.Builder() + private final FLabel btnPrintProxies = new FLabel.Builder() .fontSize(14) .tooltip("Print to HTML file") .iconInBackground(true) @@ -81,30 +71,6 @@ public enum VCurrentDeck implements IVDoc { .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PRINT)) .text(" ").hoverable(true).build(); - private final JPanel pnlRemoveButtons = - new JPanel(new MigLayout("insets 0, gap 0, ax center, hidemode 3")); - - private final FLabel btnRemove = new FLabel.Builder() - .fontSize(14) - .text("Remove card") - .tooltip("Remove selected card from current deck (or double click the row or hit the spacebar)") - .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS)) - .iconScaleAuto(false).hoverable().build(); - - private final FLabel btnRemove4 = new FLabel.Builder() - .fontSize(14) - .text("Remove 4 of card") - .tooltip("Remove up to 4 of selected card to current deck") - .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS)) - .iconScaleAuto(false).hoverable().build(); - - private final JLabel btnCycleSection = new FLabel.Builder() - .fontSize(14) - .text("Change Section") - .tooltip("Toggle between editing the deck and the sideboard/planar/scheme/vanguard parts of this deck") - .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT)) - .iconScaleAuto(false).hoverable().build(); - private final FLabel btnImport = new FLabel.Builder() .fontSize(14) .text("Import").tooltip("Attempt to import a deck from a non-Forge format") @@ -113,16 +79,9 @@ public enum VCurrentDeck implements IVDoc { private final FTextField txfTitle = new FTextField.Builder().ghostText("[New Deck]").build(); - private final JPanel pnlRemove = new JPanel(); private final JPanel pnlHeader = new JPanel(); - private final JLabel lblTitle = new FLabel.Builder().text("Title") - .fontSize(14).build(); - - // Total and color count labels/filter toggles - private final JPanel pnlStats = new JPanel(new WrapLayout(FlowLayout.LEFT)); - private final Map statLabels = - new HashMap(); + private final FLabel lblTitle = new FLabel.Builder().text("Title").fontSize(14).build(); private final ItemManagerContainer itemManagerContainer = new ItemManagerContainer(); private ItemManager itemManager; @@ -132,40 +91,17 @@ public enum VCurrentDeck implements IVDoc { private VCurrentDeck() { // Header area pnlHeader.setOpaque(false); - pnlHeader.setLayout(new MigLayout("insets 0, gap 0, ax center, hidemode 3")); + pnlHeader.setLayout(new MigLayout("insets 3, gapx 3, hidemode 3")); - pnlHeader.add(lblTitle, "w 80px!, h 30px!, gap 5px 5px 0 0"); - pnlHeader.add(txfTitle, "pushx, growx, gap 0 5px 0 0"); - pnlHeader.add(btnSave, "w 26px!, h 26px!, gap 0 5px 0 0"); - pnlHeader.add(btnNew, "w 26px!, h 26px!, gap 0 5px 0 0"); + pnlHeader.add(lblTitle, "h 26px!"); + pnlHeader.add(txfTitle, "pushx, growx"); + pnlHeader.add(btnSave, "w 26px!, h 26px!"); + pnlHeader.add(btnNew, "w 26px!, h 26px!"); - pnlHeader.add(btnLoad, "w 26px!, h 26px!, gap 0 5px 0 0"); - pnlHeader.add(btnExport, "w 26px!, h 26px!, gap 0 5px 0 0"); - pnlHeader.add(btnPrintProxies, "w 26px!, h 26px!, gap 0 5px 0 0"); - pnlHeader.add(btnImport, "w 50px!, h 26px!, gap 0 0 20px 0"); - - pnlRemove.setOpaque(false); - pnlRemove.setLayout(new MigLayout("insets 0, gap 0, ax center")); - pnlRemove.add(btnRemove, "w 30%!, h 30px!, gap 10 10 5 5"); - pnlRemove.add(btnRemove4, "w 30%!, h 30px!, gap 10 10 5 5"); - pnlRemove.add(btnCycleSection, "w 30%!, h 30px!, gap 10 10 5 5"); - - pnlStats.setOpaque(false); - - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - FLabel label = buildLabel(s); - statLabels.put(s, label); - if (SItemManagerUtil.StatTypes.PACK == s) { - pnlStats.add(buildLabel(null)); - } else { - pnlStats.add(label); - } - } - - pnlRemoveButtons.setOpaque(false); - pnlRemoveButtons.add(btnRemove, "w 30%!, h 30px!, gap 0 0 5px 5px"); - pnlRemoveButtons.add(btnRemove4, "w 30%!, h 30px!, gap 0 0 5px 5px"); - pnlRemoveButtons.add(btnCycleSection, "w 30%!, h 30px!, gap 0 0 5px 5px"); + pnlHeader.add(btnLoad, "w 26px!, h 26px!"); + pnlHeader.add(btnExport, "w 26px!, h 26px!"); + pnlHeader.add(btnPrintProxies, "w 26px!, h 26px!"); + pnlHeader.add(btnImport, "w 61px!, h 26px!"); } //========== Overridden from IVDoc @@ -216,11 +152,9 @@ public enum VCurrentDeck implements IVDoc { @Override public void populate() { final JPanel parentBody = parentCell.getBody(); - parentBody.setLayout(new MigLayout("insets 0, gap 0, wrap, hidemode 3, center")); - parentBody.add(pnlHeader, "w 98%!, gap 1% 1% 5 0"); - parentBody.add(pnlStats, "w 100:500:500, center"); - parentBody.add(pnlRemoveButtons, "w 96%!, gap 2% 0 0 0"); - parentBody.add(itemManagerContainer, "w 98%!, h 100% - 35, gap 1% 0 0 1%"); + parentBody.setLayout(new MigLayout("insets 5, gap 0, wrap, hidemode 3")); + parentBody.add(pnlHeader, "pushx, growx"); + parentBody.add(itemManagerContainer, "push, grow"); } public ItemManager getItemManager() { @@ -231,47 +165,33 @@ public enum VCurrentDeck implements IVDoc { this.itemManager = itemManager0; itemManagerContainer.setItemManager(itemManager0); } - - public Map getStatLabels() { - return statLabels; - } - public JLabel getLblTitle() { return lblTitle; } + public FLabel getLblTitle() { return lblTitle; } //========== Retrieval /** @return {@link javax.swing.JLabel} */ - public FLabel getBtnRemove() { - return btnRemove; - } - - /** @return {@link javax.swing.JLabel} */ - public FLabel getBtnRemove4() { - return btnRemove4; - } - - /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnSave() { + public FLabel getBtnSave() { return btnSave; } /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnSaveAs() { + public FLabel getBtnSaveAs() { return btnExport; } /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnPrintProxies() { + public FLabel getBtnPrintProxies() { return btnPrintProxies; } /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnOpen() { + public FLabel getBtnOpen() { return btnLoad; } /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnNew() { + public FLabel getBtnNew() { return btnNew; } @@ -285,55 +205,6 @@ public enum VCurrentDeck implements IVDoc { return pnlHeader; } - /** @return {@link javax.swing.JPanel} */ - public void setStatsVisible(boolean val) { - pnlStats.setVisible(val); - - // TODO: invisibly ensure the cell is not too large on first show - // if the program is started with pnlStats invisible, the first time it - // is made visible, the scroller cell that surrounds the panel will - // be too large. it will jump back to the correct size after any resize - // event, or if it is hidden and made visible again. For the life of - // me, I cannot figure out how to "kick" it into the correct size from - // here without the following hack, which will cause a visible jitter - // when the panel is shown for the first time (subsequent hides and shows - // will not cause any jitter), but at least it will be the correct size: - if (val) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - pnlStats.setVisible(false); - pnlStats.setVisible(true); - } - }); - } - } - - /** @return {@link javax.swing.JPanel} */ - public JPanel getPnlRemButtons() { - return pnlRemoveButtons; - } - - /** @return {@link javax.swing.JPanel} */ - public JLabel getBtnDoSideboard() { - return btnCycleSection; - } - - //========== Other methods - - private FLabel buildLabel(SItemManagerUtil.StatTypes s) { - FLabel label = new FLabel.Builder() - .icon(s == null ? null : s.img).iconScaleAuto(false) - .fontSize(11).tooltip(s == null ? null : s.toLabelString()) - .build(); - - Dimension labelSize = new Dimension(57, 20); - label.setPreferredSize(labelSize); - label.setMinimumSize(labelSize); - - return label; - } - /** * TODO: Write javadoc for this method. * @return diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/views/VDeckgen.java b/forge-gui/src/main/java/forge/gui/deckeditor/views/VDeckgen.java index d4c6667e7a8..0f8a23bb157 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/views/VDeckgen.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/views/VDeckgen.java @@ -1,7 +1,5 @@ package forge.gui.deckeditor.views; -import javax.swing.JLabel; - import net.miginfocom.swing.MigLayout; import forge.gui.deckeditor.controllers.CDeckgen; import forge.gui.framework.DragCell; @@ -24,22 +22,22 @@ public enum VDeckgen implements IVDoc { private final DragTab tab = new DragTab("Deck Generation"); // Deckgen buttons - private final JLabel btnRandCardpool = new FLabel.Builder() + private final FLabel btnRandCardpool = new FLabel.Builder() .tooltip("Generate random constructed cardpool in current deck area") .text("Random Cardpool").fontSize(14) .opaque(true).hoverable(true).build(); - private final JLabel btnRandDeck2 = new FLabel.Builder() + private final FLabel btnRandDeck2 = new FLabel.Builder() .tooltip("Generate 2 color constructed deck in current deck area") .text("Constructed (2 color)").fontSize(14) .opaque(true).hoverable(true).build(); - private final JLabel btnRandDeck3 = new FLabel.Builder() + private final FLabel btnRandDeck3 = new FLabel.Builder() .tooltip("Generate 3 color constructed deck in current deck area") .text("Constructed (3 color)").fontSize(14) .opaque(true).hoverable(true).build(); - private final JLabel btnRandDeck5 = new FLabel.Builder() + private final FLabel btnRandDeck5 = new FLabel.Builder() .tooltip("Generate 5 color constructed deck in current deck area") .text("Constructed (5 color)").fontSize(14) .opaque(true).hoverable(true).build(); @@ -106,22 +104,22 @@ public enum VDeckgen implements IVDoc { //========== Retrieval methods /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnRandCardpool() { + public FLabel getBtnRandCardpool() { return btnRandCardpool; } /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnRandDeck2() { + public FLabel getBtnRandDeck2() { return btnRandDeck2; } /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnRandDeck3() { + public FLabel getBtnRandDeck3() { return btnRandDeck3; } /** @return {@link javax.swing.JLabel} */ - public JLabel getBtnRandDeck5() { + public FLabel getBtnRandDeck5() { return btnRandDeck5; } } diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/views/VEditorPreferences.java b/forge-gui/src/main/java/forge/gui/deckeditor/views/VEditorPreferences.java index e76b7e61955..a0c03345edd 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/views/VEditorPreferences.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/views/VEditorPreferences.java @@ -62,7 +62,6 @@ public enum VEditorPreferences implements IVDoc { private JCheckBox chbDeckPower = new FCheckBox("Power"); private JCheckBox chbDeckToughness = new FCheckBox("Toughness"); - private JCheckBox chbDeckStats = new FCheckBox("Show stats in current deck"); private JCheckBox chbElasticColumns = new FCheckBox("Use elastic resizing when changing column widths"); private JCheckBox chbCardDisplayUnique = new FCheckBox("Show unique cards only (only affects Constructed)"); @@ -98,16 +97,13 @@ public enum VEditorPreferences implements IVDoc { FSkin.get(chbDeckPower).setFont(font); FSkin.get(chbDeckToughness).setFont(font); - FSkin.get(chbDeckStats).setFont(font); FSkin.get(chbElasticColumns).setFont(font); - chbDeckStats.setSelected(true); chbElasticColumns.setSelected(false); FSkin.get(chbCardDisplayUnique).setFont(font); chbCardDisplayUnique.setSelected(false); pnl.add(lblStats, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1"); - pnl.add(chbDeckStats, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1"); pnl.add(chbElasticColumns, "h 25px!, gap 5px 5px 5px 5px, ax center, span 2 1"); final String constraints = "w 75px, h 25px!, gap 5px 5px 5px 5px, ax center"; @@ -279,11 +275,6 @@ public enum VEditorPreferences implements IVDoc { return chbDeckToughness; } - /** @return {@link javax.swing.JCheckBox} */ - public JCheckBox getChbDeckStats() { - return chbDeckStats; - } - /** @return {@link javax.swing.JCheckBox} */ public JCheckBox getChbElasticColumns() { return chbElasticColumns; diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/views/VProbabilities.java b/forge-gui/src/main/java/forge/gui/deckeditor/views/VProbabilities.java index 50ac2e805f0..8871df40c5d 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/views/VProbabilities.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/views/VProbabilities.java @@ -37,12 +37,12 @@ public enum VProbabilities implements IVDoc { private final DragTab tab = new DragTab("Draw Order"); // Title labels - private final JLabel lblReshuffle = new FLabel.Builder() + private final FLabel lblReshuffle = new FLabel.Builder() .hoverable(true).text("CLICK HERE TO RE-SHUFFLE").tooltip("See a new sample shuffle") .fontSize(16).build(); - private final JLabel lblSampleHand = new FLabel.Builder().fontStyle(Font.BOLD) + private final FLabel lblSampleHand = new FLabel.Builder().fontStyle(Font.BOLD) .fontSize(12).text("SAMPLE HAND").opaque(true).build(); - private final JLabel lblRemainingDraws = new FLabel.Builder().fontStyle(Font.BOLD) + private final FLabel lblRemainingDraws = new FLabel.Builder().fontStyle(Font.BOLD) .fontSize(12).text("REMAINING DRAWS").opaque(true).build(); // private final JLabel lblExplanation = new FLabel.Builder() // .fontSize(11).text("XX % = frequency that card will appear at that position").build(); @@ -64,7 +64,7 @@ public enum VProbabilities implements IVDoc { scroller.getViewport().setBorder(null); scroller.getVerticalScrollBar().setUnitIncrement(16); - FSkin.JLabelSkin labelSkin = FSkin.get(lblSampleHand); + FSkin.JLabelSkin labelSkin = FSkin.get(lblSampleHand); labelSkin.setMatteBorder(1, 0, 1, 0, FSkin.getColor(FSkin.Colors.CLR_BORDERS)); labelSkin.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); @@ -134,7 +134,7 @@ public enum VProbabilities implements IVDoc { //========== Retrieval methods /** @return {@link javax.swing.JLabel} */ - public JLabel getLblReshuffle() { + public FLabel getLblReshuffle() { return lblReshuffle; } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FComboBox.java b/forge-gui/src/main/java/forge/gui/toolbox/FComboBox.java index d4a1e7ebb96..a82c826513d 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/FComboBox.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/FComboBox.java @@ -25,7 +25,6 @@ import forge.gui.toolbox.FSkin.SkinFont; @SuppressWarnings("serial") public class FComboBox extends JComboBox { - public enum TextAlignment { LEFT (SwingConstants.LEFT), RIGHT (SwingConstants.RIGHT), @@ -102,7 +101,6 @@ public class FComboBox extends JComboBox { } private class FComboBoxUI extends BasicComboBoxUI { - @Override protected LayoutManager createLayoutManager() { return super.createLayoutManager(); @@ -134,7 +132,6 @@ public class FComboBox extends JComboBox { @SuppressWarnings("hiding") private class CustomCellRenderer implements ListCellRenderer { - private DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer(); @Override diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FComboBoxWrapper.java b/forge-gui/src/main/java/forge/gui/toolbox/FComboBoxWrapper.java index 8ec1e8f5181..85ea9492e2d 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/FComboBoxWrapper.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/FComboBoxWrapper.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.Vector; import javax.swing.ComboBoxModel; +import javax.swing.JComponent; import javax.swing.ListCellRenderer; import forge.gui.toolbox.FComboBox.TextAlignment; @@ -136,6 +137,10 @@ public class FComboBoxWrapper { container.add(this.comboBox, constraints0); this.constraints = constraints0; } + + public JComponent getComponent() { //disguise as component for sake of rare places that need to access component in wrapper + return this.comboBox; + } private void refreshSkin() { this.comboBox = refreshComboBoxSkin(this.comboBox, this.constraints); diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java b/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java index 460d3109d23..2c3597f3d2a 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/FLabel.java @@ -360,10 +360,21 @@ public class FLabel extends JLabel implements ILocalRepaint { }; //========== Methods + /** @param b0   boolean */ + // Must be public. + @Override + public void setEnabled(final boolean b0) { + super.setEnabled(b0); + if (!this.hoverable) { return; } + if (!b0) { this.removeMouseListener(madEvents); } + else { this.addMouseListener(madEvents); } + } + /** @param b0   boolean */ // Must be public. public void setHoverable(final boolean b0) { this.hoverable = b0; + if (!this.isEnabled()) { return; } if (!b0) { this.removeMouseListener(madEvents); } else { this.addMouseListener(madEvents); } } @@ -387,7 +398,7 @@ public class FLabel extends JLabel implements ILocalRepaint { this.alphaStrong = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f); } - private void setFontSize(final int i0) { + public void setFontSize(final int i0) { switch(this.fontStyle) { case Font.BOLD: skin.setFont(FSkin.getBoldFont(i0)); break; case Font.ITALIC: skin.setFont(FSkin.getItalicFont(i0)); break; @@ -397,7 +408,7 @@ public class FLabel extends JLabel implements ILocalRepaint { /** @param i0   Font.PLAIN, .BOLD, or .ITALIC */ // NOT public; must be set when label is built. - private void setFontStyle(final int i0) { + public void setFontStyle(final int i0) { if (i0 != Font.PLAIN && i0 != Font.BOLD && i0 != Font.ITALIC) { throw new IllegalArgumentException("FLabel$setFontStyle " + "must be passed either Font.PLAIN, Font.BOLD, or Font.ITALIC."); @@ -407,7 +418,7 @@ public class FLabel extends JLabel implements ILocalRepaint { /** @param i0   SwingConstants.CENTER, .LEFT or .RIGHT */ // NOT public; must be set when label is built. - private void setFontAlign(final int i0) { + public void setFontAlign(final int i0) { if (i0 != SwingConstants.CENTER && i0 != SwingConstants.LEFT && i0 != SwingConstants.RIGHT) { throw new IllegalArgumentException("FLabel$setFontStyle " + "must be passed either SwingConstants.CENTER, " @@ -513,10 +524,12 @@ public class FLabel extends JLabel implements ILocalRepaint { else if (opaque) { if (selected) { paintDown(g2d, w, h); - } else { + } + else { paintUp(g2d, w, h); } - } else if (selectable) { + } + else if (selectable) { if (selected) { paintDown(g2d, w, h); } else { diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FSkin.java b/forge-gui/src/main/java/forge/gui/toolbox/FSkin.java index 44128da8e0d..e1bb08dbc16 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/FSkin.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/FSkin.java @@ -1644,6 +1644,10 @@ public enum FSkin { return this.font.getSize(); } + public int measureTextWidth(Graphics g, String text) { + return g.getFontMetrics(this.font).stringWidth(text); + } + private void updateFont() { this.font = baseFont.deriveFont(this.style, this.size); } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FTextField.java b/forge-gui/src/main/java/forge/gui/toolbox/FTextField.java index 2c943240dfd..218219c4278 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/FTextField.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/FTextField.java @@ -1,5 +1,6 @@ package forge.gui.toolbox; +import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; @@ -9,6 +10,8 @@ import java.awt.event.FocusEvent; import javax.swing.JTextField; import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument; @@ -47,7 +50,7 @@ public class FTextField extends JTextField { public Builder showGhostTextWithFocus(boolean b0) { showGhostTextWithFocus = b0; return this; } public Builder showGhostTextWithFocus() { return showGhostTextWithFocus(true); } } - + public static final int HEIGHT = 25; //TODO: calculate this somehow instead of hard-coding it private final FSkin.JTextComponentSkin skin; @@ -61,11 +64,11 @@ public class FTextField extends JTextField { skin.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT)); this.setMargin(new Insets(3, 3, 2, 3)); this.setOpaque(true); - + if (builder.maxLength > 0) { this.setDocument(new _LengthLimitedDocument(builder.maxLength)); } - + this.setEditable(!builder.readonly); this.setText(builder.text); this.setToolTipText(builder.toolTip); @@ -102,13 +105,17 @@ public class FTextField extends JTextField { this.ghostText = builder.ghostText; if (this.ghostText == "") { this.ghostText = null; } //don't allow empty string to make other logic easier } - - public boolean isEmpty() - { + + public boolean isEmpty() { String text = this.getText(); return (text == null || text.isEmpty()); } + public int getAutoSizeWidth() { + FontMetrics metrics = getGraphics().getFontMetrics(this.getFont()); + return metrics.stringWidth(this.getText()) + 12; + } + @Override public void paint(Graphics g) { super.paint(g); @@ -123,14 +130,12 @@ public class FTextField extends JTextField { g2d.dispose(); } } - - public String getGhostText() - { + + public String getGhostText() { return this.ghostText; } - - public void setGhostText(String ghostText0) - { + + public void setGhostText(String ghostText0) { if (ghostText0 == "") { ghostText0 = null; } //don't allow empty string to make other logic easier if (this.ghostText == ghostText0) { return; } this.ghostText = ghostText0; @@ -138,14 +143,12 @@ public class FTextField extends JTextField { this.repaint(); } } - - public boolean getShowGhostTextWithFocus() - { + + public boolean getShowGhostTextWithFocus() { return this.showGhostTextWithFocus; } - - public void setShowGhostTextWithFocus(boolean showGhostTextWithFocus0) - { + + public void setShowGhostTextWithFocus(boolean showGhostTextWithFocus0) { if (this.showGhostTextWithFocus == showGhostTextWithFocus0) { return; } this.showGhostTextWithFocus = showGhostTextWithFocus0; if (this.isEmpty() && this.hasFocus()) { @@ -155,7 +158,7 @@ public class FTextField extends JTextField { private static class _LengthLimitedDocument extends PlainDocument { private final int _limit; - + _LengthLimitedDocument(int limit) { _limit = limit; } // called each time a character is typed or a string is pasted @@ -172,4 +175,27 @@ public class FTextField extends JTextField { super.insertString(offset, s, attributeSet); } } + + public void addChangeListener(ChangeListener listener) { + this.getDocument().addDocumentListener(listener); + } + + public static abstract class ChangeListener implements DocumentListener { + @Override + public void changedUpdate(DocumentEvent e) { + textChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + textChanged(); + } + + @Override + public void insertUpdate(DocumentEvent e) { + textChanged(); + } + + public abstract void textChanged(); + } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/LayoutHelper.java b/forge-gui/src/main/java/forge/gui/toolbox/LayoutHelper.java index 5a5e4bb864e..7a56e4b2477 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/LayoutHelper.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/LayoutHelper.java @@ -9,7 +9,7 @@ import javax.swing.JComponent; public final class LayoutHelper { private final int parentWidth, parentHeight; private int x, y, lineBottom; - + public LayoutHelper(JComponent parent) { parentWidth = parent.getWidth(); parentHeight = parent.getHeight(); @@ -30,12 +30,22 @@ public final class LayoutHelper { * @param height */ public void fillLine(final JComponent comp, int height) { + fillLine(comp, height, 0); + } + + /** + * Layout component to fill remaining horizontal space of current line + * @param comp + * @param height + * @param rightPadding + */ + public void fillLine(final JComponent comp, int height, int rightPadding) { if (x >= parentWidth) { newLine(); } - include(comp, parentWidth - x, height); + include(comp, parentWidth - x - rightPadding, height); } - + /** * Include component in layout with a percentage width and fixed height * @param comp @@ -101,7 +111,7 @@ public final class LayoutHelper { x += dx; y += dy; } - + /** * Start new line of layout */ @@ -111,4 +121,27 @@ public final class LayoutHelper { y = lineBottom + 3; lineBottom = y; } + + /** + * Start new line of layout + */ + public void newLine(int dy) { + x = 0; + y = lineBottom + 3 + dy; + lineBottom = y; + } + + /** + * @return width of parent + */ + public int getParentWidth() { + return parentWidth; + } + + /** + * @return width of parent + */ + public int getParentHeight() { + return parentHeight; + } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/CardManager.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/CardManager.java index 88a713ee071..135d2256ccc 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/CardManager.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/CardManager.java @@ -1,16 +1,12 @@ package forge.gui.toolbox.itemmanager; import java.util.List; -import java.util.Map; - import javax.swing.JMenu; import javax.swing.JPopupMenu; import forge.Singletons; import forge.game.GameFormat; import forge.gui.GuiUtils; import forge.gui.home.quest.DialogChooseSets; -import forge.gui.toolbox.FLabel; -import forge.gui.toolbox.itemmanager.SItemManagerUtil.StatTypes; import forge.gui.toolbox.itemmanager.filters.CardCMCFilter; import forge.gui.toolbox.itemmanager.filters.CardColorFilter; import forge.gui.toolbox.itemmanager.filters.CardFormatFilter; @@ -30,17 +26,19 @@ import forge.quest.QuestWorld; */ @SuppressWarnings("serial") public final class CardManager extends ItemManager { + public CardManager(boolean wantUnique0) { + super(PaperCard.class, wantUnique0); - public CardManager(Map statLabels0, boolean wantUnique0) { - super(PaperCard.class, statLabels0, wantUnique0); - + this.lockFiltering = true; //temporary lock filtering for improved performance this.addFilter(new CardColorFilter(this)); this.addFilter(new CardTypeFilter(this)); + this.lockFiltering = false; + buildFilterPredicate(); } @Override - protected ItemFilter createSearchFilter(String text) { - return new CardSearchFilter(this, text); + protected ItemFilter createSearchFilter() { + return new CardSearchFilter(this); } @Override @@ -70,7 +68,7 @@ public final class CardManager extends ItemManager { public void run() { List sets = dialog.getSelectedSets(); if (!sets.isEmpty()) { - addFilter(new CardSetFilter(CardManager.this, sets)); + addFilter(new CardSetFilter(CardManager.this, sets, dialog.getWantReprints())); } } }); diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/InventoryItemManager.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/InventoryItemManager.java index 5709dd6b6d0..07cc16daf73 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/InventoryItemManager.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/InventoryItemManager.java @@ -1,11 +1,7 @@ package forge.gui.toolbox.itemmanager; -import java.util.Map; - import javax.swing.JPopupMenu; -import forge.gui.toolbox.FLabel; -import forge.gui.toolbox.itemmanager.SItemManagerUtil.StatTypes; import forge.gui.toolbox.itemmanager.filters.ItemFilter; import forge.item.InventoryItem; @@ -15,13 +11,12 @@ import forge.item.InventoryItem; */ @SuppressWarnings("serial") public final class InventoryItemManager extends ItemManager { - - public InventoryItemManager(Map statLabels0, boolean wantUnique0) { - super(InventoryItem.class, statLabels0, wantUnique0); + public InventoryItemManager(boolean wantUnique0) { + super(InventoryItem.class, wantUnique0); } @Override - protected ItemFilter createSearchFilter(String text) { + protected ItemFilter createSearchFilter() { return null; } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/ItemManager.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/ItemManager.java index 5a0b5f7288e..ee4b243289b 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/ItemManager.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/ItemManager.java @@ -18,6 +18,9 @@ package forge.gui.toolbox.itemmanager; import java.awt.Toolkit; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.HashMap; @@ -25,26 +28,30 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import javax.swing.JCheckBox; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.event.ListSelectionListener; +import net.miginfocom.swing.MigLayout; + import com.google.common.base.Predicate; - - import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import forge.Command; import forge.gui.GuiUtils; import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FTextField; import forge.gui.toolbox.LayoutHelper; import forge.gui.toolbox.ToolTipListener; +import forge.gui.toolbox.FSkin.Colors; import forge.gui.toolbox.itemmanager.filters.ItemFilter; import forge.gui.toolbox.itemmanager.table.ItemTable; import forge.gui.toolbox.itemmanager.table.ItemTableModel; @@ -73,16 +80,33 @@ public abstract class ItemManager extends JPanel { private boolean alwaysNonUnique = false; private boolean allowMultipleSelections = false; private final Class genericType; - private final Map statLabels; private final ArrayList selectionListeners = new ArrayList(); - private final FLabel btnAddFilter = new FLabel.ButtonBuilder() - .text("Add") - .tooltip("Click to add filters to the list") - .reactOnMouseDown().build(); - private final FTextField txtSearch = new FTextField.Builder().ghostText("Search").build(); + private final JCheckBox chkEnableFilters = new JCheckBox(); + + private final FTextField txtFilterLogic = new FTextField.Builder() + .tooltip("Use '&','|','!' symbols (AND,OR,NOT) in combination with filter numbers and optional grouping \"()\" to build Boolean expression evaluated when applying filters") + .readonly() //TODO: Support editing filter logic + .build(); + + private ItemFilter mainSearchFilter; + private final JPanel pnlButtons = new JPanel(new MigLayout("insets 0, gap 0, ax center, hidemode 3")); + + private final FLabel btnFilters = new FLabel.ButtonBuilder() + .text("Filters") + .tooltip("Click to configure filters") + .reactOnMouseDown() + .build(); + + private final FLabel lblRatio = new FLabel.Builder() + .tooltip("Number of cards shown / Total available cards") + .fontAlign(SwingConstants.LEFT) + .fontSize(11) + .build(); + private final ItemTable table; private final JScrollPane tableScroller; + protected boolean lockFiltering; /** * ItemManager Constructor. @@ -91,9 +115,8 @@ public abstract class ItemManager extends JPanel { * @param statLabels0 stat labels for this item manager * @param wantUnique0 whether this table should display only one item with the same name */ - protected ItemManager(final Class genericType0, Map statLabels0, final boolean wantUnique0) { + protected ItemManager(final Class genericType0, final boolean wantUnique0) { this.genericType = genericType0; - this.statLabels = statLabels0; this.wantUnique = wantUnique0; this.model = new ItemManagerModel(this, genericType0); @@ -107,13 +130,65 @@ public abstract class ItemManager extends JPanel { this.tableScroller.getViewport().setBorder(null); this.tableScroller.getVerticalScrollBar().addAdjustmentListener(new ToolTipListener()); + //build enable filters checkbox + ItemFilter.layoutCheckbox(this.chkEnableFilters); + this.chkEnableFilters.setText("(*)"); + this.chkEnableFilters.setSelected(true); + this.chkEnableFilters.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent arg0) { + lockFiltering = true; + boolean enabled = chkEnableFilters.isSelected(); + for (ItemFilter filter : orderedFilters) { + filter.setEnabled(enabled); + } + txtFilterLogic.setEnabled(enabled); + btnFilters.setEnabled(enabled); + mainSearchFilter.setEnabled(enabled); + mainSearchFilter.updateEnabled(); //need to call updateEnabled since no listener for filter checkbox + lockFiltering = false; + buildFilterPredicate(); + } + }); + //build display this.setOpaque(false); this.setLayout(null); - this.add(this.btnAddFilter); - this.add(this.txtSearch); + this.add(this.chkEnableFilters); + this.add(this.txtFilterLogic); + this.mainSearchFilter = createSearchFilter(); + this.add(mainSearchFilter.getWidget()); + this.pnlButtons.setOpaque(false); + FSkin.get(this.pnlButtons).setMatteBorder(1, 0, 1, 0, FSkin.getColor(Colors.CLR_TEXT)); + this.add(this.pnlButtons); + this.add(this.btnFilters); + this.add(this.lblRatio); this.add(this.tableScroller); + final Runnable cmdAddCurrentSearch = new Runnable() { + @Override + public void run() { + ItemFilter searchFilter = mainSearchFilter.createCopy(); + if (searchFilter != null) { + lockFiltering = true; //prevent updating filtering from this change + addFilter(searchFilter); + mainSearchFilter.reset(); + lockFiltering = false; + } + } + }; + + this.mainSearchFilter.getMainComponent().addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == 10) { + if (e.isControlDown() || e.isMetaDown()) { + cmdAddCurrentSearch.run(); + } + } + } + }); + //setup command for btnAddFilter final Command addFilterCommand = new Command() { @Override @@ -121,34 +196,35 @@ public abstract class ItemManager extends JPanel { JPopupMenu menu = new JPopupMenu("FilterMenu"); GuiUtils.addMenuItem(menu, "Current text search", KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), - new Runnable() { - @Override - public void run() { - ItemFilter searchFilter = createSearchFilter(txtSearch.getText()); - if (searchFilter != null) { - addFilter(searchFilter); - } - } - }, !txtSearch.isEmpty()); + cmdAddCurrentSearch, !mainSearchFilter.isEmpty()); buildFilterMenu(menu); - menu.show(btnAddFilter, 0, btnAddFilter.getHeight()); + menu.show(btnFilters, 0, btnFilters.getHeight()); } }; - this.btnAddFilter.setCommand(addFilterCommand); - this.btnAddFilter.setRightClickCommand(addFilterCommand); //show menu on right-click too + this.btnFilters.setCommand(addFilterCommand); + this.btnFilters.setRightClickCommand(addFilterCommand); //show menu on right-click too } @Override public void doLayout() { - //int number = 0; + int number = 0; + StringBuilder logicBuilder = new StringBuilder(); LayoutHelper helper = new LayoutHelper(this); - /*for (ItemFilter filter : this.orderedFilters) { - filter.updatePanelTitle(++number); + for (ItemFilter filter : this.orderedFilters) { + filter.setNumber(++number); + logicBuilder.append(number + "&"); helper.fillLine(filter.getPanel(), ItemFilter.PANEL_HEIGHT); } + this.txtFilterLogic.setText(logicBuilder.toString()); helper.newLine(); - helper.include(this.btnAddFilter, 30, FTextField.HEIGHT); - helper.include(this.txtSearch, 0.5f, FTextField.HEIGHT);*/ + helper.include(this.chkEnableFilters, 41, FTextField.HEIGHT); + helper.offset(-1, 0); //ensure widgets line up + helper.include(this.txtFilterLogic, this.txtFilterLogic.getAutoSizeWidth(), FTextField.HEIGHT); + helper.fillLine(this.mainSearchFilter.getWidget(), ItemFilter.PANEL_HEIGHT); + helper.newLine(-3); + helper.fillLine(this.pnlButtons, this.pnlButtons.getComponentCount() > 0 ? 32: 1); //just show border if no bottoms + helper.include(this.btnFilters, 61, FTextField.HEIGHT); + helper.fillLine(this.lblRatio, FTextField.HEIGHT); helper.fill(this.tableScroller); } @@ -356,17 +432,7 @@ public abstract class ItemManager extends JPanel { return this.model.getItems(); } - /** - * - * getStatLabel. - * - * @param s - */ - public FLabel getStatLabel(SItemManagerUtil.StatTypes s) { - return this.statLabels.get(s); - } - - protected abstract ItemFilter createSearchFilter(String text); + protected abstract ItemFilter createSearchFilter(); protected abstract void buildFilterMenu(JPopupMenu menu); protected > F getFilter(Class filterClass) { @@ -374,7 +440,7 @@ public abstract class ItemManager extends JPanel { } @SuppressWarnings("unchecked") - public void addFilter(ItemFilter filter) { + public void addFilter(final ItemFilter filter) { final Class> filterClass = (Class>) filter.getClass(); List> classFilters = this.filters.get(filterClass); if (classFilters == null) { @@ -385,10 +451,20 @@ public abstract class ItemManager extends JPanel { //if filter with the same class already exists, try to merge if allowed //NOTE: can always use first filter for these checks since if //merge is supported, only one will ever exist - ItemFilter existingFilter = classFilters.get(0); + final ItemFilter existingFilter = classFilters.get(0); if (existingFilter.merge(filter)) { - //if new filter merged with existing filter, just update layout - this.revalidate(); + //if new filter merged with existing filter, just refresh the widget + existingFilter.refreshWidget(); + + if (!this.lockFiltering) { //apply filters and focus existing filter's main component if filtering not locked + buildFilterPredicate(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + existingFilter.getMainComponent().requestFocusInWindow(); + } + }); + } return; } } @@ -396,6 +472,16 @@ public abstract class ItemManager extends JPanel { orderedFilters.add(filter); this.add(filter.getPanel()); this.revalidate(); + + if (!this.lockFiltering) { //apply filters and focus filter's main component if filtering not locked + buildFilterPredicate(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + filter.getMainComponent().requestFocusInWindow(); + } + }); + } } @SuppressWarnings("unchecked") @@ -409,15 +495,28 @@ public abstract class ItemManager extends JPanel { orderedFilters.remove(filter); this.remove(filter.getPanel()); this.revalidate(); + buildFilterPredicate(); } } public void buildFilterPredicate() { - /* - this.filterPredicate = ?; + if (this.lockFiltering) { return; } + + List> predicates = new ArrayList>(); + predicates.add(Predicates.instanceOf(this.genericType)); + + for (ItemFilter filter : this.orderedFilters) { //TODO: Support custom filter logic + if (filter.isEnabled() && !filter.isEmpty()) { + predicates.add(filter.buildPredicate()); + } + } + if (!this.mainSearchFilter.isEmpty()) { + predicates.add(mainSearchFilter.buildPredicate()); + } + this.filterPredicate = predicates.size() == 0 ? null : Predicates.and(predicates); if (this.pool != null) { this.updateView(true); - }*/ + } } /** @@ -429,19 +528,6 @@ public abstract class ItemManager extends JPanel { return this.filterPredicate == null; } - /** - * - * setFilterPredicate. - * - * @param filterToSet - */ - public void setFilterPredicate(final Predicate filterPredicate0) { - this.filterPredicate = filterPredicate0; - if (this.pool != null) { - this.updateView(true); - } - } - /** * * updateView. @@ -459,18 +545,34 @@ public abstract class ItemManager extends JPanel { Predicate> filterForPool = Predicates.compose(this.filterPredicate, this.pool.FN_GET_KEY); Iterable> items = Aggregates.uniqueByLast(Iterables.filter(this.pool, filterForPool), this.pool.FN_GET_NAME); this.model.addItems(items); - } else if (useFilter) { + } + else if (useFilter) { Predicate> pred = Predicates.compose(this.filterPredicate, this.pool.FN_GET_KEY); this.model.addItems(Iterables.filter(this.pool, pred)); - } else if (this.wantUnique) { + } + else if (this.wantUnique) { Iterable> items = Aggregates.uniqueByLast(this.pool, this.pool.FN_GET_NAME); this.model.addItems(items); - } else if (!useFilter && bForceFilter) { + } + else if (!useFilter && bForceFilter) { this.model.addItems(this.pool); } this.table.getTableModel().refreshSort(); + for (ItemFilter filter : this.orderedFilters) { + filter.afterFiltersApplied(); + } + + int total; + if (this.wantUnique) { + total = Aggregates.uniqueCount(this.pool, this.pool.FN_GET_NAME); + } + else { + total = this.pool.countAll(); + } + this.lblRatio.setText(this.getFilteredItems().countAll() + " / " + total); + //select first row if no row already selected SwingUtilities.invokeLater(new Runnable() { @Override @@ -482,6 +584,16 @@ public abstract class ItemManager extends JPanel { }); } + /** + * + * getPnlButtons. + * + * @return panel to put any custom buttons on + */ + public JPanel getPnlButtons() { + return this.pnlButtons; + } + /** * * getWantUnique. @@ -553,6 +665,15 @@ public abstract class ItemManager extends JPanel { this.table.requestFocusInWindow(); } + /** + * + * focusSearch. + * + */ + public void focusSearch() { + this.mainSearchFilter.getMainComponent().requestFocusInWindow(); + } + public void addSelectionListener(ListSelectionListener listener) { selectionListeners.remove(listener); //ensure listener not added multiple times selectionListeners.add(listener); diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SFilterUtil.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SFilterUtil.java index 127a696ec70..bb59885d94c 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SFilterUtil.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SFilterUtil.java @@ -4,8 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.commons.lang3.tuple.Pair; - import com.google.common.base.Predicate; import com.google.common.base.Predicates; @@ -13,12 +11,8 @@ import forge.card.CardRules; import forge.card.CardRulesPredicates; import forge.card.CardRulesPredicates.Presets; import forge.card.MagicColor; -import forge.gui.deckeditor.views.VCardCatalog; -import forge.gui.deckeditor.views.VCardCatalog.RangeTypes; import forge.gui.toolbox.FLabel; -import forge.gui.toolbox.FSpinner; import forge.item.PaperCard; -import forge.util.ComparableOp; import forge.util.PredicateString.StringOp; /** @@ -139,39 +133,7 @@ public class SFilterUtil { return Predicates.compose(textFilter, PaperCard.FN_GET_RULES); } - private static Predicate getCardRulesFieldPredicate(int min, int max, CardRulesPredicates.LeafNumber.CardField field) { - boolean hasMin = 0 != min; - boolean hasMax = 10 != max; - - Predicate pMin = !hasMin ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.GT_OR_EQUAL, min); - Predicate pMax = !hasMax ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.LT_OR_EQUAL, max); - - return optimizedAnd(pMin, pMax); - } - - private static Predicate optimizedAnd(Predicate p1, Predicate p2) { + public static Predicate optimizedAnd(Predicate p1, Predicate p2) { return p1 == null ? p2 : (p2 == null ? p1 : Predicates.and(p1, p2)); } - - /** - * builds a filter for an interval on a card field - */ - public static Predicate buildIntervalFilter( - Map> spinners, VCardCatalog.RangeTypes field) { - Pair sPair = spinners.get(field); - Predicate fieldFilter = getCardRulesFieldPredicate( - Integer.valueOf(sPair.getLeft().getValue().toString()), - Integer.valueOf(sPair.getRight().getValue().toString()), field.cardField); - - if (null != fieldFilter && VCardCatalog.RangeTypes.CMC != field) - { - fieldFilter = Predicates.and(fieldFilter, CardRulesPredicates.Presets.IS_CREATURE); - } - - if (fieldFilter == null) { - return Predicates.alwaysTrue(); - } else { - return Predicates.compose(fieldFilter, PaperCard.FN_GET_RULES); - } - } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerIO.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerIO.java index 1850f8391c4..25c17238a59 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerIO.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerIO.java @@ -44,7 +44,6 @@ public class SItemManagerIO { /** Preferences (must match with PREFS file). */ public enum EditorPreference { - stats_deck, display_unique_only, elastic_columns } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerUtil.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerUtil.java index dd26ca5d7b7..545a5cc3fbd 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerUtil.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/SItemManagerUtil.java @@ -1,19 +1,14 @@ package forge.gui.toolbox.itemmanager; import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; import forge.card.CardRules; import forge.card.CardRulesPredicates; +import forge.gui.deckeditor.controllers.ACEditorBase; import forge.gui.deckeditor.views.VCardCatalog; import forge.gui.deckeditor.views.VCurrentDeck; import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FSkin.SkinImage; -import forge.item.PaperCard; -import forge.item.InventoryItem; -import forge.util.Aggregates; -import forge.util.ItemPoolView; import forge.util.TextUtil; @@ -76,40 +71,13 @@ public final class SItemManagerUtil { return (int) Math.round((double) (x0 * 100) / (double) y0); } - private static final Predicate totalPred = Predicates.instanceOf(PaperCard.class); - private static final Predicate packPred = Predicates.not(totalPred); - - /** - * setStats. - * - * @param   the generic type - * @param itemManager   {@link forge.gui.toolbox.itemmanager.ItemManager} - */ - public static void setStats(final ItemManager itemManager) { - final ItemPoolView items = itemManager.getFilteredItems(); - for (StatTypes s : StatTypes.values()) { - switch (s) { - case TOTAL: - itemManager.getStatLabel(s).setText(String.valueOf( - Aggregates.sum(Iterables.filter(items, Predicates.compose(totalPred, items.FN_GET_KEY)), items.FN_GET_COUNT))); - break; - case PACK: - itemManager.getStatLabel(s).setText(String.valueOf( - Aggregates.sum(Iterables.filter(items, Predicates.compose(packPred, items.FN_GET_KEY)), items.FN_GET_COUNT))); - break; - default: - itemManager.getStatLabel(s).setText(String.valueOf(items.countAll(Predicates.compose(s.predicate, PaperCard.FN_GET_RULES), PaperCard.class))); - } - } - } - /** * Resets components that may have been changed * by various configurations of the deck editor. */ - public static void resetUI() { - VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setVisible(true); - VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4().setVisible(true); + public static void resetUI(ACEditorBase editor) { + editor.getBtnAdd4().setVisible(true); + editor.getBtnRemove4().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getBtnSave().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getBtnSaveAs().setVisible(true); @@ -126,7 +94,7 @@ public final class SItemManagerUtil { VCardCatalog.SINGLETON_INSTANCE.getTabLabel().setText("Card Catalog"); VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setVisible(true); - VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(false); + editor.getBtnCycleSection().setVisible(false); VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().setVisible(true); VCurrentDeck.SINGLETON_INSTANCE.getLblTitle().setText("Title:"); diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardCMCFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardCMCFilter.java index 7b5960e4ddd..591b39dbf6c 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardCMCFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardCMCFilter.java @@ -1,7 +1,10 @@ package forge.gui.toolbox.itemmanager.filters; -import javax.swing.JPanel; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import forge.card.CardRules; +import forge.card.CardRulesPredicates; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.PaperCard; @@ -10,23 +13,26 @@ import forge.item.PaperCard; * */ public class CardCMCFilter extends ValueRangeFilter { - public CardCMCFilter(ItemManager itemManager0) { super(itemManager0); } @Override - protected String getTitle() { - return "Card CMC"; + public ItemFilter createCopy() { + return new CardCMCFilter(itemManager); } @Override - protected void buildPanel(JPanel panel) { - + protected String getCaption() { + return "CMC"; } @Override - protected void onRemoved() { - + public Predicate buildPredicate() { + Predicate predicate = getCardRulesFieldPredicate(CardRulesPredicates.LeafNumber.CardField.CMC); + if (predicate == null) { + return Predicates.alwaysTrue(); + } + return Predicates.compose(predicate, PaperCard.FN_GET_RULES); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardColorFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardColorFilter.java index 1f27c0ba6c3..5ea1a9d0ca0 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardColorFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardColorFilter.java @@ -2,7 +2,15 @@ package forge.gui.toolbox.itemmanager.filters; import javax.swing.JPanel; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; + +import forge.card.CardRules; +import forge.card.CardRulesPredicates; +import forge.card.MagicColor; +import forge.card.CardRulesPredicates.Presets; import forge.gui.toolbox.itemmanager.ItemManager; +import forge.gui.toolbox.itemmanager.SFilterUtil; import forge.gui.toolbox.itemmanager.SItemManagerUtil.StatTypes; import forge.item.PaperCard; @@ -10,29 +18,77 @@ import forge.item.PaperCard; * TODO: Write javadoc for this type. * */ -public class CardColorFilter extends ToggleButtonsFilter { +public class CardColorFilter extends StatTypeFilter { public CardColorFilter(ItemManager itemManager0) { super(itemManager0); } @Override - protected String getTitle() { - return "Card Color"; + public ItemFilter createCopy() { + return new CardColorFilter(itemManager); } @Override - protected void buildPanel(JPanel panel) { - addToggleButton(panel, StatTypes.WHITE); - addToggleButton(panel, StatTypes.BLUE); - addToggleButton(panel, StatTypes.BLACK); - addToggleButton(panel, StatTypes.RED); - addToggleButton(panel, StatTypes.GREEN); - addToggleButton(panel, StatTypes.COLORLESS); - addToggleButton(panel, StatTypes.MULTICOLOR); + protected void buildWidget(JPanel widget) { + addToggleButton(widget, StatTypes.WHITE); + addToggleButton(widget, StatTypes.BLUE); + addToggleButton(widget, StatTypes.BLACK); + addToggleButton(widget, StatTypes.RED); + addToggleButton(widget, StatTypes.GREEN); + addToggleButton(widget, StatTypes.COLORLESS); + addToggleButton(widget, StatTypes.MULTICOLOR); } @Override - protected void onRemoved() { - + public final Predicate buildPredicate() { + byte colors = 0; + + if (buttonMap.get(StatTypes.WHITE).getSelected()) { + colors |= MagicColor.WHITE; + } + if (buttonMap.get(StatTypes.BLUE).getSelected()) { + colors |= MagicColor.BLUE; + } + if (buttonMap.get(StatTypes.BLACK).getSelected()) { + colors |= MagicColor.BLACK; + } + if (buttonMap.get(StatTypes.RED).getSelected()) { + colors |= MagicColor.RED; + } + if (buttonMap.get(StatTypes.GREEN).getSelected()) { + colors |= MagicColor.GREEN; + } + + boolean wantColorless = buttonMap.get(StatTypes.COLORLESS).getSelected(); + boolean wantMulticolor = buttonMap.get(StatTypes.MULTICOLOR).getSelected(); + + Predicate preFinal = null; + if (wantMulticolor) { + if (colors == 0) { //handle showing all multi-color cards if all 5 colors are filtered + preFinal = Presets.IS_MULTICOLOR; + if (wantColorless) { + preFinal = Predicates.or(preFinal, Presets.IS_COLORLESS); + } + } + else if (colors != MagicColor.ALL_COLORS) { + preFinal = CardRulesPredicates.canCastWithAvailable(colors); + } + } + else if (colors != MagicColor.ALL_COLORS) { + preFinal = Predicates.and(CardRulesPredicates.canCastWithAvailable(colors), Predicates.not(Presets.IS_MULTICOLOR)); + } + if (!wantColorless) { + if (colors != 0 && colors != MagicColor.ALL_COLORS) { + //if colorless filtered out ensure phyrexian cards don't appear + //unless at least one of their colors is selected + preFinal = Predicates.and(preFinal, CardRulesPredicates.isColor(colors)); + } + preFinal = SFilterUtil.optimizedAnd(preFinal, Predicates.not(Presets.IS_COLORLESS)); + } + + if (preFinal == null) { + return Predicates.alwaysTrue(); + } + return Predicates.compose(preFinal, PaperCard.FN_GET_RULES); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardFormatFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardFormatFilter.java index 440da339bf0..4aebc54276d 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardFormatFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardFormatFilter.java @@ -1,10 +1,15 @@ package forge.gui.toolbox.itemmanager.filters; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; -import javax.swing.JPanel; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import forge.Singletons; +import forge.card.CardEdition; import forge.game.GameFormat; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.PaperCard; @@ -14,17 +19,104 @@ import forge.item.PaperCard; * */ public class CardFormatFilter extends ListLabelFilter { - private final Set formats = new HashSet(); + protected boolean allowReprints = true; + protected final Set formats = new HashSet(); + public CardFormatFilter(ItemManager itemManager0) { + super(itemManager0); + } public CardFormatFilter(ItemManager itemManager0, GameFormat format0) { super(itemManager0); this.formats.add(format0); } - + + @Override + protected String getTooltip() { + Set sets = new HashSet(); + Set bannedCards = new HashSet(); + + for (GameFormat format : this.formats) { + List formatSets = format.getAllowedSetCodes(); + if (formatSets != null) { + sets.addAll(formatSets); + } + List formatBannedCards = format.getBannedCardNames(); + if (formatBannedCards != null) { + bannedCards.addAll(formatBannedCards); + } + } + + //use HTML tooltips so we can insert line breaks + int lastLen = 0; + int lineLen = 0; + StringBuilder tooltip = new StringBuilder("Sets:"); + if (sets.isEmpty()) { + tooltip.append(" All"); + } + else { + CardEdition.Collection editions = Singletons.getMagicDb().getEditions(); + + for (String code : sets) { + // don't let a single line get too long + if (50 < lineLen) { + tooltip.append("
"); + lastLen += lineLen; + lineLen = 0; + } + + CardEdition edition = editions.get(code); + tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),"); + lineLen = tooltip.length() - lastLen; + } + + // chop off last comma + tooltip.delete(tooltip.length() - 1, tooltip.length()); + + if (this.allowReprints) { + tooltip.append("

Allowing identical cards from other sets"); + } + } + + if (!bannedCards.isEmpty()) { + tooltip.append("

Banned:"); + lastLen += lineLen; + lineLen = 0; + + for (String cardName : bannedCards) { + // don't let a single line get too long + if (50 < lineLen) { + tooltip.append("
"); + lastLen += lineLen; + lineLen = 0; + } + + tooltip.append(" ").append(cardName).append(";"); + lineLen = tooltip.length() - lastLen; + } + + // chop off last semicolon + tooltip.delete(tooltip.length() - 1, tooltip.length()); + } + tooltip.append(""); + return tooltip.toString(); + } + + @Override + public void reset() { + this.formats.clear(); + } + + @Override + public ItemFilter createCopy() { + CardFormatFilter copy = new CardFormatFilter(itemManager); + copy.formats.addAll(this.formats); + return copy; + } + public static boolean canAddFormat(GameFormat format, ItemFilter existingFilter) { return existingFilter == null || !((CardFormatFilter)existingFilter).formats.contains(format); } - + /** * Merge the given filter with this filter if possible * @param filter @@ -35,22 +127,18 @@ public class CardFormatFilter extends ListLabelFilter { public boolean merge(ItemFilter filter) { CardFormatFilter cardFormatFilter = (CardFormatFilter)filter; this.formats.addAll(cardFormatFilter.formats); + this.allowReprints = cardFormatFilter.allowReprints; return true; } @Override - protected String getTitle() { - return "Card Format"; + protected String getCaption() { + return "Format"; } @Override - protected void buildPanel(JPanel panel) { - - } - - @Override - protected void onRemoved() { - + protected int getCount() { + return this.formats.size(); } @Override @@ -61,4 +149,13 @@ public class CardFormatFilter extends ListLabelFilter { } return strings; } + + @Override + public final Predicate buildPredicate() { + List> predicates = new ArrayList>(); + for (GameFormat f : this.formats) { + predicates.add(allowReprints ? f.getFilterRules() : f.getFilterPrinted()); + } + return Predicates.or(predicates); + } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardPowerFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardPowerFilter.java index 1e254f6f6e4..aa7c31c89c0 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardPowerFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardPowerFilter.java @@ -1,7 +1,10 @@ package forge.gui.toolbox.itemmanager.filters; -import javax.swing.JPanel; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import forge.card.CardRules; +import forge.card.CardRulesPredicates; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.PaperCard; @@ -15,17 +18,22 @@ public class CardPowerFilter extends ValueRangeFilter { } @Override - protected String getTitle() { - return "Card Power"; + public ItemFilter createCopy() { + return new CardPowerFilter(itemManager); } @Override - protected void buildPanel(JPanel panel) { - + protected String getCaption() { + return "Power"; } @Override - protected void onRemoved() { - + public Predicate buildPredicate() { + Predicate predicate = getCardRulesFieldPredicate(CardRulesPredicates.LeafNumber.CardField.POWER); + if (predicate == null) { + return Predicates.alwaysTrue(); + } + predicate = Predicates.and(predicate, CardRulesPredicates.Presets.IS_CREATURE); + return Predicates.compose(predicate, PaperCard.FN_GET_RULES); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardQuestWorldFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardQuestWorldFilter.java index 2ef9e322ea1..e68bcdc5bb6 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardQuestWorldFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardQuestWorldFilter.java @@ -3,9 +3,8 @@ package forge.gui.toolbox.itemmanager.filters; import java.util.HashSet; import java.util.Set; -import javax.swing.JPanel; - import forge.Singletons; +import forge.game.GameFormat; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.PaperCard; import forge.quest.QuestWorld; @@ -14,14 +13,34 @@ import forge.quest.QuestWorld; * TODO: Write javadoc for this type. * */ -public class CardQuestWorldFilter extends ListLabelFilter { +public class CardQuestWorldFilter extends CardFormatFilter { private final Set questWorlds = new HashSet(); + public CardQuestWorldFilter(ItemManager itemManager0) { + super(itemManager0); + } public CardQuestWorldFilter(ItemManager itemManager0, QuestWorld questWorld0) { super(itemManager0); this.questWorlds.add(questWorld0); + this.formats.add(getQuestWorldFormat(questWorld0)); } - + + @Override + public ItemFilter createCopy() { + CardQuestWorldFilter copy = new CardQuestWorldFilter(itemManager); + copy.questWorlds.addAll(this.questWorlds); + for (QuestWorld w : this.questWorlds) { + copy.formats.add(getQuestWorldFormat(w)); + } + return copy; + } + + @Override + public void reset() { + this.questWorlds.clear(); + super.reset(); + } + public static boolean canAddQuestWorld(QuestWorld questWorld, ItemFilter existingFilter) { if (questWorld.getFormat() == null && Singletons.getModel().getQuest().getMainFormat() == null) { return false; //must have format @@ -29,11 +48,6 @@ public class CardQuestWorldFilter extends ListLabelFilter { return existingFilter == null || !((CardQuestWorldFilter)existingFilter).questWorlds.contains(questWorld); } - @Override - protected String getTitle() { - return "Quest World"; - } - /** * Merge the given filter with this filter if possible * @param filter @@ -44,19 +58,22 @@ public class CardQuestWorldFilter extends ListLabelFilter { public boolean merge(ItemFilter filter) { CardQuestWorldFilter cardQuestWorldFilter = (CardQuestWorldFilter)filter; this.questWorlds.addAll(cardQuestWorldFilter.questWorlds); + for (QuestWorld w : cardQuestWorldFilter.questWorlds) { + this.formats.add(getQuestWorldFormat(w)); + } return true; } @Override - protected void buildPanel(JPanel panel) { - + protected String getCaption() { + return "Quest World"; } @Override - protected void onRemoved() { - + protected int getCount() { + return this.questWorlds.size(); } - + @Override protected Iterable getList() { Set strings = new HashSet(); @@ -65,4 +82,13 @@ public class CardQuestWorldFilter extends ListLabelFilter { } return strings; } + + private GameFormat getQuestWorldFormat(QuestWorld w) { + GameFormat format = w.getFormat(); + if (format == null) { + //assumes that no world other than the main world will have a null format + format = Singletons.getModel().getQuest().getMainFormat(); + } + return format; + } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSearchFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSearchFilter.java index c5b63f1f505..64e2da50835 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSearchFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSearchFilter.java @@ -1,8 +1,19 @@ package forge.gui.toolbox.itemmanager.filters; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + import javax.swing.JPanel; +import com.google.common.base.Predicate; + +import forge.Command; +import forge.gui.toolbox.FComboBoxWrapper; +import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FTextField; +import forge.gui.toolbox.LayoutHelper; import forge.gui.toolbox.itemmanager.ItemManager; +import forge.gui.toolbox.itemmanager.SFilterUtil; import forge.item.PaperCard; /** @@ -10,22 +21,101 @@ import forge.item.PaperCard; * */ public class CardSearchFilter extends TextSearchFilter { - public CardSearchFilter(ItemManager itemManager0, String text0) { - super(itemManager0, text0); + private FComboBoxWrapper cbSearchMode; + private FLabel btnName, btnType, btnText; + + public CardSearchFilter(ItemManager itemManager0) { + super(itemManager0); } @Override - protected String getTitle() { - return "Card Search"; + public ItemFilter createCopy() { + CardSearchFilter copy = new CardSearchFilter(itemManager); + copy.getWidget(); //initialize widget + copy.txtSearch.setText(this.txtSearch.getText()); + copy.cbSearchMode.setSelectedIndex(this.cbSearchMode.getSelectedIndex()); + copy.btnName.setSelected(this.btnName.getSelected()); + copy.btnType.setSelected(this.btnType.getSelected()); + copy.btnText.setSelected(this.btnText.getSelected()); + return copy; } @Override - protected void buildPanel(JPanel panel) { + public void reset() { + super.reset(); + this.cbSearchMode.setSelectedIndex(0); + this.btnName.setSelected(true); + this.btnType.setSelected(true); + this.btnText.setSelected(true); + } + /** + * Merge the given filter with this filter if possible + * @param filter + * @return true if filter merged in or to suppress adding a new filter, false to allow adding new filter + */ + @Override + @SuppressWarnings("rawtypes") + public boolean merge(ItemFilter filter) { + return false; } @Override - protected void onRemoved() { - + protected final void buildWidget(JPanel widget) { + super.buildWidget(widget); + + cbSearchMode = new FComboBoxWrapper(); + cbSearchMode.addItem("in"); + cbSearchMode.addItem("not in"); + cbSearchMode.addTo(widget); + cbSearchMode.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent arg0) { + if (!txtSearch.isEmpty()) { + applyChange(); + } + } + }); + + btnName = addButton(widget, "Name"); + btnType = addButton(widget, "Type"); + btnText = addButton(widget, "Text"); + } + + @Override + protected void doWidgetLayout(LayoutHelper helper) { + final int comboBoxWidth = 61; + final int buttonWidth = 51; + + helper.fillLine(txtSearch, FTextField.HEIGHT, comboBoxWidth + buttonWidth * 3 + 12); //leave space for combo box and buttons + helper.include(cbSearchMode.getComponent(), comboBoxWidth, FTextField.HEIGHT); + helper.include(btnName, buttonWidth, FTextField.HEIGHT); + helper.include(btnType, buttonWidth, FTextField.HEIGHT); + helper.include(btnText, buttonWidth, FTextField.HEIGHT); + } + + @SuppressWarnings("serial") + private FLabel addButton(JPanel widget, String text) { + FLabel button = new FLabel.Builder().text(text).hoverable().selectable().selected().build(); + + button.setCommand(new Command() { + @Override + public void run() { + applyChange(); + } + }); + + widget.add(button); + return button; + } + + @Override + public Predicate buildPredicate() { + return SFilterUtil.buildTextFilter( + txtSearch.getText(), + cbSearchMode.getSelectedIndex() != 0, + btnName.getSelected(), + btnType.getSelected(), + btnText.getSelected()); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSetFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSetFilter.java index 2b968073cdc..0e939dbc7f2 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSetFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardSetFilter.java @@ -4,8 +4,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; -import javax.swing.JPanel; - +import forge.game.GameFormat; import forge.gui.home.quest.DialogChooseSets; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.PaperCard; @@ -14,19 +13,27 @@ import forge.item.PaperCard; * TODO: Write javadoc for this type. * */ -public class CardSetFilter extends ListLabelFilter { +public class CardSetFilter extends CardFormatFilter { private final Set sets = new HashSet(); - public CardSetFilter(ItemManager itemManager0, Collection sets) { + public CardSetFilter(ItemManager itemManager0, Collection sets0, boolean allowReprints0) { super(itemManager0); - this.sets.addAll(sets); + this.sets.addAll(sets0); + this.formats.add(new GameFormat(null, this.sets, null)); + this.allowReprints = allowReprints0; } @Override - protected String getTitle() { - return "Card Set"; + public ItemFilter createCopy() { + return new CardSetFilter(itemManager, this.sets, this.allowReprints); } - + + @Override + public void reset() { + this.sets.clear(); + super.reset(); + } + /** * Merge the given filter with this filter if possible * @param filter @@ -37,9 +44,12 @@ public class CardSetFilter extends ListLabelFilter { public boolean merge(ItemFilter filter) { CardSetFilter cardSetFilter = (CardSetFilter)filter; this.sets.addAll(cardSetFilter.sets); + this.allowReprints = cardSetFilter.allowReprints; + this.formats.clear(); + this.formats.add(new GameFormat(null, this.sets, null)); return true; } - + public void edit() { final DialogChooseSets dialog = new DialogChooseSets(this.sets, null, true); dialog.setOkCallback(new Runnable() { @@ -47,18 +57,21 @@ public class CardSetFilter extends ListLabelFilter { public void run() { sets.clear(); sets.addAll(dialog.getSelectedSets()); + allowReprints = dialog.getWantReprints(); + formats.clear(); + formats.add(new GameFormat(null, sets, null)); } }); } @Override - protected void buildPanel(JPanel panel) { - + protected String getCaption() { + return "Set"; } @Override - protected void onRemoved() { - + protected int getCount() { + return this.sets.size(); } @Override diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardToughnessFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardToughnessFilter.java index 58715bb72d0..4b4fd0f509b 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardToughnessFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardToughnessFilter.java @@ -1,7 +1,10 @@ package forge.gui.toolbox.itemmanager.filters; -import javax.swing.JPanel; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import forge.card.CardRules; +import forge.card.CardRulesPredicates; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.PaperCard; @@ -15,17 +18,22 @@ public class CardToughnessFilter extends ValueRangeFilter { } @Override - protected String getTitle() { - return "Card Toughness"; + public ItemFilter createCopy() { + return new CardToughnessFilter(itemManager); } @Override - protected void buildPanel(JPanel panel) { - + protected String getCaption() { + return "Toughness"; } @Override - protected void onRemoved() { - + public Predicate buildPredicate() { + Predicate predicate = getCardRulesFieldPredicate(CardRulesPredicates.LeafNumber.CardField.TOUGHNESS); + if (predicate == null) { + return Predicates.alwaysTrue(); + } + predicate = Predicates.and(predicate, CardRulesPredicates.Presets.IS_CREATURE); + return Predicates.compose(predicate, PaperCard.FN_GET_RULES); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardTypeFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardTypeFilter.java index 46323dff851..967acb91aa2 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardTypeFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/CardTypeFilter.java @@ -1,8 +1,16 @@ package forge.gui.toolbox.itemmanager.filters; +import java.util.ArrayList; +import java.util.List; + import javax.swing.JPanel; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; + +import forge.card.CardRules; import forge.gui.toolbox.itemmanager.ItemManager; +import forge.gui.toolbox.itemmanager.SItemManagerUtil; import forge.gui.toolbox.itemmanager.SItemManagerUtil.StatTypes; import forge.item.PaperCard; @@ -10,29 +18,40 @@ import forge.item.PaperCard; * TODO: Write javadoc for this type. * */ -public class CardTypeFilter extends ToggleButtonsFilter { +public class CardTypeFilter extends StatTypeFilter { public CardTypeFilter(ItemManager itemManager0) { super(itemManager0); } @Override - protected String getTitle() { - return "Card Type"; + public ItemFilter createCopy() { + return new CardTypeFilter(itemManager); } @Override - protected void buildPanel(JPanel panel) { - addToggleButton(panel, StatTypes.LAND); - addToggleButton(panel, StatTypes.ARTIFACT); - addToggleButton(panel, StatTypes.CREATURE); - addToggleButton(panel, StatTypes.ENCHANTMENT); - addToggleButton(panel, StatTypes.PLANESWALKER); - addToggleButton(panel, StatTypes.INSTANT); - addToggleButton(panel, StatTypes.SORCERY); + protected void buildWidget(JPanel widget) { + addToggleButton(widget, StatTypes.LAND); + addToggleButton(widget, StatTypes.ARTIFACT); + addToggleButton(widget, StatTypes.CREATURE); + addToggleButton(widget, StatTypes.ENCHANTMENT); + addToggleButton(widget, StatTypes.PLANESWALKER); + addToggleButton(widget, StatTypes.INSTANT); + addToggleButton(widget, StatTypes.SORCERY); } @Override - protected void onRemoved() { - + public final Predicate buildPredicate() { + final List> types = new ArrayList>(); + + for (SItemManagerUtil.StatTypes s : buttonMap.keySet()) { + if (buttonMap.get(s).getSelected()) { + types.add(s.predicate); + } + } + + if (types.size() == 7) { + return Predicates.alwaysTrue(); + } + return Predicates.compose(Predicates.or(types), PaperCard.FN_GET_RULES); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ItemFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ItemFilter.java index e7392c7508b..4e551ae0706 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ItemFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ItemFilter.java @@ -1,12 +1,31 @@ package forge.gui.toolbox.itemmanager.filters; +import java.awt.BasicStroke; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.SwingUtilities; -import net.miginfocom.swing.MigLayout; -import forge.Command; -import forge.gui.toolbox.FLabel; +import com.google.common.base.Predicate; + +import forge.gui.framework.ILocalRepaint; import forge.gui.toolbox.FSkin; +import forge.gui.toolbox.FSkin.Colors; +import forge.gui.toolbox.FSkin.JComponentSkin; +import forge.gui.toolbox.FSkin.JLabelSkin; +import forge.gui.toolbox.FSkin.SkinColor; +import forge.gui.toolbox.FTextField; +import forge.gui.toolbox.LayoutHelper; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.InventoryItem; @@ -15,55 +34,101 @@ import forge.item.InventoryItem; * */ public abstract class ItemFilter { - private final ItemManager itemManager; - private JPanel panel; - private JLabel lblPanelTitle; - - public static int PANEL_HEIGHT = 30; - + public final static int PANEL_HEIGHT = 28; + + public static void layoutCheckbox(JCheckBox cb) { + JComponentSkin skin = FSkin.get(cb); + skin.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); + skin.setFont(FSkin.getFont(12)); + cb.setOpaque(false); + cb.setFocusable(false); + } + + protected final ItemManager itemManager; + private FilterPanel panel; + private Widget widget; + private final JCheckBox chkEnable = new JCheckBox(); + private RemoveButton btnRemove; + protected ItemFilter(ItemManager itemManager0) { this.itemManager = itemManager0; + this.chkEnable.setSelected(true); //enable by default } - - @SuppressWarnings("serial") + public JPanel getPanel() { if (this.panel == null) { - this.panel = new JPanel(new MigLayout("insets 0, gap 2")); - this.panel.setOpaque(false); - FSkin.get(this.panel).setMatteBorder(1, 2, 1, 2, FSkin.getColor(FSkin.Colors.CLR_TEXT)); - - this.lblPanelTitle = new FLabel.Builder().fontSize(10).build(); - this.panel.add(this.lblPanelTitle, "top"); - - //add button to remove filter - this.panel.add(new FLabel.Builder() - .text("X") - .fontSize(10) - .hoverable(true) - .tooltip("Remove filter") - .cmdClick(new Command() { - @Override - public void run() { - itemManager.removeFilter(ItemFilter.this); - ItemFilter.this.onRemoved(); - } - }).build(), "top"); - - this.buildPanel(panel); + this.panel = new FilterPanel(); + + layoutCheckbox(this.chkEnable); + this.chkEnable.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent arg0) { + updateEnabled(); + applyChange(); + } + }); + this.panel.add(this.chkEnable); + + getWidget(); //initialize widget + if (!isEnabled()) { + updateEnabled(); + } + this.panel.add(this.widget); + + this.btnRemove = new RemoveButton(); + this.panel.add(this.btnRemove); } return this.panel; } - - public void updatePanelTitle(int number) { - this.lblPanelTitle.setText(number + ". " + this.getTitle()); + + public JPanel getWidget() { + if (this.widget == null) { + this.widget = new Widget(); + this.buildWidget(this.widget); + } + return this.widget; } - - protected abstract String getTitle(); - + + public void refreshWidget() { + if (this.widget == null) { return; } + this.widget.removeAll(); + this.buildWidget(this.widget); + } + + public Component getMainComponent() { + return getWidget(); + } + + public void setNumber(int number) { + this.chkEnable.setText("(" + number + ")"); + } + + public boolean isEnabled() { + return this.chkEnable.isSelected(); + } + + public void setEnabled(boolean enabled0) { + this.chkEnable.setSelected(enabled0); + } + + public void updateEnabled() { + boolean enabled = this.isEnabled(); + for (Component comp : this.widget.getComponents()) { + comp.setEnabled(enabled); + } + } + protected void applyChange() { this.itemManager.buildFilterPredicate(); } - + + public abstract ItemFilter createCopy(); + public abstract boolean isEmpty(); + public abstract void reset(); + public abstract Predicate buildPredicate(); + public void afterFiltersApplied() { + } + /** * Merge the given filter with this filter if possible * @param filter @@ -71,7 +136,127 @@ public abstract class ItemFilter { */ @SuppressWarnings("rawtypes") public abstract boolean merge(ItemFilter filter); - - protected abstract void buildPanel(JPanel panel); - protected abstract void onRemoved(); + + protected abstract void buildWidget(JPanel widget); + protected abstract void doWidgetLayout(LayoutHelper helper); + + @SuppressWarnings("serial") + private class FilterPanel extends JPanel { + private FilterPanel() { + setLayout(null); + setOpaque(false); + FSkin.get(this).setMatteBorder(0, 0, 1, 0, FSkin.getColor(Colors.CLR_TEXT)); + } + + @Override + public void doLayout() { + LayoutHelper helper = new LayoutHelper(this); + int removeButtonSize = 17; + helper.include(chkEnable, 43, FTextField.HEIGHT); + helper.offset(-3, 0); //avoid extra padding between checkbox and widget + helper.fillLine(widget, PANEL_HEIGHT, removeButtonSize); //leave room for remove button + helper.offset(-3, (PANEL_HEIGHT - removeButtonSize) / 2 - 1); //shift position of remove button + helper.include(btnRemove, removeButtonSize, removeButtonSize); + } + } + + @SuppressWarnings("serial") + private class Widget extends JPanel { + private Widget() { + setLayout(null); + setOpaque(false); + } + + @Override + public void doLayout() { + LayoutHelper helper = new LayoutHelper(this); + ItemFilter.this.doWidgetLayout(helper); + } + } + + @SuppressWarnings("serial") + private class RemoveButton extends JLabel implements ILocalRepaint { + protected JLabelSkin skin = FSkin.get(this); + private final SkinColor iconColor = FSkin.getColor(Colors.CLR_TEXT); + private boolean pressed, hovered; + + private RemoveButton() { + setToolTipText("Remove filter"); + addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (!RemoveButton.this.isEnabled()) { return; } + if (SwingUtilities.isLeftMouseButton(e)) { + pressed = true; + repaintSelf(); + } + } + @Override + public void mouseReleased(MouseEvent e) { + if (pressed && SwingUtilities.isLeftMouseButton(e)) { + pressed = false; + if (hovered) { //only handle click if mouse released over button + repaintSelf(); + itemManager.focus(); + itemManager.removeFilter(ItemFilter.this); + } + } + } + @Override + public void mouseEntered(MouseEvent e) { + if (!RemoveButton.this.isEnabled()) { return; } + hovered = true; + repaintSelf(); + } + @Override + public void mouseExited(MouseEvent e) { + if (hovered) { + hovered = false; + repaintSelf(); + } + } + }); + } + + @Override + public void setEnabled(boolean enabled0) { + if (!enabled0 && hovered) { + hovered = false; //ensure hovered reset if disabled + } + super.setEnabled(enabled0); + } + + @Override + public void repaintSelf() { + final Dimension d = this.getSize(); + repaint(0, 0, d.width, d.height); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + + int thickness = 2; + int offset = 4; + int x1 = offset; + int y1 = offset; + int x2 = getWidth() - offset - 1; + int y2 = getHeight() - offset - 1; + + Graphics2D g2d = (Graphics2D) g; + if (hovered) { + if (pressed) { + g.translate(1, 1); //translate icon to give pressed button look + } + skin.setGraphicsColor(g2d, iconColor); + } + else { + skin.setGraphicsColor(g2d, iconColor.alphaColor(150)); + } + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(thickness)); + g2d.drawLine(x1, y1, x2, y2); + g2d.drawLine(x2, y1, x1, y2); + } + } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ListLabelFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ListLabelFilter.java index 3c4e671a6e0..a74c1c2aad5 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ListLabelFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ListLabelFilter.java @@ -1,38 +1,62 @@ package forge.gui.toolbox.itemmanager.filters; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FTextField; +import forge.gui.toolbox.LayoutHelper; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.InventoryItem; +import forge.util.TextUtil; /** * TODO: Write javadoc for this type. * */ public abstract class ListLabelFilter extends ItemFilter { - + private FLabel label; + protected ListLabelFilter(ItemManager itemManager0) { super(itemManager0); } - + + protected abstract String getCaption(); protected abstract Iterable getList(); - - public void buildPanel() { - StringBuilder label = new StringBuilder(); - boolean truncated = false; - for (String str : getList()) { - // don't let the full label get too long - if (label.length() < 32) { - label.append(" ").append(str).append(";"); - } else { - truncated = true; - break; - } - } - - // chop off last semicolons - label.delete(label.length() - 1, label.length()); - - if (truncated) { - label.append("..."); + protected abstract String getTooltip(); + protected abstract int getCount(); + + @Override + public final boolean isEmpty() { + return getCount() == 0; + } + + @Override + protected final void buildWidget(JPanel widget) { + StringBuilder labelBuilder = new StringBuilder(); + labelBuilder.append(getCaption()); + switch (getCount()) { + case 0: + labelBuilder.append(": All"); + break; + case 1: + labelBuilder.append(": " + getList().iterator().next()); + break; + default: + labelBuilder.append("s: " + TextUtil.join(getList(), ", ")); + break; } + label = new FLabel.Builder() + .text(labelBuilder.toString()) + .tooltip(getTooltip()) + .fontAlign(SwingConstants.LEFT) + .fontSize(12) + .build(); + widget.add(label); + } + + @Override + protected void doWidgetLayout(LayoutHelper helper) { + helper.fillLine(label, FTextField.HEIGHT); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/StatTypeFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/StatTypeFilter.java new file mode 100644 index 00000000000..82e783ecf93 --- /dev/null +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/StatTypeFilter.java @@ -0,0 +1,89 @@ +package forge.gui.toolbox.itemmanager.filters; + +import java.util.HashMap; +import java.util.Map; + +import javax.swing.JPanel; + +import com.google.common.base.Predicates; +import forge.Command; +import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.itemmanager.ItemManager; +import forge.gui.toolbox.itemmanager.SItemManagerUtil; +import forge.gui.toolbox.itemmanager.SItemManagerUtil.StatTypes; +import forge.item.InventoryItem; +import forge.item.PaperCard; +import forge.util.ItemPoolView; + +public abstract class StatTypeFilter extends ToggleButtonsFilter { + protected final Map buttonMap; + + public StatTypeFilter(ItemManager itemManager0) { + super(itemManager0); + buttonMap = new HashMap(); + } + + @SuppressWarnings("serial") + protected void addToggleButton(JPanel widget, final StatTypes st) { + final FLabel button = addToggleButton(widget, st.toLabelString(), st.img); + buttonMap.put(st, button); + + //hook so right-clicking a button toggles itself on and toggles off all other buttons + button.setRightClickCommand(new Command() { + @Override + public void run() { + lockFiltering = true; + boolean foundSelected = false; + for (Map.Entry btn : buttonMap.entrySet()) { + if (btn.getKey() != st) { + if (btn.getKey() == StatTypes.MULTICOLOR) { + switch (st) { + case WHITE: + case BLUE: + case BLACK: + case RED: + case GREEN: + //ensure multicolor filter selected after right-clicking a color filter + if (!btn.getValue().getSelected()) { + btn.getValue().setSelected(true); + } + continue; + default: + break; + } + } + if (btn.getValue().getSelected()) { + foundSelected = true; + btn.getValue().setSelected(false); + } + } + } + if (!button.getSelected()) { + button.setSelected(true); + } + else if (!foundSelected) { + //if statLabel only label in group selected, re-select all other labels in group + for (Map.Entry btn : buttonMap.entrySet()) { + if (btn.getKey() != st) { + if (!btn.getValue().getSelected()) { + btn.getValue().setSelected(true); + } + } + } + } + lockFiltering = false; + applyChange(); + } + }); + } + + @Override + public void afterFiltersApplied() { + final ItemPoolView items = itemManager.getFilteredItems(); + for (Map.Entry btn : buttonMap.entrySet()) { + int count = items.countAll(Predicates.compose(btn.getKey().predicate, PaperCard.FN_GET_RULES), PaperCard.class); + btn.getValue().setText(String.valueOf(count)); + } + getWidget().revalidate(); + } +} diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/TextSearchFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/TextSearchFilter.java index 45b0fb2364c..4ccf5160e51 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/TextSearchFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/TextSearchFilter.java @@ -1,8 +1,16 @@ package forge.gui.toolbox.itemmanager.filters; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + import javax.swing.JPanel; +import javax.swing.Timer; import forge.gui.toolbox.FTextField; +import forge.gui.toolbox.LayoutHelper; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.InventoryItem; @@ -11,13 +19,27 @@ import forge.item.InventoryItem; * */ public abstract class TextSearchFilter extends ItemFilter { - private String text; + protected FTextField txtSearch; - protected TextSearchFilter(ItemManager itemManager0, String text0) { + protected TextSearchFilter(ItemManager itemManager0) { super(itemManager0); - this.text = text0; } - + + @Override + public boolean isEmpty() { + return txtSearch.isEmpty(); + } + + @Override + public void reset() { + txtSearch.setText(""); + } + + @Override + public Component getMainComponent() { + return txtSearch; + } + /** * Merge the given filter with this filter if possible * @param filter @@ -28,9 +50,62 @@ public abstract class TextSearchFilter extends ItemFilt public boolean merge(ItemFilter filter) { return false; } - + @Override - protected void buildPanel(JPanel panel) { - panel.add(new FTextField.Builder().text(this.text).build()); + protected void buildWidget(JPanel widget) { + txtSearch = new FTextField.Builder().ghostText("Search").build(); + widget.add(txtSearch); + + txtSearch.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + super.keyPressed(e); + switch (e.getKeyCode()) { + case KeyEvent.VK_UP: + case KeyEvent.VK_DOWN: + case KeyEvent.VK_PAGE_UP: + case KeyEvent.VK_PAGE_DOWN: + //set focus to item manager when certain keys pressed + if (changeTimer.isRunning()) { + applyChange(); //apply change now if currently delayed + } + itemManager.focus(); + break; + case KeyEvent.VK_ENTER: + if (e.getModifiers() == 0) { + if (changeTimer.isRunning()) { + applyChange(); //apply change now if currently delayed + } + } + break; + } + } + }); + + txtSearch.addChangeListener(new FTextField.ChangeListener() { + @Override + public void textChanged() { + changeTimer.restart(); + } + }); } + + @Override + protected void doWidgetLayout(LayoutHelper helper) { + helper.offset(0, 3); //add padding above text field + helper.fillLine(txtSearch, FTextField.HEIGHT); + } + + @Override + protected void applyChange() { + changeTimer.stop(); //ensure change timer stopped before applying change + super.applyChange(); + } + + private Timer changeTimer = new Timer(200, new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + applyChange(); + } + }); } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ToggleButtonsFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ToggleButtonsFilter.java index 4b0ada69152..b420736b49c 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ToggleButtonsFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ToggleButtonsFilter.java @@ -1,15 +1,18 @@ package forge.gui.toolbox.itemmanager.filters; -import java.awt.Dimension; +import java.awt.Graphics; import java.util.ArrayList; +import javax.swing.Icon; import javax.swing.JPanel; import forge.Command; import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FSkin; +import forge.gui.toolbox.FSkin.SkinFont; import forge.gui.toolbox.FSkin.SkinImage; +import forge.gui.toolbox.LayoutHelper; import forge.gui.toolbox.itemmanager.ItemManager; -import forge.gui.toolbox.itemmanager.SItemManagerUtil.StatTypes; import forge.item.InventoryItem; /** @@ -18,50 +21,80 @@ import forge.item.InventoryItem; */ @SuppressWarnings("serial") public abstract class ToggleButtonsFilter extends ItemFilter { - private static final Dimension BUTTON_SIZE = new Dimension(60, 24); - + protected boolean lockFiltering; private final ArrayList buttons = new ArrayList(); protected ToggleButtonsFilter(ItemManager itemManager0) { super(itemManager0); } - protected void addToggleButton(JPanel panel, StatTypes s) { - addToggleButton(panel, s.toLabelString(), s.img); - } - - protected void addToggleButton(JPanel panel, String filterName, SkinImage icon) { + protected FLabel addToggleButton(JPanel widget, String filterName, SkinImage icon) { final FLabel button = new FLabel.Builder() .icon(icon).iconScaleAuto(false) .fontSize(11) .tooltip(filterName + " (click to toggle the filter, right-click to show only " + filterName.toLowerCase() + ")") .hoverable().selectable(true).selected(true) .build(); - - button.setPreferredSize(BUTTON_SIZE); - button.setMinimumSize(BUTTON_SIZE); - + button.setCommand(new Command() { @Override public void run() { + if (lockFiltering) { return; } applyChange(); } }); - //hook so right-clicking a button toggles itself on and toggles off all other buttons - button.setRightClickCommand(new Command() { - @Override - public void run() { - for(FLabel btn : buttons) { - btn.setSelected(false); - } - button.setSelected(true); - applyChange(); - } - }); - this.buttons.add(button); - panel.add(button); + widget.add(button); + return button; + } + + @Override + protected void doWidgetLayout(LayoutHelper helper) { + int availableWidth = helper.getParentWidth() - (buttons.size() - 1) * 2; //account for gaps + int buttonWidth = availableWidth / buttons.size(); + Graphics g = buttons.get(0).getGraphics(); + if (buttonWidth <= 0 || g == null) { + return; + } + + int maxTextWidth = buttonWidth - 8; //account for padding + + for (FLabel btn : buttons) { + if (!btn.getText().isEmpty()) { + int max = maxTextWidth; + Icon icon = btn.getIcon(); + if (icon != null) { + max -= icon.getIconWidth() + 4; + } + for (int fs = 11; fs > 5; fs--) { + SkinFont skinFont = FSkin.getFont(fs); + if (skinFont.measureTextWidth(g, btn.getText()) <= max) { + FSkin.get(btn).setFont(skinFont); + break; + } + } + helper.include(btn, buttonWidth, 25); + helper.offset(-1, 0); //keep buttons tighter together + } + } + } + + @Override + public final boolean isEmpty() { + for (FLabel button : buttons) { //consider filter empty if any button isn't selected + if (!button.getSelected()) { + return false; + } + } + return true; + } + + @Override + public void reset() { + for (FLabel button : buttons) { + button.setSelected(true); + } } /** diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ValueRangeFilter.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ValueRangeFilter.java index 12e3e90e64a..07b23b9fbf9 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ValueRangeFilter.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/filters/ValueRangeFilter.java @@ -1,18 +1,127 @@ package forge.gui.toolbox.itemmanager.filters; +import java.awt.Component; +import javax.swing.JPanel; +import javax.swing.JSpinner; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.google.common.base.Predicate; + +import forge.card.CardRules; +import forge.card.CardRulesPredicates; +import forge.gui.toolbox.FLabel; +import forge.gui.toolbox.FSpinner; +import forge.gui.toolbox.FTextField; +import forge.gui.toolbox.LayoutHelper; import forge.gui.toolbox.itemmanager.ItemManager; +import forge.gui.toolbox.itemmanager.SFilterUtil; import forge.item.InventoryItem; +import forge.util.ComparableOp; /** * TODO: Write javadoc for this type. * */ public abstract class ValueRangeFilter extends ItemFilter { + private FLabel label; + private FSpinner lowerBound, upperBound; protected ValueRangeFilter(ItemManager itemManager0) { super(itemManager0); } - + + protected abstract String getCaption(); + + protected int minValue() { + return 0; + } + + protected int maxValue() { + return 20; + } + + @Override + public final boolean isEmpty() { + return lowerBound.getValue().equals(minValue()) && upperBound.getValue().equals(maxValue()); + } + + @Override + public void reset() { + lowerBound.setValue(minValue()); + upperBound.setValue(maxValue()); + } + + @Override + public Component getMainComponent() { + return ((JSpinner.DefaultEditor)lowerBound.getEditor()).getTextField(); + } + + @Override + protected final void buildWidget(JPanel widget) { + lowerBound = addSpinner(widget, true); + + String text = " <= " + this.getCaption() + " <= "; + label = new FLabel.Builder().text(text).fontSize(12).build(); + widget.add(label); + + upperBound = addSpinner(widget, false); + + lowerBound.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent arg0) { + if (Integer.parseInt(upperBound.getValue().toString()) < + Integer.parseInt(lowerBound.getValue().toString())) + { + upperBound.setValue(lowerBound.getValue()); + } + applyChange(); + } + }); + + upperBound.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent arg0) { + if (Integer.parseInt(lowerBound.getValue().toString()) > + Integer.parseInt(upperBound.getValue().toString())) + { + lowerBound.setValue(upperBound.getValue()); + } + applyChange(); + } + }); + } + + @Override + protected void doWidgetLayout(LayoutHelper helper) { + helper.include(lowerBound, 45, FTextField.HEIGHT); + helper.include(label, 125, 26); + helper.include(upperBound, 45, FTextField.HEIGHT); + } + + private FSpinner addSpinner(JPanel widget, boolean lowerBound) { + FSpinner spinner = new FSpinner.Builder() + .minValue(this.minValue()) + .maxValue(this.maxValue()) + .initialValue(lowerBound ? this.minValue() : this.maxValue()) + .build(); + spinner.setFocusable(false); //only the spinner text field should be focusable, not the up/down widget + widget.add(spinner); + return spinner; + } + + protected Predicate getCardRulesFieldPredicate(CardRulesPredicates.LeafNumber.CardField field) { + int lowerValue = Integer.parseInt(lowerBound.getValue().toString()); + int upperValue = Integer.parseInt(upperBound.getValue().toString()); + boolean hasMin = lowerValue != minValue(); + boolean hasMax = upperValue != maxValue(); + + Predicate pLower = hasMin ? new CardRulesPredicates.LeafNumber(field, ComparableOp.GT_OR_EQUAL, lowerValue) : null; + Predicate pUpper = hasMax ? new CardRulesPredicates.LeafNumber(field, ComparableOp.LT_OR_EQUAL, upperValue) : null; + + return SFilterUtil.optimizedAnd(pLower, pUpper); + } + /** * Merge the given filter with this filter if possible * @param filter diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/table/ItemTable.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/table/ItemTable.java index c8538ac07c8..5412252cab1 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/table/ItemTable.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/table/ItemTable.java @@ -33,8 +33,6 @@ import java.util.List; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.JViewport; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellRenderer; @@ -43,7 +41,6 @@ import javax.swing.table.TableColumn; import forge.gui.toolbox.FSkin; import forge.gui.toolbox.itemmanager.ItemManager; import forge.gui.toolbox.itemmanager.ItemManagerModel; -import forge.gui.toolbox.itemmanager.SItemManagerUtil; import forge.item.InventoryItem; @@ -62,7 +59,7 @@ public final class ItemTable extends JTable { public ItemManager getItemManager() { return this.itemManager; } - + public ItemTableModel getTableModel() { return this.tableModel; } @@ -88,7 +85,7 @@ public final class ItemTable extends JTable { skin.setSelectionBackground(FSkin.getColor(FSkin.Colors.CLR_INACTIVE)); } } - + @Override public void focusGained(FocusEvent e) { skin.setSelectionBackground(FSkin.getColor(FSkin.Colors.CLR_ACTIVE)); @@ -98,24 +95,17 @@ public final class ItemTable extends JTable { } } }); - + skin.setFont(FSkin.getFont(12)); setBorder(null); getTableHeader().setBorder(null); setRowHeight(18); setWantElasticColumns(false); - + // prevent tables from intercepting tab focus traversals setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null); setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null); } - - private final TableModelListener tableModelListener = new TableModelListener() { - @Override - public void tableChanged(final TableModelEvent ev) { - SItemManagerUtil.setStats(ItemTable.this.itemManager); - } - }; /** * Applies a EditorTableModel and a model listener to this instance's JTable. @@ -124,7 +114,7 @@ public final class ItemTable extends JTable { */ public void setup(final List> cols) { final DefaultTableColumnModel colmodel = new DefaultTableColumnModel(); - + //ensure columns ordered properly Collections.sort(cols, new Comparator>() { @Override @@ -146,16 +136,12 @@ public final class ItemTable extends JTable { this.tableModel.refreshSort(); getTableHeader().setBackground(new Color(200, 200, 200)); - - // Update stats each time table changes - this.tableModel.removeTableModelListener(tableModelListener); //ensure listener not added multiple times - this.tableModel.addTableModelListener(tableModelListener); } - + private String _getCellTooltip(TableCellRenderer renderer, int row, int col, Object val) { Component cell = renderer.getTableCellRendererComponent( this, val, false, false, row, col); - + // if we're conditionally showing the tooltip, check to see // if we shouldn't show it if (!(cell instanceof AlwaysShowToolTip)) @@ -185,7 +171,7 @@ public final class ItemTable extends JTable { // otherwise, show the full text in the tooltip return String.valueOf(val); } - + // column headers @Override protected JTableHeader createDefaultTableHeader() { @@ -198,36 +184,36 @@ public final class ItemTable extends JTable { if (null == headerRenderer) { headerRenderer = getDefaultRenderer(); } - + return _getCellTooltip( headerRenderer, -1, col, tableColumn.getHeaderValue()); } }; } - + // cell data @Override public String getToolTipText(MouseEvent e) { Point p = e.getPoint(); int row = rowAtPoint(p); int col = columnAtPoint(p); - + if (col >= getColumnCount() || row >= getRowCount()) { return null; } - + Object val = getValueAt(row, col); if (null == val) { return null; } - + return _getCellTooltip(getCellRenderer(row, col), row, col, val); } - + private int lastTooltipRow = -1; private int lastTooltipCol = -1; private Point lastTooltipPt; - + @Override public Point getToolTipLocation(MouseEvent e) { Point p = e.getPoint(); @@ -265,19 +251,19 @@ public final class ItemTable extends JTable { if (0 > rowLastSelected) { return; } - + // 3 cases: 0 items left, select the same row, select prev row int numRows = getRowCount(); if (numRows == 0) { return; } - + int newRow = rowLastSelected; if (numRows <= newRow) { // move selection away from the last, already missing, option newRow = numRows - 1; } - + selectAndScrollTo(newRow); } @@ -291,7 +277,7 @@ public final class ItemTable extends JTable { final int iRow = getSelectedRow(); return iRow >= 0 ? this.tableModel.rowToItem(iRow).getKey() : null; } - + /** * * getSelectedItems. @@ -322,7 +308,7 @@ public final class ItemTable extends JTable { public void setWantElasticColumns(boolean value) { setAutoResizeMode(value ? JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS : JTable.AUTO_RESIZE_OFF); } - + public void selectAndScrollTo(int rowIdx) { if (!(getParent() instanceof JViewport)) { return; @@ -342,7 +328,7 @@ public final class ItemTable extends JTable { // target is above is, move to position 3 rows above target targetRect.setLocation(targetRect.x, targetRect.y - (targetRect.height * 3)); } - + scrollRectToVisible(targetRect); setRowSelectionInterval(rowIdx, rowIdx); } diff --git a/forge-gui/src/main/java/forge/gui/workshop/CWorkshopUI.java b/forge-gui/src/main/java/forge/gui/workshop/CWorkshopUI.java index 25d1feab009..f4664b1f93c 100644 --- a/forge-gui/src/main/java/forge/gui/workshop/CWorkshopUI.java +++ b/forge-gui/src/main/java/forge/gui/workshop/CWorkshopUI.java @@ -29,7 +29,6 @@ import forge.gui.toolbox.itemmanager.CardManager; import forge.gui.toolbox.itemmanager.SItemManagerIO; import forge.gui.toolbox.itemmanager.SItemManagerIO.EditorPreference; import forge.gui.toolbox.itemmanager.table.ItemTable; -import forge.gui.workshop.controllers.CWorkshopCatalog; import forge.gui.workshop.menus.CWorkshopUIMenus; import forge.gui.workshop.views.VWorkshopCatalog; import forge.item.PaperCard; @@ -78,7 +77,6 @@ public enum CWorkshopUI implements ICDoc, IMenuProvider { boolean wantUnique = SItemManagerIO.getPref(EditorPreference.display_unique_only); cardTable.setWantElasticColumns(wantElastic); cardManager.setWantUnique(wantUnique); - CWorkshopCatalog.SINGLETON_INSTANCE.applyCurrentFilter(); } /* (non-Javadoc) diff --git a/forge-gui/src/main/java/forge/gui/workshop/controllers/CWorkshopCatalog.java b/forge-gui/src/main/java/forge/gui/workshop/controllers/CWorkshopCatalog.java index dbd263c8850..496f627bb82 100644 --- a/forge-gui/src/main/java/forge/gui/workshop/controllers/CWorkshopCatalog.java +++ b/forge-gui/src/main/java/forge/gui/workshop/controllers/CWorkshopCatalog.java @@ -1,54 +1,13 @@ package forge.gui.workshop.controllers; -import java.awt.Toolkit; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JSpinner; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import org.apache.commons.lang3.tuple.Pair; - -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; - import forge.Command; -import forge.Singletons; -import forge.card.CardEdition; -import forge.game.GameFormat; -import forge.gui.GuiUtils; import forge.gui.workshop.views.VWorkshopCatalog; -import forge.gui.deckeditor.views.VCardCatalog.RangeTypes; import forge.gui.framework.ICDoc; -import forge.gui.home.quest.DialogChooseSets; -import forge.gui.toolbox.FLabel; -import forge.gui.toolbox.FSpinner; -import forge.gui.toolbox.itemmanager.SFilterUtil; -import forge.gui.toolbox.itemmanager.SItemManagerUtil; -import forge.gui.toolbox.itemmanager.SItemManagerUtil.StatTypes; import forge.gui.toolbox.itemmanager.table.SColumnUtil; import forge.gui.toolbox.itemmanager.table.TableColumnInfo; import forge.gui.toolbox.itemmanager.table.SColumnUtil.ColumnName; import forge.item.InventoryItem; -import forge.item.PaperCard; -import forge.item.ItemPredicate; -import forge.quest.QuestWorld; -import forge.quest.data.GameFormatQuest; /** * Controls the "card catalog" panel in the workshop UI. @@ -60,13 +19,6 @@ public enum CWorkshopCatalog implements ICDoc { /** */ SINGLETON_INSTANCE; - private final Set> activePredicates = new HashSet>(); - private final Set activeFormats = new HashSet(); - private final Set activeWorlds = new HashSet(); - private final Set activeRanges = EnumSet.noneOf(RangeTypes.class); - - private boolean disableFiltering = false; - private CWorkshopCatalog() { } @@ -84,279 +36,7 @@ public enum CWorkshopCatalog implements ICDoc { * @see forge.gui.framework.ICDoc#initialize() */ @Override - @SuppressWarnings("serial") - public void initialize() { - final Command updateFilterCommand = new Command() { - @Override - public void run() { - if (!disableFiltering) { - applyCurrentFilter(); - } - } - }; - - for (Map.Entry entry : VWorkshopCatalog.SINGLETON_INSTANCE.getStatLabels().entrySet()) { - final FLabel statLabel = entry.getValue(); - statLabel.setCommand(updateFilterCommand); - - //hook so right-clicking a filter in a group toggles itself off and toggles on all other filters in group - final SItemManagerUtil.StatTypes st = entry.getKey(); - final int group = st.group; - if (group > 0) { - statLabel.setRightClickCommand(new Command() { - @SuppressWarnings("incomplete-switch") - @Override - public void run() { - if (!disableFiltering) { - disableFiltering = true; - - boolean foundSelected = false; - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - if (s.group == group && s != st) { - FLabel lbl = VWorkshopCatalog.SINGLETON_INSTANCE.getCardManager().getStatLabel(s); - if (s == StatTypes.MULTICOLOR) { - switch (st) { - case WHITE: - case BLUE: - case BLACK: - case RED: - case GREEN: - //ensure multicolor filter selected after right-clicking a color filter - if (!lbl.getSelected()) { - lbl.setSelected(true); - } - continue; - } - } - if (lbl.getSelected()) { - foundSelected = true; - lbl.setSelected(false); - } - } - } - if (!statLabel.getSelected()) { - statLabel.setSelected(true); - } - else if (!foundSelected) { - //if statLabel only label in group selected, re-select all other labels in group - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - if (s.group == group && s != st) { - FLabel lbl = VWorkshopCatalog.SINGLETON_INSTANCE.getCardManager().getStatLabel(s); - if (!lbl.getSelected()) { - lbl.setSelected(true); - } - } - } - } - - disableFiltering = false; - applyCurrentFilter(); - } - } - }); - } - } - - VWorkshopCatalog.SINGLETON_INSTANCE.getStatLabels().get(SItemManagerUtil.StatTypes.TOTAL).setCommand(new Command() { - private boolean lastToggle = true; - - @Override - public void run() { - disableFiltering = true; - lastToggle = !lastToggle; - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - if (SItemManagerUtil.StatTypes.TOTAL != s) { - VWorkshopCatalog.SINGLETON_INSTANCE.getCardManager().getStatLabel(s).setSelected(lastToggle); - } - } - disableFiltering = false; - applyCurrentFilter(); - } - }); - - // assemble add restriction menu - final Command addRestrictionCommand = new Command() { - @Override - public void run() { - JPopupMenu popup = new JPopupMenu("RestrictionPopupMenu"); - GuiUtils.addMenuItem(popup, "Current text search", - KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), - new Runnable() { - @Override - public void run() { - addRestriction(buildSearchRestriction(), null, null); - } - }, canSearch()); - JMenu fmt = new JMenu("Format"); - for (final GameFormat f : Singletons.getModel().getFormats()) { - GuiUtils.addMenuItem(fmt, f.getName(), null, new Runnable() { - @Override - public void run() { - addRestriction(buildFormatRestriction(f.toString(), f, true), activeFormats, f); - } - }, !isActive(activeFormats, f)); - } - popup.add(fmt); - GuiUtils.addMenuItem(popup, "Sets...", null, new Runnable() { - @Override - public void run() { - final DialogChooseSets dialog = new DialogChooseSets(null, null, true); - dialog.setOkCallback(new Runnable() { - @Override - public void run() { - List setCodes = dialog.getSelectedSets(); - - if (setCodes.isEmpty()) { - return; - } - - StringBuilder label = new StringBuilder("Sets:"); - boolean truncated = false; - for (String code : setCodes) - { - // don't let the full label get too long - if (32 > label.length()) { - label.append(" ").append(code).append(";"); - } else { - truncated = true; - break; - } - } - - // chop off last semicolons - label.delete(label.length() - 1, label.length()); - - if (truncated) { - label.append("..."); - } - - addRestriction(buildSetRestriction(label.toString(), setCodes, dialog.getWantReprints()), null, null); - } - }); - } - }); - JMenu range = new JMenu("Value range"); - for (final RangeTypes t : RangeTypes.values()) { - GuiUtils.addMenuItem(range, t.toLabelString() + " restriction", null, new Runnable() { - @Override - public void run() { - addRestriction(buildRangeRestriction(t), activeRanges, t); - } - }, !isActive(activeRanges, t)); - } - popup.add(range); - JMenu world = new JMenu("Quest world"); - for (final QuestWorld w : Singletons.getModel().getWorlds()) { - GameFormatQuest format = w.getFormat(); - if (null == format) { - // assumes that no world other than the main world will have a null format - format = Singletons.getModel().getQuest().getMainFormat(); - } - final GameFormatQuest f = format; - GuiUtils.addMenuItem(world, w.getName(), null, new Runnable() { - @Override - public void run() { - addRestriction(buildFormatRestriction(w.getName(), f, true), activeWorlds, w); - } - }, !isActive(activeWorlds, w) && null != f); - } - popup.add(world); - popup.show(VWorkshopCatalog.SINGLETON_INSTANCE.getBtnAddRestriction(), 0, - VWorkshopCatalog.SINGLETON_INSTANCE.getBtnAddRestriction().getHeight()); - } - }; - FLabel btnAddRestriction = VWorkshopCatalog.SINGLETON_INSTANCE.getBtnAddRestriction(); - btnAddRestriction.setCommand(addRestrictionCommand); - btnAddRestriction.setRightClickCommand(addRestrictionCommand); //show menu on right-click too - - VWorkshopCatalog.SINGLETON_INSTANCE.getCbSearchMode().addItemListener(new ItemListener() { - @Override - public void itemStateChanged(ItemEvent arg0) { - applyCurrentFilter(); - } - }); - - Runnable addSearchRestriction = new Runnable() { - @Override - public void run() { - if (canSearch()) { - addRestriction(buildSearchRestriction(), null, null); - } - } - }; - - // add search restriction on ctrl-enter from either the textbox or combobox - VWorkshopCatalog.SINGLETON_INSTANCE.getCbSearchMode().addKeyListener(new _OnCtrlEnter(addSearchRestriction)); - VWorkshopCatalog.SINGLETON_INSTANCE.getTxfSearch().addKeyListener(new _OnCtrlEnter(addSearchRestriction) { - private boolean keypressPending; - @Override - public void keyReleased(KeyEvent e) { - if (KeyEvent.VK_ENTER == e.getKeyCode() && 0 == e.getModifiers()) { - // set focus to table when a plain enter is typed into the text filter box - VWorkshopCatalog.SINGLETON_INSTANCE.getCardManager().getTable().requestFocusInWindow(); - } else if (keypressPending) { - // do this in keyReleased instead of keyTyped since the textbox text isn't updated until the key is released - // but depend on keypressPending since otherwise we pick up hotkeys and other unwanted stuff - applyCurrentFilter(); - } - } - - @Override - public void keyPressed(KeyEvent e) { - super.keyPressed(e); - keypressPending = KeyEvent.VK_ENTER != e.getKeyCode(); - } - }); - - VWorkshopCatalog.SINGLETON_INSTANCE.getLblName().setCommand(updateFilterCommand); - VWorkshopCatalog.SINGLETON_INSTANCE.getLblType().setCommand(updateFilterCommand); - VWorkshopCatalog.SINGLETON_INSTANCE.getLblText().setCommand(updateFilterCommand); - - // ensure mins can's exceed maxes and maxes can't fall below mins - for (Pair sPair : VWorkshopCatalog.SINGLETON_INSTANCE.getSpinners().values()) { - final FSpinner min = sPair.getLeft(); - final FSpinner max = sPair.getRight(); - - min.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent arg0) { - if (Integer.parseInt(max.getValue().toString()) < - Integer.parseInt(min.getValue().toString())) - { - max.setValue(min.getValue()); - } - applyCurrentFilter(); - } - }); - - max.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent arg0) { - if (Integer.parseInt(min.getValue().toString()) > - Integer.parseInt(max.getValue().toString())) - { - min.setValue(max.getValue()); - } - applyCurrentFilter(); - } - }); - } - } - - private class _OnCtrlEnter extends KeyAdapter { - private final Runnable action; - _OnCtrlEnter(Runnable action) { - this.action = action; - } - - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == 10) { - if (e.isControlDown() || e.isMetaDown()) { - action.run(); - } - } - } + public void initialize() { } /* (non-Javadoc) @@ -369,202 +49,4 @@ public enum CWorkshopCatalog implements ICDoc { VWorkshopCatalog.SINGLETON_INSTANCE.getCardManager().getTable().setup(lstCatalogCols); //TODO: Restore previously selected card } - - public void applyCurrentFilter() { - // The main trick here is to apply a CardPrinted predicate - // to the table. CardRules will lead to difficulties. - - List> cardPredicates = new ArrayList>(); - cardPredicates.add(Predicates.instanceOf(PaperCard.class)); - cardPredicates.add(SFilterUtil.buildColorAndTypeFilter(VWorkshopCatalog.SINGLETON_INSTANCE.getStatLabels())); - cardPredicates.addAll(activePredicates); - - // apply current values in the range filters - for (RangeTypes t : RangeTypes.values()) { - if (activeRanges.contains(t)) { - cardPredicates.add(SFilterUtil.buildIntervalFilter(VWorkshopCatalog.SINGLETON_INSTANCE.getSpinners(), t)); - } - } - - // get the current contents of the search box - cardPredicates.add(SFilterUtil.buildTextFilter( - VWorkshopCatalog.SINGLETON_INSTANCE.getTxfSearch().getText(), - 0 != VWorkshopCatalog.SINGLETON_INSTANCE.getCbSearchMode().getSelectedIndex(), - VWorkshopCatalog.SINGLETON_INSTANCE.getLblName().getSelected(), - VWorkshopCatalog.SINGLETON_INSTANCE.getLblType().getSelected(), - VWorkshopCatalog.SINGLETON_INSTANCE.getLblText().getSelected())); - - Predicate cardFilter = Predicates.and(cardPredicates); - - // show packs and decks in the card shop according to the toggle setting - // this is special-cased apart from the buildColorAndTypeFilter() above - if (VWorkshopCatalog.SINGLETON_INSTANCE.getCardManager().getStatLabel(StatTypes.PACK).getSelected()) { - List> itemPredicates = new ArrayList>(); - itemPredicates.add(cardFilter); - itemPredicates.add(ItemPredicate.Presets.IS_PACK); - itemPredicates.add(ItemPredicate.Presets.IS_DECK); - cardFilter = Predicates.or(itemPredicates); - } - - // Apply to table - VWorkshopCatalog.SINGLETON_INSTANCE.getCardManager().setFilterPredicate(cardFilter); - } - - private boolean canSearch() { - return !VWorkshopCatalog.SINGLETON_INSTANCE.getTxfSearch().getText().isEmpty() && - (VWorkshopCatalog.SINGLETON_INSTANCE.getLblName().getSelected() || - VWorkshopCatalog.SINGLETON_INSTANCE.getLblType().getSelected() || - VWorkshopCatalog.SINGLETON_INSTANCE.getLblText().getSelected()); - } - - private boolean isActive(Set activeSet, T key) { - return activeSet.contains(key); - } - - @SuppressWarnings("serial") - private void addRestriction(Pair> restriction, final Set activeSet, final T key) { - final Predicate predicate = restriction.getRight(); - - if (null != predicate && activePredicates.contains(predicate)) { - return; - } - - VWorkshopCatalog.SINGLETON_INSTANCE.addRestrictionWidget(restriction.getLeft(), new Command() { - @Override - public void run() { - if (null != key) { - activeSet.remove(key); - } - if (null != predicate) { - activePredicates.remove(predicate); - } - applyCurrentFilter(); - } - }); - - if (null != key) { - activeSet.add(key); - } - if (null != predicate) { - activePredicates.add(predicate); - } - - applyCurrentFilter(); - } - - private Pair> buildRangeRestriction(RangeTypes t) { - final Pair s = VWorkshopCatalog.SINGLETON_INSTANCE.getSpinners().get(t); - s.getLeft().setValue(0); - s.getRight().setValue(10); - - // set focus to lower bound widget - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - ((JSpinner.DefaultEditor)s.getLeft().getEditor()).getTextField().requestFocusInWindow(); - } - }); - - return Pair.of(VWorkshopCatalog.SINGLETON_INSTANCE.buildRangeRestrictionWidget(t), null); - } - - private String buildSearchRestrictionText(String text, boolean isInverse, boolean wantName, boolean wantType, boolean wantText) { - StringBuilder sb = new StringBuilder(); - sb.append(isInverse ? "Without" : "Contains"); - sb.append(": '").append(text).append("' in:"); - if (wantName) { sb.append(" name,"); } - if (wantType) { sb.append(" type,"); } - if (wantText) { sb.append(" text,"); } - sb.delete(sb.length() - 1, sb.length()); // chop off last comma - - return sb.toString(); - } - - private Pair> buildSearchRestriction() { - boolean isInverse = - VWorkshopCatalog.SEARCH_MODE_INVERSE_INDEX == VWorkshopCatalog.SINGLETON_INSTANCE.getCbSearchMode().getSelectedIndex(); - String text = VWorkshopCatalog.SINGLETON_INSTANCE.getTxfSearch().getText(); - boolean wantName = VWorkshopCatalog.SINGLETON_INSTANCE.getLblName().getSelected(); - boolean wantType = VWorkshopCatalog.SINGLETON_INSTANCE.getLblType().getSelected(); - boolean wantText = VWorkshopCatalog.SINGLETON_INSTANCE.getLblText().getSelected(); - - String shortText = buildSearchRestrictionText(text, isInverse, wantName, wantType, wantText); - String fullText = null; - if (25 < text.length()) { - fullText = shortText; - shortText = buildSearchRestrictionText(text.substring(0, 22) + "...", - isInverse, wantName, wantType, wantText); - } - - VWorkshopCatalog.SINGLETON_INSTANCE.getTxfSearch().setText(""); - - return Pair.of( - VWorkshopCatalog.SINGLETON_INSTANCE.buildPlainRestrictionWidget(shortText, fullText), - SFilterUtil.buildTextFilter(text, isInverse, wantName, wantType, wantText)); - } - - private Pair> buildFormatRestriction(String displayName, GameFormat format, boolean allowReprints) { - CardEdition.Collection editions = Singletons.getMagicDb().getEditions(); - StringBuilder tooltip = new StringBuilder("Sets:"); - - int lastLen = 0; - int lineLen = 0; - - // use HTML tooltips so we can insert line breaks - List sets = format.getAllowedSetCodes(); - if (null == sets || sets.isEmpty()) { - tooltip.append(" All"); - } else { - for (String code : sets) { - // don't let a single line get too long - if (50 < lineLen) { - tooltip.append("
"); - lastLen += lineLen; - lineLen = 0; - } - - CardEdition edition = editions.get(code); - tooltip.append(" ").append(edition.getName()).append(" (").append(code).append("),"); - lineLen = tooltip.length() - lastLen; - } - - // chop off last comma - tooltip.delete(tooltip.length() - 1, tooltip.length()); - - if (allowReprints) { - tooltip.append("

Allowing identical cards from other sets"); - } - } - - List bannedCards = format.getBannedCardNames(); - if (null != bannedCards && !bannedCards.isEmpty()) { - tooltip.append("

Banned:"); - lastLen += lineLen; - lineLen = 0; - - for (String cardName : bannedCards) { - // don't let a single line get too long - if (50 < lineLen) { - tooltip.append("
"); - lastLen += lineLen; - lineLen = 0; - } - - tooltip.append(" ").append(cardName).append(";"); - lineLen = tooltip.length() - lastLen; - } - - // chop off last semicolon - tooltip.delete(tooltip.length() - 1, tooltip.length()); - } - tooltip.append(""); - - return Pair.of( - VWorkshopCatalog.SINGLETON_INSTANCE.buildPlainRestrictionWidget(displayName, tooltip.toString()), - allowReprints ? format.getFilterRules() : format.getFilterPrinted()); - } - - private Pair> buildSetRestriction(String displayName, List setCodes, boolean allowReprints) { - return buildFormatRestriction(displayName, new GameFormat(null, setCodes, null), allowReprints); - } } diff --git a/forge-gui/src/main/java/forge/gui/workshop/views/VWorkshopCatalog.java b/forge-gui/src/main/java/forge/gui/workshop/views/VWorkshopCatalog.java index 18a3287fd31..04c031d1cad 100644 --- a/forge-gui/src/main/java/forge/gui/workshop/views/VWorkshopCatalog.java +++ b/forge-gui/src/main/java/forge/gui/workshop/views/VWorkshopCatalog.java @@ -1,42 +1,22 @@ package forge.gui.workshop.views; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.util.HashMap; -import java.util.Map; - -import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.JTextField; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang3.tuple.Pair; - import com.google.common.collect.Iterables; -import forge.Command; import forge.Singletons; -import forge.gui.WrapLayout; -import forge.gui.deckeditor.views.VCardCatalog.RangeTypes; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; import forge.gui.framework.IVDoc; import forge.gui.match.controllers.CDetail; import forge.gui.match.controllers.CPicture; -import forge.gui.toolbox.FComboBoxWrapper; -import forge.gui.toolbox.FLabel; -import forge.gui.toolbox.FSkin; -import forge.gui.toolbox.FSpinner; -import forge.gui.toolbox.FTextField; import forge.gui.toolbox.itemmanager.CardManager; import forge.gui.toolbox.itemmanager.ItemManagerContainer; -import forge.gui.toolbox.itemmanager.SItemManagerUtil; import forge.gui.workshop.controllers.CCardScript; import forge.gui.workshop.controllers.CWorkshopCatalog; import forge.item.PaperCard; @@ -57,76 +37,13 @@ public enum VWorkshopCatalog implements IVDoc { // Fields used with interface IVDoc private DragCell parentCell; private final DragTab tab = new DragTab("Card Catalog"); - - // Total and color count labels/filter toggles - private final Dimension labelSize = new Dimension(60, 24); - private final JPanel pnlStats = new JPanel(new WrapLayout(FlowLayout.LEFT)); - private final Map statLabels = - new HashMap(); - - // restriction button and search widgets - private final JPanel pnlSearch = new JPanel(new MigLayout("insets 0, gap 5px, center")); - private final FLabel btnAddRestriction = new FLabel.ButtonBuilder() - .text("Add filter") - .tooltip("Click to add custom filters to the card list") - .reactOnMouseDown().build(); - private final FComboBoxWrapper cbSearchMode = new FComboBoxWrapper(); - private final JTextField txfSearch = new FTextField.Builder().ghostText("Search").build(); - private final FLabel lblName = new FLabel.Builder().text("Name").hoverable().selectable().selected().build(); - private final FLabel lblType = new FLabel.Builder().text("Type").hoverable().selectable().selected().build(); - private final FLabel lblText = new FLabel.Builder().text("Text").hoverable().selectable().selected().build(); - private final JPanel pnlRestrictions = new JPanel(new WrapLayout(FlowLayout.LEFT, 10, 5)); - private final ItemManagerContainer cardManagerContainer = new ItemManagerContainer(); private final CardManager cardManager; - private final Map> spinners = new HashMap>(); - //========== Constructor /** */ private VWorkshopCatalog() { - pnlStats.setOpaque(false); - - for (SItemManagerUtil.StatTypes s : SItemManagerUtil.StatTypes.values()) { - FLabel label = buildToggleLabel(s, SItemManagerUtil.StatTypes.TOTAL != s); - statLabels.put(s, label); - JComponent component = label; - if (SItemManagerUtil.StatTypes.TOTAL == s) { - label.setToolTipText("Total cards (click to toggle all filters)"); - } else if (SItemManagerUtil.StatTypes.PACK == s) { - // wrap in a constant-size panel so we can change its visibility without affecting layout - component = new JPanel(new MigLayout("insets 0, gap 0")); - component.setPreferredSize(labelSize); - component.setMinimumSize(labelSize); - component.setOpaque(false); - label.setVisible(false); - component.add(label); - } - pnlStats.add(component); - } - - pnlSearch.setOpaque(false); - pnlSearch.add(btnAddRestriction, "center, w pref+8, h pref+8"); - pnlSearch.add(txfSearch, "pushx, growx"); - cbSearchMode.addItem("in"); - cbSearchMode.addItem("not in"); - cbSearchMode.addTo(pnlSearch, "center"); - pnlSearch.add(lblName, "w pref+8, h pref+8"); - pnlSearch.add(lblType, "w pref+8, h pref+8"); - pnlSearch.add(lblText, "w pref+8, h pref+8"); - - pnlRestrictions.setOpaque(false); - - // fill spinner map - for (RangeTypes t : RangeTypes.values()) { - FSpinner lowerBound = new FSpinner.Builder().maxValue(10).build(); - FSpinner upperBound = new FSpinner.Builder().maxValue(10).build(); - _setupSpinner(lowerBound); - _setupSpinner(upperBound); - spinners.put(t, Pair.of(lowerBound, upperBound)); - } - - this.cardManager = new CardManager(this.statLabels, true); + this.cardManager = new CardManager(true); Iterable allCards = Iterables.concat(Singletons.getMagicDb().getCommonCards(), Singletons.getMagicDb().getVariantCards()); this.cardManager.setPool(ItemPool.createFrom(allCards, PaperCard.class), true); this.cardManagerContainer.setItemManager(this.cardManager); @@ -142,10 +59,6 @@ public enum VWorkshopCatalog implements IVDoc { }); } - private void _setupSpinner (JSpinner spinner) { - spinner.setFocusable(false); // only the spinner text field should be focusable, not the up/down widget - } - //========== Overridden from IVDoc @Override @@ -176,98 +89,11 @@ public enum VWorkshopCatalog implements IVDoc { @Override public void populate() { JPanel parentBody = parentCell.getBody(); - parentBody.setLayout(new MigLayout("insets 0, gap 0, wrap, hidemode 3")); - parentBody.add(pnlStats, "w 100:520:520, center"); - parentBody.add(pnlSearch, "w 96%, gap 1% 1%"); - parentBody.add(pnlRestrictions, "w 96%, gapleft 1%, gapright push"); - parentBody.add(cardManagerContainer, "w 98%!, h 100% - 35, gap 1% 0 0 1%"); + parentBody.setLayout(new MigLayout("insets 5, gap 0, wrap, hidemode 3")); + parentBody.add(cardManagerContainer, "push, grow"); } - //========== Accessor/mutator methods - public FLabel getLblName() { return lblName; } - public FLabel getLblType() { return lblType; } - public FLabel getLblText() { return lblText; } - - public FLabel getBtnAddRestriction() { return btnAddRestriction; } - public FComboBoxWrapper getCbSearchMode() { return cbSearchMode; } - public JTextField getTxfSearch() { return txfSearch; } - public CardManager getCardManager() { return cardManager; } - public Map getStatLabels() { - return statLabels; - } - public Map> getSpinners() { - return spinners; - } - - //========== Other methods - private FLabel buildToggleLabel(SItemManagerUtil.StatTypes s, boolean selectable) { - String tooltip; - if (selectable) { //construct tooltip for selectable toggle labels, indicating click and right-click behavior - String labelString = s.toLabelString(); - tooltip = labelString + " (click to toggle the filter, right-click to show only " + labelString.toLowerCase() + ")"; - } - else { tooltip = ""; } - - FLabel label = new FLabel.Builder() - .icon(s.img).iconScaleAuto(false) - .fontSize(11) - .tooltip(tooltip) - .hoverable().selectable(selectable).selected(selectable) - .build(); - - label.setPreferredSize(labelSize); - label.setMinimumSize(labelSize); - - return label; - } - - @SuppressWarnings("serial") - public void addRestrictionWidget(JComponent component, final Command onRemove) { - final JPanel pnl = new JPanel(new MigLayout("insets 2, gap 2, h 30!")); - - pnl.setOpaque(false); - FSkin.get(pnl).setMatteBorder(1, 2, 1, 2, FSkin.getColor(FSkin.Colors.CLR_TEXT)); - - pnl.add(component, "h 30!, center"); - pnl.add(new FLabel.Builder().text("X").fontSize(10).hoverable(true) - .tooltip("Remove filter").cmdClick(new Command() { - @Override - public void run() { - pnlRestrictions.remove(pnl); - refreshRestrictionWidgets(); - onRemove.run(); - } - }).build(), "top"); - - pnlRestrictions.add(pnl, "h 30!"); - refreshRestrictionWidgets(); - } - - public void refreshRestrictionWidgets() { - Container parent = pnlRestrictions.getParent(); - pnlRestrictions.validate(); - parent.validate(); - parent.repaint(); - } - - public JPanel buildRangeRestrictionWidget(RangeTypes t) { - JPanel pnl = new JPanel(new MigLayout("insets 0, gap 2")); - pnl.setOpaque(false); - - Pair s = spinners.get(t); - pnl.add(s.getLeft(), "w 45!, h 26!, center"); - pnl.add(new FLabel.Builder().text("<=").fontSize(11).build(), "h 26!, center"); - pnl.add(new FLabel.Builder().text(t.toLabelString()).fontSize(11).build(), "h 26!, center"); - pnl.add(new FLabel.Builder().text("<=").fontSize(11).build(), "h 26!, center"); - pnl.add(s.getRight(), "w 45!, h 26!, center"); - - return pnl; - } - - public FLabel buildPlainRestrictionWidget(String label, String tooltip) { - return new FLabel.Builder().text(label).tooltip(tooltip).fontSize(11).build(); - } }