mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Add grouping support for Deck editors
This commit is contained in:
@@ -25,6 +25,7 @@ import forge.gui.toolbox.FButton;
|
|||||||
import forge.gui.toolbox.FOptionPane;
|
import forge.gui.toolbox.FOptionPane;
|
||||||
import forge.gui.toolbox.itemmanager.CardManager;
|
import forge.gui.toolbox.itemmanager.CardManager;
|
||||||
import forge.gui.toolbox.itemmanager.ItemManagerContainer;
|
import forge.gui.toolbox.itemmanager.ItemManagerContainer;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
||||||
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
@@ -132,7 +133,7 @@ public class FDeckViewer extends FDialog {
|
|||||||
ItemColumn qtyColumn = new ItemColumn(ColumnDef.QUANTITY);
|
ItemColumn qtyColumn = new ItemColumn(ColumnDef.QUANTITY);
|
||||||
qtyColumn.setIndex(0);
|
qtyColumn.setIndex(0);
|
||||||
columns.put(ColumnDef.QUANTITY, qtyColumn);
|
columns.put(ColumnDef.QUANTITY, qtyColumn);
|
||||||
this.cardManager.setup(columns);
|
this.cardManager.setup(columns, GroupDef.CREATURE_SPELL_LAND, ColumnDef.CMC);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeSection() {
|
private void changeSection() {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import forge.gui.framework.FScreen;
|
|||||||
import forge.gui.toolbox.itemmanager.CardManager;
|
import forge.gui.toolbox.itemmanager.CardManager;
|
||||||
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -164,7 +165,7 @@ public final class CEditorCommander extends ACEditorBase<PaperCard, Deck> {
|
|||||||
lstCatalogCols.remove(ColumnDef.QUANTITY);
|
lstCatalogCols.remove(ColumnDef.QUANTITY);
|
||||||
|
|
||||||
this.getCatalogManager().setup(lstCatalogCols);
|
this.getCatalogManager().setup(lstCatalogCols);
|
||||||
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns());
|
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns(), GroupDef.CREATURE_SPELL_LAND, ColumnDef.CMC);
|
||||||
|
|
||||||
SItemManagerUtil.resetUI(this);
|
SItemManagerUtil.resetUI(this);
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import forge.gui.framework.FScreen;
|
|||||||
import forge.gui.toolbox.itemmanager.CardManager;
|
import forge.gui.toolbox.itemmanager.CardManager;
|
||||||
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -340,7 +341,7 @@ public final class CEditorConstructed extends ACEditorBase<PaperCard, Deck> {
|
|||||||
lstCatalogCols.remove(ColumnDef.QUANTITY);
|
lstCatalogCols.remove(ColumnDef.QUANTITY);
|
||||||
|
|
||||||
this.getCatalogManager().setup(lstCatalogCols);
|
this.getCatalogManager().setup(lstCatalogCols);
|
||||||
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns());
|
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns(), GroupDef.CREATURE_SPELL_LAND, ColumnDef.CMC);
|
||||||
|
|
||||||
SItemManagerUtil.resetUI(this);
|
SItemManagerUtil.resetUI(this);
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import forge.gui.framework.FScreen;
|
|||||||
import forge.gui.home.sanctioned.CSubmenuDraft;
|
import forge.gui.home.sanctioned.CSubmenuDraft;
|
||||||
import forge.gui.toolbox.FOptionPane;
|
import forge.gui.toolbox.FOptionPane;
|
||||||
import forge.gui.toolbox.itemmanager.CardManager;
|
import forge.gui.toolbox.itemmanager.CardManager;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.limited.BoosterDraft;
|
import forge.limited.BoosterDraft;
|
||||||
@@ -261,7 +263,7 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
|
|||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
this.getCatalogManager().setup(SColumnUtil.getCatalogDefaultColumns());
|
this.getCatalogManager().setup(SColumnUtil.getCatalogDefaultColumns());
|
||||||
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns());
|
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns(), GroupDef.CREATURE_SPELL_LAND, ColumnDef.CMC);
|
||||||
|
|
||||||
ccAddLabel = this.getBtnAdd().getText();
|
ccAddLabel = this.getBtnAdd().getText();
|
||||||
this.getBtnAdd().setText("Choose Card");
|
this.getBtnAdd().setText("Choose Card");
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import forge.gui.home.sanctioned.CSubmenuDraft;
|
|||||||
import forge.gui.home.sanctioned.CSubmenuSealed;
|
import forge.gui.home.sanctioned.CSubmenuSealed;
|
||||||
import forge.gui.toolbox.itemmanager.CardManager;
|
import forge.gui.toolbox.itemmanager.CardManager;
|
||||||
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.util.storage.IStorage;
|
import forge.util.storage.IStorage;
|
||||||
@@ -161,7 +163,7 @@ public final class CEditorLimited extends ACEditorBase<PaperCard, DeckGroup> {
|
|||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
this.getCatalogManager().setup(SColumnUtil.getCatalogDefaultColumns());
|
this.getCatalogManager().setup(SColumnUtil.getCatalogDefaultColumns());
|
||||||
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns());
|
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns(), GroupDef.CREATURE_SPELL_LAND, ColumnDef.CMC);
|
||||||
|
|
||||||
SItemManagerUtil.resetUI(this);
|
SItemManagerUtil.resetUI(this);
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import forge.gui.home.quest.CSubmenuQuestDecks;
|
|||||||
import forge.gui.toolbox.itemmanager.CardManager;
|
import forge.gui.toolbox.itemmanager.CardManager;
|
||||||
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -255,7 +256,7 @@ public final class CEditorQuest extends ACEditorBase<PaperCard, Deck> {
|
|||||||
columnsDeck.put(ColumnDef.DECKS, new ItemColumn(ColumnDef.DECKS, this.fnDeckCompare, this.fnDeckGet));
|
columnsDeck.put(ColumnDef.DECKS, new ItemColumn(ColumnDef.DECKS, this.fnDeckCompare, this.fnDeckGet));
|
||||||
|
|
||||||
this.getCatalogManager().setup(columnsCatalog);
|
this.getCatalogManager().setup(columnsCatalog);
|
||||||
this.getDeckManager().setup(columnsDeck);
|
this.getDeckManager().setup(columnsDeck, GroupDef.CREATURE_SPELL_LAND, ColumnDef.CMC);
|
||||||
|
|
||||||
SItemManagerUtil.resetUI(this);
|
SItemManagerUtil.resetUI(this);
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import forge.gui.framework.FScreen;
|
|||||||
import forge.gui.toolbox.itemmanager.CardManager;
|
import forge.gui.toolbox.itemmanager.CardManager;
|
||||||
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
import forge.gui.toolbox.itemmanager.SItemManagerUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
import forge.gui.toolbox.itemmanager.views.SColumnUtil;
|
||||||
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -163,7 +164,7 @@ public final class CEditorVariant extends ACEditorBase<PaperCard, Deck> {
|
|||||||
lstCatalogCols.remove(ColumnDef.QUANTITY);
|
lstCatalogCols.remove(ColumnDef.QUANTITY);
|
||||||
|
|
||||||
this.getCatalogManager().setup(lstCatalogCols);
|
this.getCatalogManager().setup(lstCatalogCols);
|
||||||
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns());
|
this.getDeckManager().setup(SColumnUtil.getDeckDefaultColumns(), GroupDef.CREATURE_SPELL_LAND, ColumnDef.CMC);
|
||||||
|
|
||||||
SItemManagerUtil.resetUI(this);
|
SItemManagerUtil.resetUI(this);
|
||||||
|
|
||||||
|
|||||||
@@ -1240,6 +1240,10 @@ public enum FSkin {
|
|||||||
return SkinFont.get(Font.ITALIC, size);
|
return SkinFont.get(Font.ITALIC, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setGraphicsFont(Graphics g, SkinFont skinFont) {
|
||||||
|
g.setFont(skinFont.font);
|
||||||
|
}
|
||||||
|
|
||||||
public static class SkinFont {
|
public static class SkinFont {
|
||||||
private static Font baseFont;
|
private static Font baseFont;
|
||||||
private static Map<String, SkinFont> fonts = new HashMap<String, SkinFont>();
|
private static Map<String, SkinFont> fonts = new HashMap<String, SkinFont>();
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import forge.gui.toolbox.LayoutHelper;
|
|||||||
import forge.gui.toolbox.FSkin.Colors;
|
import forge.gui.toolbox.FSkin.Colors;
|
||||||
import forge.gui.toolbox.itemmanager.filters.ItemFilter;
|
import forge.gui.toolbox.itemmanager.filters.ItemFilter;
|
||||||
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
import forge.gui.toolbox.itemmanager.views.ColumnDef;
|
||||||
|
import forge.gui.toolbox.itemmanager.views.GroupDef;
|
||||||
import forge.gui.toolbox.itemmanager.views.ImageView;
|
import forge.gui.toolbox.itemmanager.views.ImageView;
|
||||||
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
import forge.gui.toolbox.itemmanager.views.ItemColumn;
|
||||||
import forge.gui.toolbox.itemmanager.views.ItemListView;
|
import forge.gui.toolbox.itemmanager.views.ItemListView;
|
||||||
@@ -120,6 +121,7 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
|
|||||||
|
|
||||||
private final List<ItemView<T>> views = new ArrayList<ItemView<T>>();
|
private final List<ItemView<T>> views = new ArrayList<ItemView<T>>();
|
||||||
private final ItemListView<T> listView;
|
private final ItemListView<T> listView;
|
||||||
|
private final ImageView<T> imageView;
|
||||||
private ItemView<T> currentView;
|
private ItemView<T> currentView;
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
protected boolean lockFiltering;
|
protected boolean lockFiltering;
|
||||||
@@ -135,12 +137,13 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
|
|||||||
this.genericType = genericType0;
|
this.genericType = genericType0;
|
||||||
this.wantUnique = wantUnique0;
|
this.wantUnique = wantUnique0;
|
||||||
this.model = new ItemManagerModel<T>(genericType0);
|
this.model = new ItemManagerModel<T>(genericType0);
|
||||||
|
|
||||||
this.listView = new ItemListView<T>(this, this.model);
|
this.listView = new ItemListView<T>(this, this.model);
|
||||||
this.listView.setAllowMultipleSelections(false);
|
this.imageView = new ImageView<T>(this, this.model);
|
||||||
this.currentView = this.listView;
|
|
||||||
|
|
||||||
this.views.add(this.listView);
|
this.views.add(this.listView);
|
||||||
this.views.add(new ImageView<T>(this, this.model));
|
this.views.add(this.imageView);
|
||||||
|
this.currentView = this.listView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -283,7 +286,12 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setup(final Map<ColumnDef, ItemColumn> cols) {
|
public void setup(final Map<ColumnDef, ItemColumn> cols) {
|
||||||
|
this.setup(cols, null, null);
|
||||||
|
}
|
||||||
|
public void setup(final Map<ColumnDef, ItemColumn> cols, GroupDef groupBy, ColumnDef pileBy) {
|
||||||
this.listView.setup(cols);
|
this.listView.setup(cols);
|
||||||
|
this.imageView.setGroupBy(groupBy);
|
||||||
|
this.imageView.setPileBy(pileBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setViewIndex(int index) {
|
public void setViewIndex(int index) {
|
||||||
@@ -291,15 +299,21 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
|
|||||||
ItemView<T> view = this.views.get(index);
|
ItemView<T> view = this.views.get(index);
|
||||||
if (this.currentView == view) { return; }
|
if (this.currentView == view) { return; }
|
||||||
|
|
||||||
final int selectedIndexBefore = this.currentView.getSelectedIndex();
|
final int backupIndexToSelect = this.currentView.getSelectedIndex();
|
||||||
final Iterable<T> selectedItemsBefore = this.currentView.getSelectedItems();
|
final Iterable<T> itemsToSelect; //only retain selected items if not single selection of first item
|
||||||
|
if (backupIndexToSelect > 0 || this.getSelectionCount() > 1) {
|
||||||
|
itemsToSelect = this.currentView.getSelectedItems();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
itemsToSelect = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.currentView.getButton().setSelected(false);
|
this.currentView.getButton().setSelected(false);
|
||||||
this.remove(this.currentView.getScroller());
|
this.remove(this.currentView.getScroller());
|
||||||
|
|
||||||
this.currentView = view;
|
this.currentView = view;
|
||||||
this.currentView.getButton().setSelected(true);
|
this.currentView.getButton().setSelected(true);
|
||||||
this.currentView.refresh(selectedItemsBefore, selectedIndexBefore);
|
this.currentView.refresh(itemsToSelect, backupIndexToSelect);
|
||||||
|
|
||||||
this.add(currentView.getScroller());
|
this.add(currentView.getScroller());
|
||||||
this.revalidate();
|
this.revalidate();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package forge.gui.toolbox.itemmanager.views;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
@@ -32,11 +33,12 @@ import forge.gui.toolbox.FSkin.SkinImage;
|
|||||||
import forge.gui.toolbox.itemmanager.ItemManager;
|
import forge.gui.toolbox.itemmanager.ItemManager;
|
||||||
import forge.gui.toolbox.itemmanager.ItemManagerModel;
|
import forge.gui.toolbox.itemmanager.ItemManagerModel;
|
||||||
import forge.item.InventoryItem;
|
import forge.item.InventoryItem;
|
||||||
import forge.view.arcane.CardArea;
|
|
||||||
import forge.view.arcane.CardPanel;
|
import forge.view.arcane.CardPanel;
|
||||||
|
|
||||||
public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
||||||
|
private static final int PADDING = 5;
|
||||||
private static final float GAP_SCALE_FACTOR = 0.04f;
|
private static final float GAP_SCALE_FACTOR = 0.04f;
|
||||||
|
private static final int GROUP_HEADER_HEIGHT = 19;
|
||||||
|
|
||||||
private final CardViewDisplay display;
|
private final CardViewDisplay display;
|
||||||
private List<Integer> selectedIndices = new ArrayList<Integer>();
|
private List<Integer> selectedIndices = new ArrayList<Integer>();
|
||||||
@@ -44,19 +46,40 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
private boolean allowMultipleSelections;
|
private boolean allowMultipleSelections;
|
||||||
private ColumnDef pileBy = null;
|
private ColumnDef pileBy = null;
|
||||||
private GroupDef groupBy = null;
|
private GroupDef groupBy = null;
|
||||||
|
private Point hoverPoint;
|
||||||
|
private Point hoverScrollPos;
|
||||||
|
private ItemInfo hoveredItem;
|
||||||
|
private ArrayList<ItemInfo> orderedItems = new ArrayList<ItemInfo>();
|
||||||
|
private ArrayList<Group> groups = new ArrayList<Group>();
|
||||||
|
|
||||||
public ImageView(ItemManager<T> itemManager0, ItemManagerModel<T> model0) {
|
public ImageView(ItemManager<T> itemManager0, ItemManagerModel<T> model0) {
|
||||||
super(itemManager0, model0);
|
super(itemManager0, model0);
|
||||||
this.display = new CardViewDisplay();
|
display = new CardViewDisplay();
|
||||||
this.display.addMouseListener(new FMouseAdapter() {
|
display.addMouseListener(new FMouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onLeftMouseDown(MouseEvent e) {
|
public void onLeftMouseDown(MouseEvent e) {
|
||||||
selectItem(e);
|
if (!selectItem(e)) {
|
||||||
|
//if didn't click on item, see if clicked on group header
|
||||||
|
if (groupBy != null) {
|
||||||
|
Point point = e.getPoint();
|
||||||
|
for (Group group : groups) {
|
||||||
|
if (group.getBounds().contains(point)) {
|
||||||
|
if (point.y < group.getTop() + GROUP_HEADER_HEIGHT) {
|
||||||
|
group.isCollapsed = !group.isCollapsed;
|
||||||
|
updateLayout();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLeftDoubleClick(MouseEvent e) {
|
public void onLeftDoubleClick(MouseEvent e) {
|
||||||
itemManager.activateSelectedItems();
|
if (hoveredItem != null && hoveredItem.selected) {
|
||||||
|
itemManager.activateSelectedItems();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -65,23 +88,23 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
itemManager.showContextMenu(e);
|
itemManager.showContextMenu(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectItem(MouseEvent e) {
|
private boolean selectItem(MouseEvent e) {
|
||||||
focus();
|
focus();
|
||||||
|
|
||||||
ItemInfo item = display.getItemAtPoint(e.getPoint());
|
ItemInfo item = getItemAtPoint(e.getPoint());
|
||||||
if (item == null) { return; }
|
if (item == null) { return false; }
|
||||||
|
|
||||||
if (item.selected) {
|
if (item.selected) {
|
||||||
//toggle selection off item if Control down and left mouse down, otherwise do nothing
|
//toggle selection off item if Control down and left mouse down, otherwise do nothing
|
||||||
if (e.getButton() != 1) {
|
if (e.getButton() != 1) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
if (e.isControlDown() && allowMultipleSelections) {
|
if (e.isControlDown() && allowMultipleSelections) {
|
||||||
item.selected = false;
|
item.selected = false;
|
||||||
selectedIndices.remove(item.index);
|
selectedIndices.remove(item.index);
|
||||||
onSelectionChange();
|
onSelectionChange();
|
||||||
item.scrollIntoView();
|
item.scrollIntoView();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!allowMultipleSelections || (!e.isControlDown() && !e.isShiftDown())) {
|
if (!allowMultipleSelections || (!e.isControlDown() && !e.isShiftDown())) {
|
||||||
@@ -91,11 +114,12 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
item.selected = true;
|
item.selected = true;
|
||||||
onSelectionChange();
|
onSelectionChange();
|
||||||
item.scrollIntoView();
|
item.scrollIntoView();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMouseExit(MouseEvent e) {
|
public void onMouseExit(MouseEvent e) {
|
||||||
if (display.updateHoveredItem(null, null)) {
|
if (updateHoveredItem(null, null)) {
|
||||||
display.repaint();
|
display.repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,25 +127,209 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
display.addMouseMotionListener(new MouseMotionAdapter() {
|
display.addMouseMotionListener(new MouseMotionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(MouseEvent e) {
|
public void mouseMoved(MouseEvent e) {
|
||||||
FScrollPane scroller = ImageView.this.getScroller();
|
FScrollPane scroller = getScroller();
|
||||||
Point hoverScrollPos = new Point(scroller.getHorizontalScrollBar().getValue(), scroller.getVerticalScrollBar().getValue());
|
Point hoverScrollPos = new Point(scroller.getHorizontalScrollBar().getValue(), scroller.getVerticalScrollBar().getValue());
|
||||||
if (display.updateHoveredItem(e.getPoint(), hoverScrollPos)) {
|
if (updateHoveredItem(e.getPoint(), hoverScrollPos)) {
|
||||||
display.repaint();
|
display.repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public GroupDef getGroupBy() {
|
||||||
protected void onResize() {
|
return groupBy;
|
||||||
if (this.pileBy == null) {
|
}
|
||||||
display.refresh(); //need to refresh to adjust wrapping of items
|
public void setGroupBy(GroupDef groupBy0) {
|
||||||
|
groupBy = groupBy0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnDef getPileBy() {
|
||||||
|
return pileBy;
|
||||||
|
}
|
||||||
|
public void setPileBy(ColumnDef pileBy0) {
|
||||||
|
pileBy = pileBy0;
|
||||||
|
if (pileBy == null) {
|
||||||
|
getScroller().setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getScroller().setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResize() {
|
||||||
|
updateLayout(); //need to update layout to adjust wrapping of items
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onRefresh() {
|
protected void onRefresh() {
|
||||||
display.refresh();
|
groups.clear();
|
||||||
|
|
||||||
|
Group otherItems;
|
||||||
|
if (groupBy == null) { //use single group with all items if not grouping
|
||||||
|
otherItems = new Group("");
|
||||||
|
groups.add(otherItems);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
otherItems = null;
|
||||||
|
for (String groupName : groupBy.getGroups()) {
|
||||||
|
groups.add(new Group(groupName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry<T, Integer> itemEntry : model.getOrderedList()) {
|
||||||
|
T item = itemEntry.getKey();
|
||||||
|
int qty = itemEntry.getValue();
|
||||||
|
int groupIndex = groupBy == null ? -1 : groupBy.getItemGroupIndex(item);
|
||||||
|
|
||||||
|
for (int i = 0; i < qty; i++) {
|
||||||
|
if (groupIndex >= 0) {
|
||||||
|
groups.get(groupIndex).add(new ItemInfo(item));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (otherItems == null) {
|
||||||
|
otherItems = new Group("Other");
|
||||||
|
groups.add(otherItems);
|
||||||
|
}
|
||||||
|
otherItems.add(new ItemInfo(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLayout() {
|
||||||
|
orderedItems.clear();
|
||||||
|
|
||||||
|
int x, groupY;
|
||||||
|
int y = PADDING;
|
||||||
|
int groupX = PADDING;
|
||||||
|
int itemAreaWidth = getVisibleSize().width;
|
||||||
|
int groupWidth = itemAreaWidth - 2 * groupX;
|
||||||
|
int pileX = groupBy == null ? groupX : 2 * groupX + 1;
|
||||||
|
int pileWidth = itemAreaWidth - 2 * pileX;
|
||||||
|
|
||||||
|
int itemIndex = 0;
|
||||||
|
int itemWidth = 50 * imageScaleFactor;
|
||||||
|
int gap = Math.round(itemWidth * GAP_SCALE_FACTOR);
|
||||||
|
int dx = itemWidth + gap;
|
||||||
|
int itemsPerRow = (pileWidth + gap) / dx;
|
||||||
|
if (itemsPerRow == 0) {
|
||||||
|
itemsPerRow = 1;
|
||||||
|
itemWidth = pileWidth;
|
||||||
|
}
|
||||||
|
int itemHeight = Math.round(itemWidth * CardPanel.ASPECT_RATIO);
|
||||||
|
int dy = itemHeight + gap;
|
||||||
|
|
||||||
|
for (Group group : groups) {
|
||||||
|
group.piles.clear();
|
||||||
|
|
||||||
|
groupY = y;
|
||||||
|
if (groupBy != null) {
|
||||||
|
y += GROUP_HEADER_HEIGHT + PADDING; //leave room for group header
|
||||||
|
if (group.isCollapsed || group.items.isEmpty()) {
|
||||||
|
group.setBounds(groupX, groupY, groupWidth, GROUP_HEADER_HEIGHT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (group.items.isEmpty()) {
|
||||||
|
group.setBounds(groupX, groupY, groupWidth, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pile pile = new Pile(); //use a pile for each row
|
||||||
|
x = pileX;
|
||||||
|
|
||||||
|
for (ItemInfo itemInfo : group.items) {
|
||||||
|
itemInfo.index = itemIndex++;
|
||||||
|
orderedItems.add(itemInfo);
|
||||||
|
|
||||||
|
if (pile.items.size() == itemsPerRow) {
|
||||||
|
pile = new Pile();
|
||||||
|
x = pileX;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemInfo.setBounds(x, y, itemWidth, itemHeight);
|
||||||
|
|
||||||
|
if (pile.items.size() == 0) {
|
||||||
|
pile.setBounds(pileX, y, pileWidth, itemHeight);
|
||||||
|
group.piles.add(pile);
|
||||||
|
}
|
||||||
|
pile.items.add(itemInfo);
|
||||||
|
x += dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
y += itemHeight;
|
||||||
|
if (groupBy != null) {
|
||||||
|
y += PADDING + 1; //leave room for group footer
|
||||||
|
}
|
||||||
|
group.setBounds(groupX, groupY, groupWidth, y - groupY);
|
||||||
|
y += PADDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
display.setPreferredSize(new Dimension(itemAreaWidth, y));
|
||||||
|
display.revalidate();
|
||||||
|
display.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemInfo getItemAtPoint(Point p) {
|
||||||
|
for (int i = groups.size() - 1; i >= 0; i--) {
|
||||||
|
Group group = groups.get(i);
|
||||||
|
if (!group.isCollapsed && group.getBounds().contains(p)) {
|
||||||
|
for (int j = group.piles.size() - 1; j >= 0; j--) {
|
||||||
|
Pile pile = group.piles.get(j);
|
||||||
|
if (pile.getBounds().contains(p)) {
|
||||||
|
for (int k = pile.items.size() - 1; k >= 0; k--) {
|
||||||
|
ItemInfo item = pile.items.get(k);
|
||||||
|
if (item.getBounds().contains(p)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dimension getVisibleSize() {
|
||||||
|
FScrollPane scroller = getScroller();
|
||||||
|
Dimension size = getScroller().getSize();
|
||||||
|
Insets insets = getScroller().getInsets();
|
||||||
|
size = new Dimension(size.width - insets.left - insets.right,
|
||||||
|
size.height - insets.top - insets.bottom);
|
||||||
|
if (scroller.getVerticalScrollBarPolicy() != ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER) {
|
||||||
|
size.width -= scroller.getVerticalScrollBar().getPreferredSize().width;
|
||||||
|
}
|
||||||
|
if (scroller.getHorizontalScrollBarPolicy() != ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) {
|
||||||
|
size.height -= scroller.getHorizontalScrollBar().getPreferredSize().height;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updateHoveredItem(Point hoverPoint0, Point hoverScrollPos0) {
|
||||||
|
hoverPoint = hoverPoint0;
|
||||||
|
hoverScrollPos = hoverScrollPos0;
|
||||||
|
|
||||||
|
ItemInfo item = null;
|
||||||
|
FScrollPane scroller = getScroller();
|
||||||
|
if (hoverPoint0 != null) {
|
||||||
|
Point displayPoint = new Point(hoverPoint0);
|
||||||
|
//account for change in scroll positions since mouse last moved
|
||||||
|
displayPoint.x += scroller.getHorizontalScrollBar().getValue() - hoverScrollPos0.x;
|
||||||
|
displayPoint.y += scroller.getVerticalScrollBar().getValue() - hoverScrollPos0.y;
|
||||||
|
item = getItemAtPoint(displayPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hoveredItem == item) { return false; }
|
||||||
|
hoveredItem = item;
|
||||||
|
if (item != null) {
|
||||||
|
CDetail.SINGLETON_INSTANCE.showCard(item.item);
|
||||||
|
CPicture.SINGLETON_INSTANCE.showImage(item.item);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -131,13 +339,13 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAllowMultipleSelections(boolean allowMultipleSelections0) {
|
public void setAllowMultipleSelections(boolean allowMultipleSelections0) {
|
||||||
this.allowMultipleSelections = allowMultipleSelections0;
|
allowMultipleSelections = allowMultipleSelections0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getItemAtIndex(int index) {
|
public T getItemAtIndex(int index) {
|
||||||
if (index >= 0 && index < getCount()) {
|
if (index >= 0 && index < getCount()) {
|
||||||
return display.items.get(index).item;
|
return orderedItems.get(index).item;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -145,12 +353,11 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
@Override
|
@Override
|
||||||
public int getIndexOfItem(T item) {
|
public int getIndexOfItem(T item) {
|
||||||
for (int i = getCount() - 1; i >= 0; i--) {
|
for (int i = getCount() - 1; i >= 0; i--) {
|
||||||
ItemInfo itemInfo = display.items.get(i);
|
if (orderedItems.get(i).item == item) {
|
||||||
if (itemInfo.item == item) {
|
return i;
|
||||||
return itemInfo.index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -165,7 +372,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return display.items.size();
|
return orderedItems.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,7 +382,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIndexAtPoint(Point p) {
|
public int getIndexAtPoint(Point p) {
|
||||||
ItemInfo item = display.getItemAtPoint(p);
|
ItemInfo item = getItemAtPoint(p);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
return item.index;
|
return item.index;
|
||||||
}
|
}
|
||||||
@@ -198,7 +405,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
@Override
|
@Override
|
||||||
public void selectAll() {
|
public void selectAll() {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
for (Integer i = 0; i < display.items.size(); i++) {
|
for (Integer i = 0; i < getCount(); i++) {
|
||||||
selectedIndices.add(i);
|
selectedIndices.add(i);
|
||||||
}
|
}
|
||||||
updateSelection();
|
updateSelection();
|
||||||
@@ -224,7 +431,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
int count = getCount();
|
int count = getCount();
|
||||||
for (Integer i : selectedIndices) {
|
for (Integer i : selectedIndices) {
|
||||||
if (i < count) {
|
if (i < count) {
|
||||||
display.items.get(i).selected = false;
|
orderedItems.get(i).selected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectedIndices.clear();
|
selectedIndices.clear();
|
||||||
@@ -232,7 +439,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
|
|
||||||
private void updateSelection() {
|
private void updateSelection() {
|
||||||
for (Integer i : selectedIndices) {
|
for (Integer i : selectedIndices) {
|
||||||
display.items.get(i).selected = true;
|
orderedItems.get(i).selected = true;
|
||||||
}
|
}
|
||||||
onSelectionChange();
|
onSelectionChange();
|
||||||
}
|
}
|
||||||
@@ -247,7 +454,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
protected void onScrollSelectionIntoView(JViewport viewport) {
|
protected void onScrollSelectionIntoView(JViewport viewport) {
|
||||||
if (selectedIndices.isEmpty()) { return; }
|
if (selectedIndices.isEmpty()) { return; }
|
||||||
|
|
||||||
ItemInfo itemInfo = display.items.get(selectedIndices.get(0));
|
ItemInfo itemInfo = orderedItems.get(selectedIndices.get(0));
|
||||||
itemInfo.scrollIntoView();
|
itemInfo.scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,234 +462,165 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
private final Rectangle bounds = new Rectangle();
|
private final Rectangle bounds = new Rectangle();
|
||||||
|
|
||||||
public Rectangle getBounds() {
|
public Rectangle getBounds() {
|
||||||
return this.bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
public void setBounds(int x, int y, int width, int height) {
|
public void setBounds(int x, int y, int width, int height) {
|
||||||
this.bounds.x = x;
|
bounds.x = x;
|
||||||
this.bounds.y = y;
|
bounds.y = y;
|
||||||
this.bounds.width = width;
|
bounds.width = width;
|
||||||
this.bounds.height = height;
|
bounds.height = height;
|
||||||
|
}
|
||||||
|
public int getLeft() {
|
||||||
|
return bounds.x;
|
||||||
|
}
|
||||||
|
public int getTop() {
|
||||||
|
return bounds.y;
|
||||||
|
}
|
||||||
|
public int getRight() {
|
||||||
|
return bounds.x + bounds.width;
|
||||||
|
}
|
||||||
|
public int getBottom() {
|
||||||
|
return bounds.y + bounds.height;
|
||||||
}
|
}
|
||||||
public void scrollIntoView() {
|
public void scrollIntoView() {
|
||||||
int x = this.bounds.x - CardArea.GUTTER_X;
|
int x = bounds.x - PADDING;
|
||||||
int y = this.bounds.y - CardArea.GUTTER_Y;
|
int y = bounds.y - PADDING;
|
||||||
int width = this.bounds.width + 2 * CardArea.GUTTER_Y;
|
int width = bounds.width + 2 * PADDING;
|
||||||
int height = this.bounds.height + 2 * CardArea.GUTTER_Y;
|
int height = bounds.height + 2 * PADDING;
|
||||||
display.scrollRectToVisible(new Rectangle(x, y, width, height));
|
display.scrollRectToVisible(new Rectangle(x, y, width, height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private class Group extends DisplayArea {
|
private class Group extends DisplayArea {
|
||||||
|
private final List<ItemInfo> items = new ArrayList<ItemInfo>();
|
||||||
private final List<Pile> piles = new ArrayList<Pile>();
|
private final List<Pile> piles = new ArrayList<Pile>();
|
||||||
|
private final String name;
|
||||||
private boolean isCollapsed;
|
private boolean isCollapsed;
|
||||||
|
|
||||||
|
public Group(String name0) {
|
||||||
|
name = name0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(ItemInfo item) {
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private class Pile extends DisplayArea {
|
private class Pile extends DisplayArea {
|
||||||
private final List<ItemInfo> items = new ArrayList<ItemInfo>();
|
private final List<ItemInfo> items = new ArrayList<ItemInfo>();
|
||||||
}
|
}
|
||||||
private class ItemInfo extends DisplayArea {
|
private class ItemInfo extends DisplayArea {
|
||||||
private final T item;
|
private final T item;
|
||||||
private Integer index;
|
private int index;
|
||||||
private boolean selected;
|
private boolean selected;
|
||||||
|
|
||||||
private ItemInfo(T item0, int index0) {
|
private ItemInfo(T item0) {
|
||||||
this.item = item0;
|
item = item0;
|
||||||
this.index = index0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.item.toString();
|
return item.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
private class CardViewDisplay extends JPanel {
|
private class CardViewDisplay extends JPanel {
|
||||||
private Point hoverPoint;
|
|
||||||
private Point hoverScrollPos;
|
|
||||||
private ItemInfo hoveredItem;
|
|
||||||
private List<ItemInfo> items = new ArrayList<ItemInfo>();
|
|
||||||
private List<Group> sections = new ArrayList<Group>();
|
|
||||||
|
|
||||||
private CardViewDisplay() {
|
private CardViewDisplay() {
|
||||||
this.setOpaque(false);
|
setOpaque(false);
|
||||||
this.setFocusable(true);
|
setFocusable(true);
|
||||||
}
|
|
||||||
|
|
||||||
private void refresh() {
|
|
||||||
int index = 0;
|
|
||||||
this.items.clear();
|
|
||||||
for (Entry<T, Integer> itemEntry : model.getOrderedList()) {
|
|
||||||
for (int i = 0; i < itemEntry.getValue(); i++) {
|
|
||||||
this.items.add(new ItemInfo(itemEntry.getKey(), index++));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.refreshSections();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshSections() {
|
|
||||||
this.sections.clear();
|
|
||||||
|
|
||||||
if (!this.items.isEmpty()) {
|
|
||||||
if (ImageView.this.pileBy == null) {
|
|
||||||
buildSpreadsheet();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buildPiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.revalidate();
|
|
||||||
this.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ItemInfo getItemAtPoint(Point p) {
|
|
||||||
for (int i = this.sections.size() - 1; i >= 0; i--) {
|
|
||||||
Group group = this.sections.get(i);
|
|
||||||
if (!group.isCollapsed && group.getBounds().contains(p)) {
|
|
||||||
for (int j = group.piles.size() - 1; j >= 0; j--) {
|
|
||||||
Pile pile = group.piles.get(j);
|
|
||||||
if (pile.getBounds().contains(p)) {
|
|
||||||
for (int k = pile.items.size() - 1; k >= 0; k--) {
|
|
||||||
ItemInfo item = pile.items.get(k);
|
|
||||||
if (item.getBounds().contains(p)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dimension getVisibleSize() {
|
|
||||||
FScrollPane scroller = ImageView.this.getScroller();
|
|
||||||
Dimension size = ImageView.this.getScroller().getSize();
|
|
||||||
Insets insets = ImageView.this.getScroller().getInsets();
|
|
||||||
size = new Dimension(size.width - insets.left - insets.right,
|
|
||||||
size.height - insets.top - insets.bottom);
|
|
||||||
if (scroller.getVerticalScrollBarPolicy() != ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER) {
|
|
||||||
size.width -= scroller.getVerticalScrollBar().getWidth();
|
|
||||||
}
|
|
||||||
if (scroller.getHorizontalScrollBarPolicy() != ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) {
|
|
||||||
size.height -= scroller.getHorizontalScrollBar().getHeight();
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildSpreadsheet() {
|
|
||||||
ImageView.this.getScroller().setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
|
||||||
|
|
||||||
Group group = new Group();
|
|
||||||
|
|
||||||
final int itemAreaWidth = getVisibleSize().width;
|
|
||||||
int itemWidth = 50 * imageScaleFactor;
|
|
||||||
int gap = Math.round(itemWidth * GAP_SCALE_FACTOR);
|
|
||||||
int dx = itemWidth + gap;
|
|
||||||
int itemsPerRow = (itemAreaWidth - 2 * CardArea.GUTTER_X + gap) / dx;
|
|
||||||
if (itemsPerRow == 0) {
|
|
||||||
itemsPerRow = 1;
|
|
||||||
itemWidth = itemAreaWidth - 2 * CardArea.GUTTER_X;
|
|
||||||
}
|
|
||||||
int itemHeight = Math.round(itemWidth * CardPanel.ASPECT_RATIO);
|
|
||||||
int dy = itemHeight + gap;
|
|
||||||
|
|
||||||
Pile pile = new Pile(); //use a pile for each row
|
|
||||||
int x = CardArea.GUTTER_X;
|
|
||||||
int y = CardArea.GUTTER_Y;
|
|
||||||
|
|
||||||
for (ItemInfo itemInfo : this.items) {
|
|
||||||
if (pile.items.size() == itemsPerRow) {
|
|
||||||
pile = new Pile();
|
|
||||||
x = CardArea.GUTTER_X;
|
|
||||||
y += dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
itemInfo.setBounds(x, y, itemWidth, itemHeight);
|
|
||||||
|
|
||||||
if (pile.items.size() == 0) {
|
|
||||||
pile.setBounds(0, y, itemAreaWidth, dy);
|
|
||||||
group.piles.add(pile);
|
|
||||||
}
|
|
||||||
pile.items.add(itemInfo);
|
|
||||||
x += dx;
|
|
||||||
}
|
|
||||||
|
|
||||||
group.setBounds(0, 0, itemAreaWidth, y + itemHeight + CardArea.GUTTER_Y);
|
|
||||||
this.setPreferredSize(group.getBounds().getSize());
|
|
||||||
|
|
||||||
this.sections.add(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildPiles() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean updateHoveredItem(Point hoverPoint0, Point hoverScrollPos0) {
|
|
||||||
this.hoverPoint = hoverPoint0;
|
|
||||||
this.hoverScrollPos = hoverScrollPos0;
|
|
||||||
|
|
||||||
ItemInfo item = null;
|
|
||||||
FScrollPane scroller = ImageView.this.getScroller();
|
|
||||||
if (hoverPoint0 != null) {
|
|
||||||
Point displayPoint = new Point(hoverPoint0);
|
|
||||||
//account for change in scroll positions since mouse last moved
|
|
||||||
displayPoint.x += scroller.getHorizontalScrollBar().getValue() - hoverScrollPos0.x;
|
|
||||||
displayPoint.y += scroller.getVerticalScrollBar().getValue() - hoverScrollPos0.y;
|
|
||||||
item = this.getItemAtPoint(displayPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.hoveredItem == item) { return false; }
|
|
||||||
this.hoveredItem = item;
|
|
||||||
if (item != null) {
|
|
||||||
CDetail.SINGLETON_INSTANCE.showCard(item.item);
|
|
||||||
CPicture.SINGLETON_INSTANCE.showImage(item.item);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void paintComponent(final Graphics g) {
|
public final void paintComponent(final Graphics g) {
|
||||||
if (this.items.isEmpty()) { return; }
|
updateHoveredItem(hoverPoint, hoverScrollPos); //ensure hovered item up to date
|
||||||
|
|
||||||
updateHoveredItem(this.hoverPoint, this.hoverScrollPos); //ensure hovered item up to date
|
|
||||||
|
|
||||||
final Graphics2D g2d = (Graphics2D) g;
|
final Graphics2D g2d = (Graphics2D) g;
|
||||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
int sectionIdx = 0, pileIdx = 0;
|
final Dimension visibleSize = getVisibleSize();
|
||||||
final int scrollTop = ImageView.this.getScroller().getVerticalScrollBar().getValue();
|
final int visibleTop = getScroller().getVerticalScrollBar().getValue();
|
||||||
final int scrollBottom = scrollTop + getVisibleSize().height;
|
final int visibleBottom = visibleTop + visibleSize.height;
|
||||||
if (ImageView.this.pileBy == null) {
|
final int visibleLeft = getScroller().getHorizontalScrollBar().getValue();
|
||||||
pileIdx = scrollTop / this.sections.get(0).piles.get(0).getBounds().height;
|
final int visibleRight = visibleLeft + visibleSize.width;
|
||||||
}
|
|
||||||
else {
|
FSkin.setGraphicsFont(g2d, ItemListView.ROW_FONT);
|
||||||
|
FontMetrics fm = g2d.getFontMetrics();
|
||||||
}
|
int fontOffsetY = (GROUP_HEADER_HEIGHT - fm.getHeight()) / 2 + fm.getAscent();
|
||||||
for (; sectionIdx < this.sections.size(); sectionIdx++, pileIdx = 0) {
|
|
||||||
Group group = this.sections.get(sectionIdx);
|
for (Group group : groups) {
|
||||||
if (group.getBounds().y >= scrollBottom) {
|
if (group.getBottom() < visibleTop) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (group.getTop() >= visibleBottom) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (this.sections.size() > 1) {
|
if (groupBy != null) {
|
||||||
//TODO: Draw group name/border
|
Rectangle bounds = group.getBounds();
|
||||||
if (group.isCollapsed) {
|
FSkin.setGraphicsColor(g2d, ItemListView.HEADER_BACK_COLOR);
|
||||||
|
g2d.fillRect(bounds.x, bounds.y, bounds.width, GROUP_HEADER_HEIGHT - 1);
|
||||||
|
FSkin.setGraphicsColor(g2d, ItemListView.FORE_COLOR);
|
||||||
|
g2d.drawString(group.name + " (" + group.items.size() + ")", bounds.x + PADDING, bounds.y + fontOffsetY);
|
||||||
|
if (!group.items.isEmpty()) { //draw expand/collapse glyph as long as group isn't empty
|
||||||
|
int offset = GROUP_HEADER_HEIGHT / 4;
|
||||||
|
int x1 = bounds.x + bounds.width - PADDING;
|
||||||
|
int x2 = x1 - offset;
|
||||||
|
int x3 = x2 - offset;
|
||||||
|
int y2 = bounds.y + GROUP_HEADER_HEIGHT / 2;
|
||||||
|
if (!group.isCollapsed) {
|
||||||
|
offset *= -1;
|
||||||
|
y2++;
|
||||||
|
}
|
||||||
|
int y1 = y2 - offset;
|
||||||
|
g2d.drawLine(x1, y1, x2, y2);
|
||||||
|
g2d.drawLine(x2, y2, x3, y1);
|
||||||
|
if (group.isCollapsed) {
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
offset--;
|
||||||
|
}
|
||||||
|
y1 += offset;
|
||||||
|
y2 += offset;
|
||||||
|
g2d.drawLine(x1, y1, x2, y2);
|
||||||
|
g2d.drawLine(x2, y2, x3, y1);
|
||||||
|
}
|
||||||
|
FSkin.setGraphicsColor(g2d, ItemListView.GRID_COLOR);
|
||||||
|
g2d.drawRect(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);
|
||||||
|
if (group.isCollapsed || group.items.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
int y = bounds.y + GROUP_HEADER_HEIGHT - 1; //draw bottom border of header
|
||||||
|
g2d.drawLine(bounds.x, y, bounds.x + bounds.width - 1, y);
|
||||||
}
|
}
|
||||||
for (; pileIdx < group.piles.size(); pileIdx++) {
|
else if (group.items.isEmpty()) {
|
||||||
Pile pile = group.piles.get(pileIdx);
|
continue;
|
||||||
if (pile.getBounds().y >= scrollBottom) {
|
}
|
||||||
|
for (Pile pile : group.piles) {
|
||||||
|
if (pile.getBottom() < visibleTop || pile.getRight() < visibleLeft) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pile.getTop() >= visibleBottom || pile.getLeft() >= visibleRight) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (ItemInfo itemInfo : pile.items) {
|
for (ItemInfo itemInfo : pile.items) {
|
||||||
if (itemInfo != this.hoveredItem) { //save hovered item for last
|
if (itemInfo.getBottom() < visibleTop || itemInfo.getRight() < visibleLeft) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (itemInfo.getTop() >= visibleBottom || itemInfo.getLeft() >= visibleRight) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (itemInfo != hoveredItem) { //save hovered item for last
|
||||||
drawItemImage(g2d, itemInfo);
|
drawItemImage(g2d, itemInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.hoveredItem != null) { //draw hovered item on top
|
if (hoveredItem != null) { //draw hovered item on top
|
||||||
drawItemImage(g2d, this.hoveredItem);
|
drawItemImage(g2d, hoveredItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,7 +637,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
bounds.width + 2 * selBorderSize, bounds.height + 2 * selBorderSize,
|
bounds.width + 2 * selBorderSize, bounds.height + 2 * selBorderSize,
|
||||||
cornerSize + selBorderSize, cornerSize + selBorderSize);
|
cornerSize + selBorderSize, cornerSize + selBorderSize);
|
||||||
}
|
}
|
||||||
else if (itemInfo == this.hoveredItem) {
|
else if (itemInfo == hoveredItem) {
|
||||||
int hoverBorderSize = Math.max(1, selBorderSize / 2);
|
int hoverBorderSize = Math.max(1, selBorderSize / 2);
|
||||||
g.setColor(Color.green);
|
g.setColor(Color.green);
|
||||||
g.fillRoundRect(bounds.x - hoverBorderSize, bounds.y - hoverBorderSize,
|
g.fillRoundRect(bounds.x - hoverBorderSize, bounds.y - hoverBorderSize,
|
||||||
@@ -517,7 +655,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
else {
|
else {
|
||||||
g.setColor(Color.white);
|
g.setColor(Color.white);
|
||||||
Shape clip = g.getClip();
|
Shape clip = g.getClip();
|
||||||
g.setClip(bounds.x, bounds.y, bounds.width, bounds.height);
|
g.setClip(bounds);
|
||||||
g.drawString(itemInfo.item.getName(), bounds.x + 10, bounds.y + 20);
|
g.drawString(itemInfo.item.getName(), bounds.x + 10, bounds.y + 20);
|
||||||
g.setClip(clip);
|
g.setClip(clip);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,14 +78,14 @@ import forge.item.InventoryItem;
|
|||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public final class ItemListView<T extends InventoryItem> extends ItemView<T> {
|
public final class ItemListView<T extends InventoryItem> extends ItemView<T> {
|
||||||
static final SkinColor BACK_COLOR = FSkin.getColor(FSkin.Colors.CLR_ZEBRA);
|
static final SkinColor BACK_COLOR = FSkin.getColor(FSkin.Colors.CLR_ZEBRA);
|
||||||
private static final SkinColor FORE_COLOR = FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
static final SkinColor FORE_COLOR = FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
||||||
private static final SkinColor SEL_ACTIVE_COLOR = FSkin.getColor(FSkin.Colors.CLR_ACTIVE);
|
private static final SkinColor SEL_ACTIVE_COLOR = FSkin.getColor(FSkin.Colors.CLR_ACTIVE);
|
||||||
private static final SkinColor SEL_INACTIVE_COLOR = FSkin.getColor(FSkin.Colors.CLR_INACTIVE);
|
private static final SkinColor SEL_INACTIVE_COLOR = FSkin.getColor(FSkin.Colors.CLR_INACTIVE);
|
||||||
private static final SkinColor HEADER_BACK_COLOR = BACK_COLOR.getContrastColor(-10);
|
static final SkinColor HEADER_BACK_COLOR = BACK_COLOR.getContrastColor(-10);
|
||||||
static final SkinColor ALT_ROW_COLOR = BACK_COLOR.getContrastColor(-20);
|
static final SkinColor ALT_ROW_COLOR = BACK_COLOR.getContrastColor(-20);
|
||||||
private static final SkinColor GRID_COLOR = BACK_COLOR.getContrastColor(20);
|
static final SkinColor GRID_COLOR = BACK_COLOR.getContrastColor(20);
|
||||||
private static final SkinBorder HEADER_BORDER = new FSkin.CompoundSkinBorder(new FSkin.MatteSkinBorder(0, 0, 1, 1, GRID_COLOR), new EmptyBorder(0, 1, 0, 0));
|
private static final SkinBorder HEADER_BORDER = new FSkin.CompoundSkinBorder(new FSkin.MatteSkinBorder(0, 0, 1, 1, GRID_COLOR), new EmptyBorder(0, 1, 0, 0));
|
||||||
private static final SkinFont ROW_FONT = FSkin.getFont(12);
|
static final SkinFont ROW_FONT = FSkin.getFont(12);
|
||||||
private static final int ROW_HEIGHT = 19;
|
private static final int ROW_HEIGHT = 19;
|
||||||
|
|
||||||
private final ItemTable table = new ItemTable();
|
private final ItemTable table = new ItemTable();
|
||||||
@@ -104,6 +104,7 @@ public final class ItemListView<T extends InventoryItem> extends ItemView<T> {
|
|||||||
public ItemListView(ItemManager<T> itemManager0, ItemManagerModel<T> model0) {
|
public ItemListView(ItemManager<T> itemManager0, ItemManagerModel<T> model0) {
|
||||||
super(itemManager0, model0);
|
super(itemManager0, model0);
|
||||||
this.tableModel = new ItemTableModel(model0);
|
this.tableModel = new ItemTableModel(model0);
|
||||||
|
this.setAllowMultipleSelections(false);
|
||||||
|
|
||||||
// use different selection highlight colors for focused vs. unfocused tables
|
// use different selection highlight colors for focused vs. unfocused tables
|
||||||
this.table.addMouseListener(new FMouseAdapter() {
|
this.table.addMouseListener(new FMouseAdapter() {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import forge.gui.toolbox.FLabel;
|
import forge.gui.toolbox.FLabel;
|
||||||
import forge.gui.toolbox.FScrollPane;
|
import forge.gui.toolbox.FScrollPane;
|
||||||
import forge.gui.toolbox.FSkin;
|
import forge.gui.toolbox.FSkin;
|
||||||
|
import forge.gui.toolbox.FSkin.SkinColor;
|
||||||
import forge.gui.toolbox.FSkin.SkinImage;
|
import forge.gui.toolbox.FSkin.SkinImage;
|
||||||
import forge.gui.toolbox.ToolTipListener;
|
import forge.gui.toolbox.ToolTipListener;
|
||||||
import forge.gui.toolbox.itemmanager.ItemManager;
|
import forge.gui.toolbox.itemmanager.ItemManager;
|
||||||
@@ -40,6 +41,8 @@ import forge.gui.toolbox.itemmanager.ItemManagerModel;
|
|||||||
import forge.item.InventoryItem;
|
import forge.item.InventoryItem;
|
||||||
|
|
||||||
public abstract class ItemView<T extends InventoryItem> {
|
public abstract class ItemView<T extends InventoryItem> {
|
||||||
|
private static final SkinColor BORDER_COLOR = FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
||||||
|
|
||||||
protected final ItemManager<T> itemManager;
|
protected final ItemManager<T> itemManager;
|
||||||
protected final ItemManagerModel<T> model;
|
protected final ItemManagerModel<T> model;
|
||||||
private final FScrollPane scroller;
|
private final FScrollPane scroller;
|
||||||
@@ -51,7 +54,7 @@ public abstract class ItemView<T extends InventoryItem> {
|
|||||||
this.itemManager = itemManager0;
|
this.itemManager = itemManager0;
|
||||||
this.model = model0;
|
this.model = model0;
|
||||||
this.scroller = new FScrollPane(false);
|
this.scroller = new FScrollPane(false);
|
||||||
this.scroller.setBorder(new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_TEXT)));
|
this.scroller.setBorder(new FSkin.LineSkinBorder(BORDER_COLOR));
|
||||||
this.button = new FLabel.Builder().hoverable().selectable(true)
|
this.button = new FLabel.Builder().hoverable().selectable(true)
|
||||||
.icon(getIcon()).iconScaleAuto(false)
|
.icon(getIcon()).iconScaleAuto(false)
|
||||||
.tooltip(getCaption()).build();
|
.tooltip(getCaption()).build();
|
||||||
@@ -114,7 +117,8 @@ public abstract class ItemView<T extends InventoryItem> {
|
|||||||
protected abstract void onRefresh();
|
protected abstract void onRefresh();
|
||||||
private void fixSelection(final Iterable<T> itemsToSelect, final int backupIndexToSelect) {
|
private void fixSelection(final Iterable<T> itemsToSelect, final int backupIndexToSelect) {
|
||||||
if (itemsToSelect == null) {
|
if (itemsToSelect == null) {
|
||||||
setSelectedIndex(0); //select first item if no items to select
|
setSelectedIndex(0, false); //select first item if no items to select
|
||||||
|
getScroller().getVerticalScrollBar().setValue(0); //ensure scrolled to top
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!setSelectedItems(itemsToSelect)) {
|
if (!setSelectedItems(itemsToSelect)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user