From 689ef0cf8a9968abf6721ea87ad5b315b513f378 Mon Sep 17 00:00:00 2001 From: drdev Date: Mon, 23 Dec 2013 03:03:33 +0000 Subject: [PATCH] Make selection after adding/removing cards from deck behave as expected and improve performance of adding multiple cards at once Support Ctrl+F in Current Deck pane Prevent losing multi-selection when using Left/Right arrow keys to switch focus between Catalog and Deck --- forge-gui/CHANGES.txt | 2 + .../forge/gui/deckeditor/CDeckEditorUI.java | 162 +++++++++--------- .../deckeditor/controllers/ACEditorBase.java | 53 +++++- .../controllers/CEditorCommander.java | 50 +++--- .../controllers/CEditorConstructed.java | 60 +++---- .../controllers/CEditorDraftingProcess.java | 24 ++- .../controllers/CEditorLimited.java | 30 ++-- .../deckeditor/controllers/CEditorQuest.java | 37 ++-- .../controllers/CEditorQuestCardShop.java | 142 ++++++++------- .../controllers/CEditorVariant.java | 26 ++- .../gui/toolbox/itemmanager/ItemManager.java | 134 +++++++++++++-- .../itemmanager/views/ItemListView.java | 87 ++++------ .../toolbox/itemmanager/views/ItemView.java | 83 ++++++++- 13 files changed, 550 insertions(+), 340 deletions(-) diff --git a/forge-gui/CHANGES.txt b/forge-gui/CHANGES.txt index 78d9470ed8a..5be13d31d59 100644 --- a/forge-gui/CHANGES.txt +++ b/forge-gui/CHANGES.txt @@ -19,6 +19,8 @@ The Total stat label has been removed in favor of showing a caption and (# SHOWN Checkboxes are now available for each filter type, allowing that filter to be disabled and re-enabled without losing the configuration of that filter (such as chosen sets) Adding a filter for formats, sets, and quest worlds now merges into existing filters of that type if possible to apply OR logic, rather than both appearing as separate filters with AND logic applied, likely resulting in no results Pressing Ctrl+Enter to add a filter for the current search now adds another editable search bar rather than just a label. +Cards added to deck are now selected, even if multiple are added at once. The performance of adding and removing multiple cards at once has also been improved. +When some but not all copies of a selected card are removed from the deck, that card now remains selected in the case of multiple cards being selected. - Constructed mode - 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 46276441e8a..de98cc49146 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/CDeckEditorUI.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/CDeckEditorUI.java @@ -30,6 +30,7 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.HashMap; import java.util.List; +import java.util.Map.Entry; import javax.swing.JMenu; import javax.swing.JPopupMenu; @@ -45,8 +46,6 @@ import javax.swing.event.ListSelectionListener; import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3.StringUtils; -import com.google.common.primitives.Ints; - import forge.Command; import forge.Singletons; import forge.deck.DeckBase; @@ -70,6 +69,7 @@ import forge.gui.toolbox.itemmanager.SItemManagerIO; import forge.gui.toolbox.itemmanager.SItemManagerIO.EditorPreference; import forge.gui.toolbox.itemmanager.views.ItemListView; import forge.item.InventoryItem; +import forge.util.ItemPool; /** * Constructs instance of deck editor UI controller, used as a single point of @@ -131,75 +131,76 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { setCurrentEditorController(childController0); } } - - private interface _MoveAction { - void move(InventoryItem item, int qty); - } @SuppressWarnings("unchecked") - public void incrementDeckQuantity(InventoryItem item, int delta) { + public void incrementDeckQuantity(T item, int delta) { if (item == null || delta == 0) { return; } if (delta > 0) { //add items - int qty = Math.min(delta, ((ItemManager)childController.getCatalogManager()).getItemCount(item)); + int qty = Math.min(delta, ((ItemManager)childController.getCatalogManager()).getItemCount(item)); if (qty == 0) { return; } - childController.addCard(item, false, qty); + ((ACEditorBase)childController).addItem(item, qty, false); } else { //remove items - int qty = Math.min(-delta, ((ItemManager)childController.getDeckManager()).getItemCount(item)); + int qty = Math.min(-delta, ((ItemManager)childController.getDeckManager()).getItemCount(item)); if (qty == 0) { return; } - childController.removeCard(item, false, qty); + ((ACEditorBase)childController).removeItem(item, qty, false); } CStatistics.SINGLETON_INSTANCE.update(); CProbabilities.SINGLETON_INSTANCE.update(); } - private void moveSelectedCards(ItemManager itemManager, _MoveAction moveAction, int maxQty) { - List items = itemManager.getSelectedItems(); - if (items.isEmpty()) { - return; - } - - for (InventoryItem item : items) { - int toMove = Math.min(maxQty, itemManager.getItemCount(item)); - moveAction.move(item, toMove); + private interface _MoveAction { + public void move(Iterable> items); + } + + private void moveSelectedItems(ItemManager itemManager, _MoveAction moveAction, int maxQty) { + if (maxQty == 0) { return; } + + ItemPool items = new ItemPool(itemManager.getGenericType()); + for (T item : itemManager.getSelectedItems()) { + int qty = Math.min(maxQty, itemManager.getItemCount(item)); + if (qty > 0) { + items.add(item, qty); + } } + if (items.isEmpty()) { return; } + + moveAction.move(items); CStatistics.SINGLETON_INSTANCE.update(); CProbabilities.SINGLETON_INSTANCE.update(); } @SuppressWarnings("unchecked") public void addSelectedCards(final boolean toAlternate, int number) { - moveSelectedCards((ItemManager)childController.getCatalogManager(), - new _MoveAction() { + moveSelectedItems(childController.getCatalogManager(), new _MoveAction() { @Override - public void move(InventoryItem item, int qty) { - childController.addCard(item, toAlternate, qty); + public void move(Iterable> items) { + ((ACEditorBase)childController).addItems(items, toAlternate); } }, number); } @SuppressWarnings("unchecked") public void removeSelectedCards(final boolean toAlternate, int number) { - moveSelectedCards((ItemManager)childController.getDeckManager(), - new _MoveAction() { + moveSelectedItems(childController.getDeckManager(), new _MoveAction() { @Override - public void move(InventoryItem item, int qty) { - childController.removeCard(item, toAlternate, qty); + public void move(Iterable> items) { + ((ACEditorBase)childController).removeItems(items, toAlternate); } }, number); } @SuppressWarnings("unchecked") public void removeAllCards(final boolean toAlternate) { - ItemManager v = (ItemManager)childController.getDeckManager(); + ItemManager v = childController.getDeckManager(); v.getTable().selectAll(); - moveSelectedCards(v, new _MoveAction() { + moveSelectedItems(v, new _MoveAction() { @Override - public void move(InventoryItem item, int qty) { - childController.removeCard(item, toAlternate, qty); + public void move(Iterable> items) { + ((ACEditorBase)childController).removeItems(items, toAlternate); } }, Integer.MAX_VALUE); } @@ -210,32 +211,33 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { } private class _ContextMenuBuilder implements ACEditorBase.ContextMenuBuilder { - private final MouseEvent _e; - private final ItemListView _nextTable; - private final _MoveCard _onMove; - private final int _numSelected; - private final JPopupMenu _menu = new JPopupMenu("TableContextMenu"); - private boolean _showTextFilterItem = false; + private final MouseEvent _e; + private final ItemManager _itemManager; + private final ItemManager _nextItemManager; + private final _MoveCard _onMove; + private final JPopupMenu _menu = new JPopupMenu("ItemViewContextMenu"); - public _ContextMenuBuilder(MouseEvent e, ItemListView table, ItemListView nextTable, _MoveCard onMove) { + public _ContextMenuBuilder(MouseEvent e, ItemManager itemManager, ItemManager nextItemManager, _MoveCard onMove) { _e = e; - _nextTable = nextTable; + _itemManager = itemManager; + _nextItemManager = nextItemManager; _onMove = onMove; - - // ensure the table has focus - if (!table.hasFocus()) { - table.focus(); + + //ensure the item manager has focus + itemManager.focus(); + + //if item under the cursor is not selected, select it + int index = itemManager.getTable().getIndexAtPoint(e.getPoint()); + boolean needSelection = true; + for (Integer selectedIndex : itemManager.getSelectedIndices()) { + if (selectedIndex == index) { + needSelection = false; + break; + } } - - // if item under the cursor is not selected, select it - int index = table.getIndexAtPoint(e.getPoint()); - int[] selectedIndices = table.getSelectedIndices(); - if (!Ints.contains(selectedIndices, index)) { - table.setSelectedIndex(index); + if (needSelection) { + itemManager.setSelectedIndex(index); } - - // record selection count - _numSelected = selectedIndices.length; } private void show() { @@ -243,31 +245,29 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { GuiUtils.addMenuItem(_menu, "Jump to previous table", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), new Runnable() { - @Override public void run() { _nextTable.focus(); } + @Override public void run() { _nextItemManager.focus(); } }); GuiUtils.addMenuItem(_menu, "Jump to next table", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), new Runnable() { - @Override public void run() { _nextTable.focus(); } + @Override public void run() { _nextItemManager.focus(); } + }); + GuiUtils.addMenuItem(_menu, "Jump to text filter", + KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), + new Runnable() { + @Override public void run() { + _itemManager.focusSearch(); + } }); - - if (_showTextFilterItem) { - GuiUtils.addMenuItem(_menu, "Jump to text filter", - KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), - new Runnable() { - @Override public void run() { - VCardCatalog.SINGLETON_INSTANCE.getItemManager().focusSearch(); - } - }); - } _menu.show(_e.getComponent(), _e.getX(), _e.getY()); } private String _doNoun(String nounSingular, String nounPlural) { - if (1 == _numSelected) { + int numSelected = _itemManager.getSelectionCount(); + if (1 == numSelected) { return nounSingular; } - return String.format("%d %s", _numSelected, nounPlural); + return String.format("%d %s", numSelected, nounPlural); } private String _doDest(String destination) { @@ -314,11 +314,6 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { @Override public void run() { _onMove.moveCard(true, 4); } }); } - - @Override - public void addTextFilterItem() { - _showTextFilterItem = true; - } } /** @@ -343,12 +338,15 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { public void keyPressed(KeyEvent e) { if (!isFindingAsYouType && KeyEvent.VK_SPACE == e.getKeyCode()) { addSelectedCards(e.isControlDown() || e.isMetaDown(), e.isShiftDown() ? 4: 1); - } else if (KeyEvent.VK_LEFT == e.getKeyCode() || KeyEvent.VK_RIGHT == e.getKeyCode()) { + } + else if (KeyEvent.VK_LEFT == e.getKeyCode() || KeyEvent.VK_RIGHT == e.getKeyCode()) { deckTable.focus(); - } else if (KeyEvent.VK_F == e.getKeyCode()) { + e.consume(); //prevent losing selection + } + 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.getItemManager().focusSearch(); + catView.focusSearch(); } } } @@ -359,8 +357,16 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { public void keyPressed(KeyEvent e) { if (!isFindingAsYouType && KeyEvent.VK_SPACE == e.getKeyCode()) { removeSelectedCards(e.isControlDown() || e.isMetaDown(), e.isShiftDown() ? 4: 1); - } else if (KeyEvent.VK_LEFT == e.getKeyCode() || KeyEvent.VK_RIGHT == e.getKeyCode()) { + } + else if (KeyEvent.VK_LEFT == e.getKeyCode() || KeyEvent.VK_RIGHT == e.getKeyCode()) { catTable.focus(); + e.consume(); //prevent losing selection + } + else if (KeyEvent.VK_F == e.getKeyCode()) { + // let ctrl/cmd-F set focus to the text filter box + if (e.isControlDown() || e.isMetaDown()) { + deckView.focusSearch(); + } } } }); @@ -387,7 +393,7 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { @Override public void onRightClick(MouseEvent e) { - _ContextMenuBuilder cmb = new _ContextMenuBuilder(e, catTable, deckTable, onAdd); + _ContextMenuBuilder cmb = new _ContextMenuBuilder(e, catView, deckView, onAdd); childController.buildAddContextMenu(cmb); cmb.show(); } @@ -402,7 +408,7 @@ public enum CDeckEditorUI implements ICDoc, IMenuProvider { @Override public void onRightClick(MouseEvent e) { - _ContextMenuBuilder cmb = new _ContextMenuBuilder(e, deckTable, catTable, onRemove); + _ContextMenuBuilder cmb = new _ContextMenuBuilder(e, deckView, catView, onRemove); childController.buildRemoveContextMenu(cmb); cmb.show(); } 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 9837d75543c..0807f5ee48f 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 @@ -17,6 +17,8 @@ */ package forge.gui.deckeditor.controllers; +import java.util.Map.Entry; + import javax.swing.SwingUtilities; import forge.Command; @@ -31,6 +33,7 @@ import forge.gui.toolbox.FLabel; import forge.gui.toolbox.FSkin; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.InventoryItem; +import forge.util.ItemPool; import forge.view.FView; /** @@ -60,7 +63,6 @@ public abstract class ACEditorBase createPoolForItem(final TItem item, final int qty) { + if (item == null || qty <= 0) { return null; } + + ItemPool pool = new ItemPool((Class)item.getClass()); + pool.add(item, qty); + return pool; + } + + public final void addItems(Iterable> items, boolean toAlternate) { + if (items == null || !items.iterator().hasNext()) { return; } //do nothing if no items + onAddItems(items, toAlternate); + } + + public final void removeItems(Iterable> items, boolean toAlternate) { + if (items == null || !items.iterator().hasNext()) { return; } //do nothing if no items + onRemoveItems(items, toAlternate); + } + /** - * Operation to add one of selected card to current deck. + * Operation to add selected items to current deck. */ - public abstract void addCard(InventoryItem item, boolean toAlternate, int qty); + protected abstract void onAddItems(Iterable> items, boolean toAlternate); /** - * Operation to remove one of selected card from current deck. + * Operation to remove selected item from current deck. */ - public abstract void removeCard(InventoryItem item, boolean toAlternate, int qty); + protected abstract void onRemoveItems(Iterable> items, boolean toAlternate); public abstract void buildAddContextMenu(ContextMenuBuilder cmb); public abstract void buildRemoveContextMenu(ContextMenuBuilder cmb); 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 83e28ed6fb0..a5b4a4e19fe 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 @@ -20,7 +20,7 @@ package forge.gui.deckeditor.controllers; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; +import java.util.Map.Entry; import com.google.common.base.Predicates; import com.google.common.base.Supplier; @@ -101,51 +101,53 @@ public final class CEditorCommander extends ACEditorBase { //=========== Overridden from ACEditorBase /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#addCard() + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() */ @Override - public void addCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || toAlternate) { - return; - } + protected void onAddItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } + List limitExceptions = Arrays.asList(new String[]{"Relentless Rats", "Shadowborn Apostle"}); - if((controller.getModel().getMain().contains((PaperCard)item) - || controller.getModel().getOrCreate(DeckSection.Sideboard).contains((PaperCard)item) - || controller.getModel().getOrCreate(DeckSection.Commander).contains((PaperCard)item)) - && !(((PaperCard)item).getRules().getType().isBasic() || limitExceptions.contains(item.getName()))) { - return; + List> itemList = new ArrayList>(); + + for (Entry item : items) { + PaperCard card = item.getKey(); + if ((controller.getModel().getMain().contains(card) + || controller.getModel().getOrCreate(DeckSection.Sideboard).contains(card) + || controller.getModel().getOrCreate(DeckSection.Commander).contains(card)) + && !(card.getRules().getType().isBasic() || limitExceptions.contains(card.getName()))) { + continue; + } + itemList.add(item); } + if (itemList.isEmpty()) { return; } + if (sectionMode == DeckSection.Commander) { - for(Map.Entry cp : getDeckManager().getPool()) { - getDeckManager().removeItem(cp.getKey(), cp.getValue()); - } + this.getDeckManager().removeItems(getDeckManager().getPool()); } - final PaperCard card = (PaperCard) item; - this.getDeckManager().addItem(card, qty); + this.getDeckManager().addItems(itemList); + this.getCatalogManager().selectItemEntrys(itemList); //just select all removed cards in Catalog this.controller.notifyModelChanged(); } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#removeCard() + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() */ @Override - public void removeCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || toAlternate) { - return; - } + protected void onRemoveItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } - final PaperCard card = (PaperCard) item; - this.getDeckManager().removeItem(card, qty); + this.getDeckManager().removeItems(items); + this.getCatalogManager().selectItemEntrys(items); //just select all removed cards in Catalog this.controller.notifyModelChanged(); } @Override public void buildAddContextMenu(ContextMenuBuilder cmb) { cmb.addMoveItems("Move", "card", "cards", "to deck"); - cmb.addTextFilterItem(); } @Override 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 d3108d9b224..cdd0bca708f 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 @@ -19,7 +19,7 @@ package forge.gui.deckeditor.controllers; import java.util.ArrayList; import java.util.List; -import java.util.Map; +import java.util.Map.Entry; import com.google.common.base.Predicates; import com.google.common.base.Supplier; @@ -104,54 +104,55 @@ public final class CEditorConstructed extends ACEditorBase { //=========== Overridden from ACEditorBase /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#addCard() + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() */ @Override - public void addCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard)) { - return; - } - + protected void onAddItems(Iterable> items, boolean toAlternate) { if (sectionMode == DeckSection.Avatar) { - for(Map.Entry cp : getDeckManager().getPool()) { - getDeckManager().removeItem(cp.getKey(), cp.getValue()); - } + getDeckManager().removeItems(getDeckManager().getPool()); } - final PaperCard card = (PaperCard) item; if (toAlternate) { if (sectionMode != DeckSection.Sideboard) { - controller.getModel().getOrCreate(DeckSection.Sideboard).add(card, qty); + controller.getModel().getOrCreate(DeckSection.Sideboard).addAll(items); } - } else { - getDeckManager().addItem(card, qty); } - // if not in sideboard mode, "remove" 0 cards in order to re-show the selected card - this.getCatalogManager().removeItem(card, sectionMode == DeckSection.Sideboard ? qty : 0); - + else { + getDeckManager().addItems(items); + } + if (sectionMode == DeckSection.Sideboard) { + this.getCatalogManager().removeItems(items); + } + else { //if not in sideboard mode, just select all added cards in Catalog + List cards = new ArrayList(); + for (Entry itemEntry : items) { + cards.add(itemEntry.getKey()); + } + this.getCatalogManager().setSelectedItems(cards); + } this.controller.notifyModelChanged(); } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#removeCard() + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() */ @Override - public void removeCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard)) { - return; - } - - final PaperCard card = (PaperCard) item; + protected void onRemoveItems(Iterable> items, boolean toAlternate) { if (toAlternate) { if (sectionMode != DeckSection.Sideboard) { - controller.getModel().getOrCreate(DeckSection.Sideboard).add(card, qty); - } else { + controller.getModel().getOrCreate(DeckSection.Sideboard).addAll(items); + } + else { // "added" to library, but library will be recalculated when it is shown again } - } else if (sectionMode == DeckSection.Sideboard) { - this.getCatalogManager().addItem(card, qty); } - this.getDeckManager().removeItem(card, qty); + else if (sectionMode == DeckSection.Sideboard) { + this.getCatalogManager().addItems(items); + } + else { //if not in sideboard mode, just select all removed cards in Catalog + this.getCatalogManager().selectItemEntrys(items); + } + this.getDeckManager().removeItems(items); this.controller.notifyModelChanged(); } @@ -159,7 +160,6 @@ public final class CEditorConstructed extends ACEditorBase { public void buildAddContextMenu(ContextMenuBuilder cmb) { cmb.addMoveItems(sectionMode == DeckSection.Sideboard ? "Move" : "Add", "card", "cards", sectionMode == DeckSection.Sideboard ? "to sideboard" : "to deck"); cmb.addMoveAlternateItems(sectionMode == DeckSection.Sideboard ? "Remove" : "Add", "card", "cards", sectionMode == DeckSection.Sideboard ? "from deck" : "to sideboard"); - cmb.addTextFilterItem(); } @Override 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 b5bb6fae31f..be799bedafc 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 @@ -17,6 +17,8 @@ */ package forge.gui.deckeditor.controllers; +import java.util.Map.Entry; + import javax.swing.JOptionPane; import forge.Singletons; @@ -37,7 +39,6 @@ import forge.gui.home.sanctioned.CSubmenuDraft; import forge.gui.toolbox.itemmanager.CardManager; import forge.gui.toolbox.itemmanager.views.SColumnUtil; import forge.item.PaperCard; -import forge.item.InventoryItem; import forge.limited.BoosterDraft; import forge.limited.IBoosterDraft; import forge.util.ItemPoolView; @@ -86,17 +87,14 @@ public class CEditorDraftingProcess extends ACEditorBase { } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#addCard() + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() */ @Override - public void addCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || toAlternate) { - return; - } - - final PaperCard card = (PaperCard) item; + protected void onAddItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } // can only draft one at a time, regardless of the requested quantity + PaperCard card = items.iterator().next().getKey(); this.getDeckManager().addItem(card, 1); // get next booster pack @@ -104,23 +102,23 @@ public class CEditorDraftingProcess extends ACEditorBase { if (this.boosterDraft.hasNextChoice()) { this.showChoices(this.boosterDraft.nextChoice()); - } else { + } + else { this.boosterDraft.finishedDrafting(); this.saveDraft(); } } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#removeCard() + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() */ @Override - public void removeCard(InventoryItem item, boolean toAlternate, int qty) { + protected void onRemoveItems(Iterable> items, boolean toAlternate) { } @Override public void buildAddContextMenu(ContextMenuBuilder cmb) { cmb.addMoveItems("Draft", "card", "cards", null); - cmb.addTextFilterItem(); } @Override @@ -141,7 +139,7 @@ public class CEditorDraftingProcess extends ACEditorBase { VCardCatalog.SINGLETON_INSTANCE.getLblTitle().setText("Select a card from pack number " + (((BoosterDraft) boosterDraft).getCurrentBoosterIndex() + 1) + "."); this.getCatalogManager().setPool(list); - this.getCatalogManager().getTable().fixSelection(0); + this.getCatalogManager().getTable().setSelectedIndex(0); } // showChoices() /** 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 47328b758e5..70709b14ee9 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 @@ -17,6 +17,8 @@ */ package forge.gui.deckeditor.controllers; +import java.util.Map.Entry; + import com.google.common.base.Supplier; import forge.deck.Deck; @@ -35,7 +37,6 @@ import forge.gui.toolbox.itemmanager.CardManager; import forge.gui.toolbox.itemmanager.SItemManagerUtil; import forge.gui.toolbox.itemmanager.views.SColumnUtil; import forge.item.PaperCard; -import forge.item.InventoryItem; import forge.util.storage.IStorage; /** @@ -91,41 +92,34 @@ public final class CEditorLimited extends ACEditorBase { //========== Overridden from ACEditorBase /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#addCard() + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() */ @Override - public void addCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || toAlternate) { - return; - } + protected void onAddItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } // update view - final PaperCard card = (PaperCard) item; - this.getDeckManager().addItem(card, qty); - this.getCatalogManager().removeItem(card, qty); + this.getDeckManager().addItems(items); + this.getCatalogManager().removeItems(items); this.getDeckController().notifyModelChanged(); } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#removeCard() + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() */ @Override - public void removeCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || toAlternate) { - return; - } + protected void onRemoveItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } // update view - final PaperCard card = (PaperCard) item; - this.getCatalogManager().addItem(card, qty); - this.getDeckManager().removeItem(card, qty); + this.getCatalogManager().addItems(items); + this.getDeckManager().removeItems(items); this.getDeckController().notifyModelChanged(); } @Override public void buildAddContextMenu(ContextMenuBuilder cmb) { cmb.addMoveItems("Move", "card", "cards", "to deck"); - cmb.addTextFilterItem(); } @Override 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 0e463366d20..16d83ec45c4 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 @@ -143,46 +143,38 @@ public final class CEditorQuest extends ACEditorBase { //=========== Overridden from ACEditorBase /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#addCard() + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() */ @Override - public void addCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard)) { - return; - } - - final PaperCard card = (PaperCard) item; + protected void onAddItems(Iterable> items, boolean toAlternate) { if (toAlternate) { // if we're in sideboard mode, the library will get adjusted properly when we call resetTables() if (!sideboardMode) { - controller.getModel().getOrCreate(DeckSection.Sideboard).add(card, qty); + controller.getModel().getOrCreate(DeckSection.Sideboard).addAll(items); } - } else { - getDeckManager().addItem(card, qty); } - this.getCatalogManager().removeItem(card, qty); + else { + getDeckManager().addItems(items); + } + this.getCatalogManager().removeItems(items); this.controller.notifyModelChanged(); } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#removeCard() + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() */ @Override - public void removeCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard)) { - return; - } - - final PaperCard card = (PaperCard) item; + protected void onRemoveItems(Iterable> items, boolean toAlternate) { if (toAlternate) { // if we're in sideboard mode, the library will get adjusted properly when we call resetTables() if (!sideboardMode) { - controller.getModel().getOrCreate(DeckSection.Sideboard).add(card, qty); + controller.getModel().getOrCreate(DeckSection.Sideboard).addAll(items); } - } else { - this.getCatalogManager().addItem(card, qty); } - this.getDeckManager().removeItem(card, qty); + else { + this.getCatalogManager().addItems(items); + } + this.getDeckManager().removeItems(items); this.controller.notifyModelChanged(); } @@ -190,7 +182,6 @@ public final class CEditorQuest extends ACEditorBase { public void buildAddContextMenu(ContextMenuBuilder cmb) { cmb.addMoveItems(sideboardMode ? "Move" : "Add", "card", "cards", sideboardMode ? "to sideboard" : "to deck"); cmb.addMoveAlternateItems(sideboardMode ? "Remove" : "Add", "card", "cards", sideboardMode ? "from deck" : "to sideboard"); - cmb.addTextFilterItem(); } @Override 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 b2ded9b80be..4f7564323e0 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 @@ -19,6 +19,7 @@ package forge.gui.deckeditor.controllers; import java.text.DecimalFormat; import java.text.NumberFormat; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -289,83 +290,103 @@ public final class CEditorQuestCardShop extends ACEditorBase> items, boolean toAlternate) { // disallow "buying" cards while showing the full catalog - if (item == null || showingFullCatalog || toAlternate) { + if (showingFullCatalog || toAlternate) { return; } - final int value = this.getCardValue(item); + ItemPool itemsToAdd = new ItemPool(InventoryItem.class); + List> itemsToRemove = new ArrayList>(); - if (value > this.questData.getAssets().getCredits()) { - JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "Not enough credits!"); - return; - } - - if (item instanceof PaperCard) { - final PaperCard card = (PaperCard) item; - this.getDeckManager().addItem(card, qty); - this.questData.getCards().buyCard(card, qty, value); + for (Entry itemEntry : items) { + final InventoryItem item = itemEntry.getKey(); + final int qty = itemEntry.getValue(); + final int value = this.getCardValue(item); - } else if (item instanceof SealedProduct) { - for (int i = 0; qty > i; ++i) { - SealedProduct booster = null; - if (item instanceof BoosterPack) { - booster = (BoosterPack) ((BoosterPack) item).clone(); - } else if (item instanceof TournamentPack) { - booster = (TournamentPack) ((TournamentPack) item).clone(); - } else if (item instanceof FatPack) { - booster = (FatPack) ((FatPack) item).clone(); + if (value > this.questData.getAssets().getCredits()) { + JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), + "Not enough credits to purchase " + (qty == 1 ? "" : qty + " copies of ") + item.getName() + "."); + continue; + } + + if (item instanceof PaperCard) { + this.questData.getCards().buyCard((PaperCard) item, qty, value); + itemsToAdd.add(item, qty); + } + else if (item instanceof SealedProduct) { + for (int i = 0; i < qty; i++) { + SealedProduct booster = null; + if (item instanceof BoosterPack) { + booster = (BoosterPack) ((BoosterPack) item).clone(); + } + else if (item instanceof TournamentPack) { + booster = (TournamentPack) ((TournamentPack) item).clone(); + } + else if (item instanceof FatPack) { + booster = (FatPack) ((FatPack) item).clone(); + } + this.questData.getCards().buyPack(booster, value); + final List newCards = booster.getCards(); + + itemsToAdd.addAllFlat(newCards); + + final CardListViewer c = new CardListViewer(booster.getName(), "You have found the following cards inside:", newCards); + c.show(); + } + } + else if (item instanceof PreconDeck) { + final PreconDeck deck = (PreconDeck) item; + for (int i = 0; i < qty; i++) { + this.questData.getCards().buyPreconDeck(deck, value); + + itemsToAdd.addAll(deck.getDeck().getMain()); } - this.questData.getCards().buyPack(booster, value); - final List newCards = booster.getCards(); - ItemPool newInventory = new ItemPool(InventoryItem.class); - newInventory.addAllFlat(newCards); - getDeckManager().addItems(newInventory); - final CardListViewer c = new CardListViewer(booster.getName(), "You have found the following cards inside:", newCards); - c.show(); + boolean one = (qty == 1); + JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), String.format( + "%s '%s' %s added to your decklist.%n%n%s cards were also added to your pool.", + one ? "Deck" : String.format("%d copies of deck", qty), + deck.getName(), one ? "was" : "were", one ? "Its" : "Their"), + "Thanks for purchasing!", JOptionPane.INFORMATION_MESSAGE); } - } else if (item instanceof PreconDeck) { - final PreconDeck deck = (PreconDeck) item; - this.questData.getCards().buyPreconDeck(deck, value); - final ItemPool newInventory = - ItemPool.createFrom(deck.getDeck().getMain(), InventoryItem.class); - for (int i = 0; qty > i; ++i) { - getDeckManager().addItems(newInventory); + else { + continue; //don't remove item from Catalog if any other type } - boolean one = 1 == qty; - JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), String.format( - "%s '%s' %s added to your decklist.%n%n%s cards were also added to your pool.", - one ? "Deck" : String.format("%d copies of deck", qty), - deck.getName(), one ? "was" : "were", one ? "Its" : "Their"), - "Thanks for purchasing!", JOptionPane.INFORMATION_MESSAGE); - } else return; - this.getCatalogManager().removeItem(item, qty); + itemsToRemove.add(itemEntry); + } + + if (itemsToRemove.isEmpty()) { return; } + + this.getDeckManager().addItems(itemsToAdd); + this.getCatalogManager().removeItems(itemsToRemove); this.creditsLabel.setText("Credits: " + this.questData.getAssets().getCredits()); } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#removeCard() + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() */ @Override - public void removeCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || showingFullCatalog || toAlternate) { - return; + protected void onRemoveItems(Iterable> items, boolean toAlternate) { + if (showingFullCatalog || toAlternate) { return; } + + this.getCatalogManager().addItems(items); + this.getDeckManager().removeItems(items); + + for (Entry itemEntry : items) { + final InventoryItem item = itemEntry.getKey(); + if (item instanceof PaperCard) { + final PaperCard card = (PaperCard) item; + final int qty = itemEntry.getValue(); + final int price = Math.min((int) (this.multiplier * this.getCardValue(card)), this.questData.getCards().getSellPriceLimit()); + this.questData.getCards().sellCard(card, qty, price); + } } - final PaperCard card = (PaperCard) item; - this.getCatalogManager().addItem(card, qty); - this.getDeckManager().removeItem(card, qty); - - final int price = Math.min((int) (this.multiplier * this.getCardValue(card)), this.questData.getCards() - .getSellPriceLimit()); - this.questData.getCards().sellCard(card, qty, price); - this.creditsLabel.setText("Credits: " + this.questData.getAssets().getCredits()); } @@ -374,7 +395,6 @@ public final class CEditorQuestCardShop extends ACEditorBase> cardsToRemove) { + public void removeCards(List> cardsToRemove) { if (showingFullCatalog) { return; } @@ -392,7 +412,7 @@ public final class CEditorQuestCardShop extends ACEditorBase item : cardsToRemove) { + for (Entry item : cardsToRemove) { if (!(item.getKey() instanceof PaperCard)) { continue; } @@ -499,8 +519,8 @@ public final class CEditorQuestCardShop extends ACEditorBase> cardsToRemove = new LinkedList>(); - for (Map.Entry item : getDeckManager().getPool()) { + List> cardsToRemove = new LinkedList>(); + for (Entry item : getDeckManager().getPool()) { PaperCard card = (PaperCard)item.getKey(); int numToKeep = card.getRules().getType().isBasic() ? 50 : 4; if ("Relentless Rats".equals(card.getName())) { diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorVariant.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorVariant.java index 5b161d45c89..ee21a49402b 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorVariant.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CEditorVariant.java @@ -18,6 +18,7 @@ package forge.gui.deckeditor.controllers; import java.util.List; +import java.util.Map.Entry; import com.google.common.base.Predicate; import com.google.common.base.Supplier; @@ -83,37 +84,32 @@ public final class CEditorVariant extends ACEditorBase { //=========== Overridden from ACEditorBase /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#addCard() + * @see forge.gui.deckeditor.ACEditorBase#onAddItems() */ @Override - public void addCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || toAlternate) { - return; - } + protected void onAddItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } - final PaperCard card = (PaperCard) item; - this.getDeckManager().addItem(card, qty); + this.getDeckManager().addItems(items); + this.getCatalogManager().selectItemEntrys(items); //just select all added cards in Catalog this.controller.notifyModelChanged(); } /* (non-Javadoc) - * @see forge.gui.deckeditor.ACEditorBase#removeCard() + * @see forge.gui.deckeditor.ACEditorBase#onRemoveItems() */ @Override - public void removeCard(InventoryItem item, boolean toAlternate, int qty) { - if ((item == null) || !(item instanceof PaperCard) || toAlternate) { - return; - } + protected void onRemoveItems(Iterable> items, boolean toAlternate) { + if (toAlternate) { return; } - final PaperCard card = (PaperCard) item; - this.getDeckManager().removeItem(card, qty); + this.getDeckManager().removeItems(items); + this.getCatalogManager().selectItemEntrys(items); //just select all removed cards in Catalog this.controller.notifyModelChanged(); } @Override public void buildAddContextMenu(ContextMenuBuilder cmb) { cmb.addMoveItems("Move", "card", "cards", "to deck"); - cmb.addTextFilterItem(); } @Override 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 d6ab28c79e8..4d9df3e6123 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 @@ -56,6 +56,7 @@ import forge.gui.toolbox.itemmanager.filters.ItemFilter; import forge.gui.toolbox.itemmanager.views.ItemListView; import forge.gui.toolbox.itemmanager.views.ItemView; import forge.item.InventoryItem; +import forge.item.PaperCard; import forge.util.Aggregates; import forge.util.ItemPool; import forge.util.ItemPoolView; @@ -253,6 +254,16 @@ public abstract class ItemManager extends JPanel { helper.fill(this.viewScroller); } + /** + * + * getGenericType. + * + * @return generic type of items + */ + public Class getGenericType() { + return this.genericType; + } + /** * * getCaption. @@ -344,6 +355,26 @@ public abstract class ItemManager extends JPanel { return this.table; } + /** + * + * getItemCount. + * + * @return int + */ + public int getItemCount() { + return this.table.getCount(); + } + + /** + * + * getSelectionCount. + * + * @return int + */ + public int getSelectionCount() { + return this.table.getSelectionCount(); + } + /** * * getSelectedItem. @@ -358,9 +389,9 @@ public abstract class ItemManager extends JPanel { * * getSelectedItems. * - * @return List + * @return Iterable */ - public List getSelectedItems() { + public Iterable getSelectedItems() { return this.table.getSelectedItems(); } @@ -374,6 +405,30 @@ public abstract class ItemManager extends JPanel { this.table.setSelectedItem(item); } + /** + * + * setSelectedItems. + * + * @param items - Items to select + */ + public void setSelectedItems(Iterable items) { + this.table.setSelectedItems(items); + } + + /** + * + * selectItemEntrys. + * + * @param itemEntrys - Item entrys to select + */ + public void selectItemEntrys(Iterable> itemEntrys) { + List items = new ArrayList(); + for (Entry itemEntry : itemEntrys) { + items.add(itemEntry.getKey()); + } + this.setSelectedItems(items); + } + /** * * getSelectedItem. @@ -386,14 +441,34 @@ public abstract class ItemManager extends JPanel { /** * - * setSelectedItem. + * getSelectedItems. * - * @param item - Item to select + * @return Iterable + */ + public Iterable getSelectedIndices() { + return this.table.getSelectedIndices(); + } + + /** + * + * setSelectedIndex. + * + * @param index - Index to select */ public void setSelectedIndex(int index) { this.table.setSelectedIndex(index); } + /** + * + * setSelectedIndices. + * + * @param indices - Indices to select + */ + public void setSelectedIndices(Iterable indices) { + this.table.setSelectedIndices(indices); + } + /** * * addItem. @@ -402,13 +477,12 @@ public abstract class ItemManager extends JPanel { * @param qty */ public void addItem(final T item, int qty) { - final int n = this.table.getSelectedIndex(); this.pool.add(item, qty); if (this.isUnfiltered()) { this.model.addItem(item, qty); } this.updateView(false); - this.table.fixSelection(n); + this.table.setSelectedItem(item); } /** @@ -417,14 +491,18 @@ public abstract class ItemManager extends JPanel { * * @param itemsToAdd */ - public void addItems(Iterable> itemsToAdd) { - final int n = this.table.getSelectedIndex(); + public void addItems(Iterable> itemsToAdd) { this.pool.addAll(itemsToAdd); if (this.isUnfiltered()) { this.model.addItems(itemsToAdd); } this.updateView(false); - this.table.fixSelection(n); + + List items = new ArrayList(); + for (Map.Entry item : itemsToAdd) { + items.add(item.getKey()); + } + this.table.setSelectedItems(items); } /** @@ -435,13 +513,15 @@ public abstract class ItemManager extends JPanel { * @param qty */ public void removeItem(final T item, int qty) { - final int n = this.table.getSelectedIndex(); + final int selectedIndexBefore = this.getSelectedIndex(); + final Iterable selectedItemsBefore = this.getSelectedItems(); + this.pool.remove(item, qty); if (this.isUnfiltered()) { this.model.removeItem(item, qty); } this.updateView(false); - this.table.fixSelection(n); + this.fixSelection(selectedIndexBefore, selectedItemsBefore); } /** @@ -450,8 +530,10 @@ public abstract class ItemManager extends JPanel { * * @param itemsToRemove */ - public void removeItems(List> itemsToRemove) { - final int n = this.table.getSelectedIndex(); + public void removeItems(Iterable> itemsToRemove) { + final int selectedIndexBefore = this.getSelectedIndex(); + final Iterable selectedItemsBefore = this.getSelectedItems(); + for (Map.Entry item : itemsToRemove) { this.pool.remove(item.getKey(), item.getValue()); if (this.isUnfiltered()) { @@ -459,7 +541,29 @@ public abstract class ItemManager extends JPanel { } } this.updateView(false); - this.table.fixSelection(n); + this.fixSelection(selectedIndexBefore, selectedItemsBefore); + } + + /** + * + * fixSelection. + * + * @param selectedIndexBefore + * @param selectedItemsBefore + */ + private void fixSelection(int selectedIndexBefore, final Iterable selectedItemsBefore) { + if (!this.table.setSelectedItems(selectedItemsBefore)) { + this.table.setSelectedIndex(selectedIndexBefore); //restore selected index if couldn't restore selected items + } + } + + /** + * + * scrollSelectionIntoView. + * + */ + public void scrollSelectionIntoView() { + this.table.scrollSelectionIntoView(); } /** @@ -635,7 +739,7 @@ public abstract class ItemManager extends JPanel { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - if (table.getCount() > 0 && table.getSelectedIndices().length == 0) { + if (table.getCount() > 0 && table.getSelectionCount() == 0) { table.setSelectedIndex(0); } } diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemListView.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemListView.java index bf2d9444c78..b51c6191af4 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemListView.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemListView.java @@ -162,33 +162,6 @@ public final class ItemListView extends ItemView { table.setColumnModel(colModel); } - /** - * - * fixSelection. Call this after deleting an item from table. - * - * @param rowLastSelected - * an int - */ - public void fixSelection(final int rowLastSelected) { - if (0 > rowLastSelected) { - return; - } - - // 3 cases: 0 items left, select the same row, select prev row - int numRows = getCount(); - if (numRows == 0) { - return; - } - - int newRow = rowLastSelected; - if (numRows <= newRow) { - // move selection away from the last, already missing, option - newRow = numRows - 1; - } - - setSelectedIndex(newRow); - } - public JTable getTable() { return this.table; } @@ -214,34 +187,44 @@ public final class ItemListView extends ItemView { } @Override - public T getSelectedItem() { - final int iRow = this.table.getSelectedRow(); - return iRow >= 0 ? this.tableModel.rowToItem(iRow).getKey() : null; - } - - @Override - public int[] getSelectedIndices() { - return this.table.getSelectedRows(); - } - - @Override - public List getSelectedItems() { - List items = new ArrayList(); - for (int row : this.table.getSelectedRows()) { - items.add(tableModel.rowToItem(row).getKey()); + public Iterable getSelectedIndices() { + List indices = new ArrayList(); + int[] selectedRows = this.table.getSelectedRows(); + for (int i = 0; i < selectedRows.length; i++) { + indices.add(selectedRows[i]); } - return items; + return indices; } @Override - public void setSelectedIndex(int index) { - if (!(this.table.getParent() instanceof JViewport)) { - return; - } - JViewport viewport = (JViewport)this.table.getParent(); + protected void onSetSelectedIndex(int index) { + int count = getCount(); + if (count == 0) { return; } + if (index >= count) { + index = count - 1; + } + this.table.setRowSelectionInterval(index, index); + } + + @Override + protected void onSetSelectedIndices(Iterable indices) { + int count = getCount(); + if (count == 0) { return; } + + this.table.clearSelection(); + for (Integer index : indices) { + if (index >= count) { + index = count - 1; + } + this.table.addRowSelectionInterval(index, index); + } + } + + @Override + protected void onScrollSelectionIntoView(JViewport viewport) { // compute where we're going and where we are - Rectangle targetRect = this.table.getCellRect(index, 0, true); + Rectangle targetRect = this.table.getCellRect(this.getSelectedIndex(), 0, true); Rectangle curViewRect = viewport.getViewRect(); // if the target cell is not visible, attempt to jump to a location where it is @@ -256,7 +239,6 @@ public final class ItemListView extends ItemView { } this.table.scrollRectToVisible(targetRect); - this.table.setRowSelectionInterval(index, index); } @Override @@ -279,6 +261,11 @@ public final class ItemListView extends ItemView { return this.table.getRowCount(); } + @Override + public int getSelectionCount() { + return this.table.getSelectedRowCount(); + } + @Override public int getIndexAtPoint(Point p) { return this.table.rowAtPoint(p); diff --git a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemView.java b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemView.java index 04af7dcad6a..84c269ae07c 100644 --- a/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemView.java +++ b/forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemView.java @@ -1,9 +1,12 @@ package forge.gui.toolbox.itemmanager.views; +import java.awt.Container; import java.awt.Point; +import java.util.ArrayList; import java.util.List; import javax.swing.JComponent; +import javax.swing.JViewport; import forge.gui.toolbox.itemmanager.ItemManager; import forge.item.InventoryItem; @@ -19,10 +22,75 @@ public abstract class ItemView { return this.itemManager; } - public void setSelectedItem(T item) { - int index = this.getIndexOfItem(item); + public final T getSelectedItem() { + int index = getSelectedIndex(); + return index >= 0 ? getItemAtIndex(index) : null; + } + + public final Iterable getSelectedItems() { + List items = new ArrayList(); + for (Integer i : getSelectedIndices()) { + items.add(getItemAtIndex(i)); + } + return items; + } + + public final boolean setSelectedItem(T item) { + return setSelectedItem(item, true); + } + public final boolean setSelectedItem(T item, boolean scrollIntoView) { + int index = getIndexOfItem(item); if (index != -1) { - setSelectedIndex(index); + setSelectedIndex(index, scrollIntoView); + return true; + } + return false; + } + + public final boolean setSelectedItems(Iterable items) { + return setSelectedItems(items, true); + } + public final boolean setSelectedItems(Iterable items, boolean scrollIntoView) { + if (getCount() == 0) { return false; } + + List indices = new ArrayList(); + for (T item : items) { + int index = getIndexOfItem(item); + if (index != -1) { + indices.add(index); + } + } + if (indices.size() > 0) { + setSelectedIndices(indices, scrollIntoView); + return true; + } + return false; + } + + public void setSelectedIndex(int index) { + setSelectedIndex(index, true); + } + public void setSelectedIndex(int index, boolean scrollIntoView) { + onSetSelectedIndex(index); + if (scrollIntoView) { + scrollSelectionIntoView(); + } + } + + public void setSelectedIndices(Iterable indices) { + setSelectedIndices(indices, true); + } + public void setSelectedIndices(Iterable indices, boolean scrollIntoView) { + onSetSelectedIndices(indices); + if (scrollIntoView) { + scrollSelectionIntoView(); + } + } + + public void scrollSelectionIntoView() { + Container parent = getComponent().getParent(); + if (parent instanceof JViewport) { + onScrollSelectionIntoView((JViewport)parent); } } @@ -44,12 +112,13 @@ public abstract class ItemView { public abstract T getItemAtIndex(int index); public abstract int getIndexOfItem(T item); public abstract int getSelectedIndex(); - public abstract int[] getSelectedIndices(); - public abstract T getSelectedItem(); - public abstract List getSelectedItems(); - public abstract void setSelectedIndex(int index); + public abstract Iterable getSelectedIndices(); public abstract void selectAll(); public abstract int getCount(); + public abstract int getSelectionCount(); public abstract int getIndexAtPoint(Point p); protected abstract String getCaption(); + protected abstract void onSetSelectedIndex(int index); + protected abstract void onSetSelectedIndices(Iterable indices); + protected abstract void onScrollSelectionIntoView(JViewport viewport); }