Add image view to item managers

This commit is contained in:
drdev
2014-02-01 01:16:43 +00:00
parent 070fd7695a
commit 2b685348ab
14 changed files with 620 additions and 64 deletions

1
.gitattributes vendored
View File

@@ -15688,6 +15688,7 @@ forge-gui/src/main/java/forge/gui/toolbox/itemmanager/package-info.java -text
forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ColorSetRenderer.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ColorSetRenderer.java -text
forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ColumnDef.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ColumnDef.java -text
forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/DeckQuantityRenderer.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/DeckQuantityRenderer.java -text
forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ImageView.java -text
forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/IntegerRenderer.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/IntegerRenderer.java -text
forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemCellRenderer.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemCellRenderer.java -text
forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemColumn.java -text forge-gui/src/main/java/forge/gui/toolbox/itemmanager/views/ItemColumn.java -text

Binary file not shown.

Before

Width:  |  Height:  |  Size: 643 KiB

After

Width:  |  Height:  |  Size: 643 KiB

View File

@@ -71,6 +71,9 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
catalogManager.setAlwaysNonUnique(true); catalogManager.setAlwaysNonUnique(true);
deckManager.setAlwaysNonUnique(true); deckManager.setAlwaysNonUnique(true);
catalogManager.setViewIndex(1);
deckManager.setViewIndex(1);
this.setCatalogManager(catalogManager); this.setCatalogManager(catalogManager);
this.setDeckManager(deckManager); this.setDeckManager(deckManager);
} }
@@ -154,7 +157,7 @@ public class CEditorDraftingProcess extends ACEditorBase<PaperCard, DeckGroup> {
deck.getOrCreate(DeckSection.Sideboard).addAll(this.getDeckManager().getPool()); deck.getOrCreate(DeckSection.Sideboard).addAll(this.getDeckManager().getPool());
final String landSet = IBoosterDraft.LAND_SET_CODE[0].getCode(); final String landSet = IBoosterDraft.LAND_SET_CODE[0].getCode();
final int landsCount = 10; final int landsCount = 10;
for(String landName : MagicColor.Constant.BASIC_LANDS) { for(String landName : MagicColor.Constant.BASIC_LANDS) {
final int numArt = Singletons.getMagicDb().getCommonCards().getArtCount(landName, landSet); final int numArt = Singletons.getMagicDb().getCommonCards().getArtCount(landName, landSet);

View File

@@ -124,7 +124,7 @@ public enum FScreen {
VDeckEditorUI.SINGLETON_INSTANCE, VDeckEditorUI.SINGLETON_INSTANCE,
CDeckEditorUI.SINGLETON_INSTANCE, CDeckEditorUI.SINGLETON_INSTANCE,
"Draft", "Draft",
FSkin.getImage(FSkin.ZoneImages.ICO_HAND), FSkin.getImage(FSkin.ZoneImages.IMG_HAND),
true, true,
"Leave Draft", "Leave Draft",
NewConstants.EDITOR_LAYOUT_FILE), NewConstants.EDITOR_LAYOUT_FILE),

View File

@@ -439,7 +439,7 @@ public class FLabel extends SkinnedLabel implements ILocalRepaint {
if (this.getIcon() != null) { if (this.getIcon() != null) {
width += this.getIcon().getIconWidth() + this.getIconTextGap(); width += this.getIcon().getIconWidth() + this.getIconTextGap();
} }
if (opaque) { if (opaque || selectable) {
width += 6; //account for border/padding if opaque width += 6; //account for border/padding if opaque
} }
return width; return width;

View File

@@ -861,12 +861,12 @@ public enum FSkin {
/** int[] can hold [xcoord, ycoord, width, height, newwidth, newheight]. */ /** int[] can hold [xcoord, ycoord, width, height, newwidth, newheight]. */
public enum ZoneImages implements SkinProp { public enum ZoneImages implements SkinProp {
ICO_HAND (new int[] {280, 40, 40, 40}), IMG_HAND (new int[] {280, 40, 40, 40}),
ICO_LIBRARY (new int[] {280, 0, 40, 40}), IMG_LIBRARY (new int[] {280, 0, 40, 40}),
ICO_EXILE (new int[] {320, 40, 40, 40}), IMG_EXILE (new int[] {320, 40, 40, 40}),
ICO_FLASHBACK (new int[] {280, 80, 40, 40}), IMG_FLASHBACK (new int[] {280, 80, 40, 40}),
ICO_GRAVEYARD (new int[] {320, 0, 40, 40}), IMG_GRAVEYARD (new int[] {320, 0, 40, 40}),
ICO_POISON (new int[] {320, 80, 40, 40}); IMG_POISON (new int[] {320, 80, 40, 40});
private int[] coords; private int[] coords;
/** @param xy &emsp; int[] coordinates */ /** @param xy &emsp; int[] coordinates */
@@ -1085,6 +1085,8 @@ public enum FSkin {
ICO_SAVE (new int[] {660, 560, 20, 20}), ICO_SAVE (new int[] {660, 560, 20, 20}),
ICO_SAVEAS (new int[] {660, 580, 20, 20}), ICO_SAVEAS (new int[] {660, 580, 20, 20}),
ICO_CLOSE (new int[] {640, 640, 20, 20}), ICO_CLOSE (new int[] {640, 640, 20, 20}),
ICO_LIST (new int[] {640, 660, 20, 20}),
ICO_CARD_IMAGE (new int[] {660, 660, 20, 20}),
ICO_UNKNOWN (new int[] {0, 720, 80, 80}), ICO_UNKNOWN (new int[] {0, 720, 80, 80}),
ICO_LOGO (new int[] {480, 0, 200, 200}), ICO_LOGO (new int[] {480, 0, 200, 200}),
ICO_FLIPCARD (new int[] {400, 0, 80, 120}), ICO_FLIPCARD (new int[] {400, 0, 80, 120}),

View File

@@ -8,11 +8,16 @@ import javax.swing.JComponent;
*/ */
public final class LayoutHelper { public final class LayoutHelper {
private final int parentWidth, parentHeight; private final int parentWidth, parentHeight;
private int x, y, lineBottom; private int x, y, lineBottom, gapX, gapY;
public LayoutHelper(JComponent parent) { public LayoutHelper(JComponent parent) {
this(parent, 3, 3);
}
public LayoutHelper(JComponent parent, int gapX0, int gapY0) {
parentWidth = parent.getWidth(); parentWidth = parent.getWidth();
parentHeight = parent.getHeight(); parentHeight = parent.getHeight();
gapX = gapX0;
gapY = gapY0;
} }
/** /**
@@ -96,7 +101,7 @@ public final class LayoutHelper {
if (y >= parentHeight) { return; } if (y >= parentHeight) { return; }
} }
comp.setBounds(x, y, width, height); comp.setBounds(x, y, width, height);
x += width + 3; x += width + gapX;
if (y + height > lineBottom) { if (y + height > lineBottom) {
lineBottom = y + height; lineBottom = y + height;
} }
@@ -118,7 +123,7 @@ public final class LayoutHelper {
public void newLine() { public void newLine() {
if (lineBottom == y) { return; } if (lineBottom == y) { return; }
x = 0; x = 0;
y = lineBottom + 3; y = lineBottom + gapY;
lineBottom = y; lineBottom = y;
} }
@@ -127,7 +132,7 @@ public final class LayoutHelper {
*/ */
public void newLine(int dy) { public void newLine(int dy) {
x = 0; x = 0;
y = lineBottom + 3 + dy; y = lineBottom + gapY + dy;
lineBottom = y; lineBottom = y;
} }
@@ -158,4 +163,18 @@ public final class LayoutHelper {
public int getY() { public int getY() {
return y; return y;
} }
/**
* @return gap X
*/
public int getGapX() {
return gapX;
}
/**
* @return gap Y
*/
public int getGapY() {
return gapY;
}
} }

View File

@@ -3,6 +3,7 @@ package forge.gui.toolbox.itemmanager;
import java.util.List; import java.util.List;
import javax.swing.JMenu; import javax.swing.JMenu;
import forge.Singletons; import forge.Singletons;
import forge.game.GameFormat; import forge.game.GameFormat;
import forge.gui.GuiUtils; import forge.gui.GuiUtils;

View File

@@ -49,7 +49,6 @@ import com.google.common.collect.Iterables;
import forge.Command; import forge.Command;
import forge.gui.GuiUtils; import forge.gui.GuiUtils;
import forge.gui.toolbox.ContextMenuBuilder; import forge.gui.toolbox.ContextMenuBuilder;
import forge.gui.toolbox.FComboBoxWrapper;
import forge.gui.toolbox.FLabel; import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FSkin.SkinnedCheckBox; import forge.gui.toolbox.FSkin.SkinnedCheckBox;
@@ -59,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.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;
import forge.gui.toolbox.itemmanager.views.ItemView; import forge.gui.toolbox.itemmanager.views.ItemView;
@@ -118,9 +118,9 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
.fontSize(12) .fontSize(12)
.build(); .build();
private final FComboBoxWrapper<ItemView<T>> cbViews = new FComboBoxWrapper<ItemView<T>>(); private final List<ItemView<T>> views = new ArrayList<ItemView<T>>();
private final ItemListView<T> listView;
private ItemView<T> currentView; private ItemView<T> currentView;
private final ItemListView<T> table;
private boolean initialized; private boolean initialized;
protected boolean lockFiltering; protected boolean lockFiltering;
@@ -135,23 +135,12 @@ 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.table = new ItemListView<T>(this, this.model); this.listView = new ItemListView<T>(this, this.model);
this.table.setAllowMultipleSelections(false); this.listView.setAllowMultipleSelections(false);
this.currentView = this.table; this.currentView = this.listView;
this.cbViews.addItem(this.table); this.views.add(this.listView);
this.cbViews.addItemListener(new ItemListener() { this.views.add(new ImageView<T>(this, this.model));
@SuppressWarnings("unchecked")
@Override
public void itemStateChanged(ItemEvent e) {
ItemView<T> view = (ItemView<T>) e.getItem();
if (currentView == view) { return; }
ItemManager.this.remove(currentView.getScroller());
currentView = view;
ItemManager.this.add(currentView.getScroller());
ItemManager.this.revalidate();
}
});
} }
/** /**
@@ -160,8 +149,10 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
public void initialize() { public void initialize() {
if (this.initialized) { return; } //avoid initializing more than once if (this.initialized) { return; } //avoid initializing more than once
//build table view //initialize views
this.table.initialize(); for (int i = 0; i < this.views.size(); i++) {
this.views.get(i).initialize(i);
}
//build enable filters checkbox //build enable filters checkbox
ItemFilter.layoutCheckbox(this.chkEnableFilters); ItemFilter.layoutCheckbox(this.chkEnableFilters);
@@ -196,7 +187,10 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
this.add(this.btnFilters); this.add(this.btnFilters);
this.add(this.lblCaption); this.add(this.lblCaption);
this.add(this.lblRatio); this.add(this.lblRatio);
this.cbViews.addTo(this); for (ItemView<T> view : this.views) {
this.add(view.getButton());
view.getButton().setSelected(view == this.currentView);
}
this.add(this.currentView.getScroller()); this.add(this.currentView.getScroller());
final Runnable cmdAddCurrentSearch = new Runnable() { final Runnable cmdAddCurrentSearch = new Runnable() {
@@ -289,7 +283,28 @@ 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.table.setup(cols); this.listView.setup(cols);
}
public void setViewIndex(int index) {
if (index < 0 || index >= this.views.size()) { return; }
ItemView<T> view = this.views.get(index);
if (this.currentView == view) { return; }
final int selectedIndexBefore = this.currentView.getSelectedIndex();
final Iterable<T> selectedItemsBefore = this.currentView.getSelectedItems();
this.currentView.getButton().setSelected(false);
this.remove(this.currentView.getScroller());
this.currentView = view;
this.currentView.getButton().setSelected(true);
this.currentView.refresh(selectedItemsBefore, selectedIndexBefore);
this.add(currentView.getScroller());
this.revalidate();
this.repaint();
this.focus();
} }
@Override @Override
@@ -333,8 +348,8 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
helper.include(this.btnFilters, 61, FTextField.HEIGHT); helper.include(this.btnFilters, 61, FTextField.HEIGHT);
int captionWidth = this.lblCaption.getAutoSizeWidth(); int captionWidth = this.lblCaption.getAutoSizeWidth();
int ratioWidth = this.lblRatio.getAutoSizeWidth(); int ratioWidth = this.lblRatio.getAutoSizeWidth();
int cbViewsWidth = this.cbViews.getAutoSizeWidth(); int viewButtonWidth = FTextField.HEIGHT;
int availableCaptionWidth = helper.getParentWidth() - cbViewsWidth - ratioWidth - helper.getX() - 9; int availableCaptionWidth = helper.getParentWidth() - viewButtonWidth * this.views.size() - ratioWidth - helper.getX() - (this.views.size() + 2) * helper.getGapX();
if (captionWidth > availableCaptionWidth) { //truncate caption if not enough room for it if (captionWidth > availableCaptionWidth) { //truncate caption if not enough room for it
this.lblCaption.setToolTipText(this.lblCaption.getText()); this.lblCaption.setToolTipText(this.lblCaption.getText());
captionWidth = availableCaptionWidth; captionWidth = availableCaptionWidth;
@@ -343,8 +358,11 @@ public abstract class ItemManager<T extends InventoryItem> extends JPanel {
this.lblCaption.setToolTipText(null); this.lblCaption.setToolTipText(null);
} }
helper.include(this.lblCaption, captionWidth, FTextField.HEIGHT); helper.include(this.lblCaption, captionWidth, FTextField.HEIGHT);
helper.fillLine(this.lblRatio, FTextField.HEIGHT, cbViewsWidth); //leave room for cbViews helper.fillLine(this.lblRatio, FTextField.HEIGHT, (viewButtonWidth + helper.getGapX()) * this.views.size() - 1); //leave room for view buttons
helper.fillLine(this.cbViews.getComponent(), FTextField.HEIGHT); for (ItemView<T> view : this.views) {
helper.include(view.getButton(), viewButtonWidth, FTextField.HEIGHT);
helper.offset(-1, 0);
}
helper.fill(this.currentView.getScroller()); helper.fill(this.currentView.getScroller());
} }

View File

@@ -0,0 +1,481 @@
package forge.gui.toolbox.itemmanager.views;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JViewport;
import javax.swing.ScrollPaneConstants;
import forge.ImageCache;
import forge.gui.deckeditor.DeckProxy;
import forge.gui.toolbox.FMouseAdapter;
import forge.gui.toolbox.FScrollPane;
import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FSkin.SkinImage;
import forge.gui.toolbox.itemmanager.ItemManager;
import forge.gui.toolbox.itemmanager.ItemManagerModel;
import forge.item.InventoryItem;
import forge.view.arcane.CardArea;
import forge.view.arcane.CardPanel;
public class ImageView<T extends InventoryItem> extends ItemView<T> {
private static final float GAP_SCALE_FACTOR = 0.04f;
public enum LayoutType {
Spreadsheet,
Piles
}
private final CardViewDisplay display;
private final ItemManagerModel<T> model;
private List<Integer> selectedIndices = new ArrayList<Integer>();
private int imageScaleFactor = 3;
private boolean allowMultipleSelections;
private LayoutType layoutType = LayoutType.Spreadsheet;
public ImageView(ItemManager<T> itemManager0, ItemManagerModel<T> model0) {
super(itemManager0);
this.display = new CardViewDisplay();
this.model = model0;
this.display.addMouseListener(new FMouseAdapter() {
@Override
public void onLeftMouseDown(MouseEvent e) {
selectItem(e);
}
@Override
public void onLeftDoubleClick(MouseEvent e) {
getItemManager().activateSelectedItems();
}
@Override
public void onRightClick(MouseEvent e) {
selectItem(e);
getItemManager().showContextMenu(e);
}
private void selectItem(MouseEvent e) {
focus();
ItemInfo item = display.getItemAtPoint(e.getPoint());
if (item == null) { return; }
if (item.selected) {
//toggle selection off item if Control down and left mouse down, otherwise do nothing
if (e.getButton() != 1) {
return;
}
if (e.isControlDown() && allowMultipleSelections) {
item.selected = false;
selectedIndices.remove(item.index);
onSelectionChange();
item.scrollIntoView();
return;
}
}
if (!allowMultipleSelections || (!e.isControlDown() && !e.isShiftDown())) {
clearSelection();
}
selectedIndices.add(0, item.index);
item.selected = true;
onSelectionChange();
item.scrollIntoView();
}
});
}
@Override
protected void onResize() {
if (this.layoutType == LayoutType.Spreadsheet) {
display.refresh(); //need to refresh to adjust wrapping of items
}
}
@Override
protected void onRefresh() {
display.refresh();
}
@Override
public JComponent getComponent() {
return display;
}
@Override
public void setAllowMultipleSelections(boolean allowMultipleSelections0) {
this.allowMultipleSelections = allowMultipleSelections0;
}
@Override
public T getItemAtIndex(int index) {
if (index >= 0 && index < getCount()) {
return display.items.get(index).item;
}
return null;
}
@Override
public int getIndexOfItem(T item) {
for (int i = getCount() - 1; i >= 0; i--) {
ItemInfo itemInfo = display.items.get(i);
if (itemInfo.item == item) {
return itemInfo.index;
}
}
return 0;
}
@Override
public int getSelectedIndex() {
return selectedIndices.isEmpty() ? -1 : selectedIndices.get(0);
}
@Override
public Iterable<Integer> getSelectedIndices() {
return selectedIndices;
}
@Override
public int getCount() {
return display.items.size();
}
@Override
public int getSelectionCount() {
return selectedIndices.size();
}
@Override
public int getIndexAtPoint(Point p) {
ItemInfo item = display.getItemAtPoint(p);
if (item != null) {
return item.index;
}
return -1;
}
@Override
protected SkinImage getIcon() {
if (getItemManager().getGenericType().equals(DeckProxy.class)) {
return FSkin.getImage(FSkin.EditorImages.IMG_PACK).resize(18, 18);
}
return FSkin.getIcon(FSkin.InterfaceIcons.ICO_CARD_IMAGE);
}
@Override
protected String getCaption() {
return "Image View";
}
@Override
public void selectAll() {
clearSelection();
for (Integer i = 0; i < display.items.size(); i++) {
selectedIndices.add(i);
}
updateSelection();
}
@Override
protected void onSetSelectedIndex(int index) {
clearSelection();
selectedIndices.add(index);
updateSelection();
}
@Override
protected void onSetSelectedIndices(Iterable<Integer> indices) {
clearSelection();
for (Integer index : indices) {
selectedIndices.add(index);
}
updateSelection();
}
private void clearSelection() {
int count = getCount();
for (Integer i : selectedIndices) {
if (i < count) {
display.items.get(i).selected = false;
}
}
selectedIndices.clear();
}
private void updateSelection() {
for (Integer i : selectedIndices) {
display.items.get(i).selected = true;
}
onSelectionChange();
}
@Override
protected void onSelectionChange() {
super.onSelectionChange();
display.repaint();
}
@Override
protected void onScrollSelectionIntoView(JViewport viewport) {
if (selectedIndices.isEmpty()) { return; }
ItemInfo itemInfo = display.items.get(selectedIndices.get(0));
itemInfo.scrollIntoView();
}
private class DisplayArea {
private final Rectangle bounds = new Rectangle();
public Rectangle getBounds() {
return this.bounds;
}
public void setBounds(int x, int y, int width, int height) {
this.bounds.x = x;
this.bounds.y = y;
this.bounds.width = width;
this.bounds.height = height;
}
public void scrollIntoView() {
int x = this.bounds.x - CardArea.GUTTER_X;
int y = this.bounds.y - CardArea.GUTTER_Y;
int width = this.bounds.width + 2 * CardArea.GUTTER_Y;
int height = this.bounds.height + 2 * CardArea.GUTTER_Y;
display.scrollRectToVisible(new Rectangle(x, y, width, height));
}
}
private class Section extends DisplayArea {
private final List<Pile> piles = new ArrayList<Pile>();
private boolean isCollapsed;
}
private class Pile extends DisplayArea {
private final List<ItemInfo> items = new ArrayList<ItemInfo>();
}
private class ItemInfo extends DisplayArea {
private final T item;
private Integer index;
private boolean selected;
private ItemInfo(T item0) {
this.item = item0;
}
@Override
public String toString() {
return this.item.toString();
}
}
@SuppressWarnings("serial")
private class CardViewDisplay extends JPanel {
private List<ItemInfo> items = new ArrayList<ItemInfo>();
private List<Section> sections = new ArrayList<Section>();
private CardViewDisplay() {
this.setOpaque(false);
this.setFocusable(true);
}
private void refresh() {
this.items.clear();
for (Entry<T, Integer> itemEntry : model.getItems()) {
for (int i = 0; i < itemEntry.getValue(); i++) {
this.items.add(new ItemInfo(itemEntry.getKey()));
}
}
Collections.sort(this.items, new Comparator<ItemInfo>() {
@Override
public int compare(ItemInfo arg0, ItemInfo arg1) {
return arg0.item.getName().compareTo(arg1.item.getName());
}
});
for (int i = 0; i < this.items.size(); i++) {
this.items.get(i).index = i;
}
this.refreshSections();
}
private void refreshSections() {
this.sections.clear();
if (!this.items.isEmpty()) {
switch (ImageView.this.layoutType) {
case Spreadsheet:
buildSpreadsheet();
break;
case Piles:
buildPiles();
break;
}
}
this.revalidate();
this.repaint();
}
private ItemInfo getItemAtPoint(Point p) {
for (int i = this.sections.size() - 1; i >= 0; i--) {
Section section = this.sections.get(i);
if (!section.isCollapsed && section.getBounds().contains(p)) {
for (int j = section.piles.size() - 1; j >= 0; j--) {
Pile pile = section.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);
Section section = new Section();
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);
section.piles.add(pile);
}
pile.items.add(itemInfo);
x += dx;
}
section.setBounds(0, 0, itemAreaWidth, y + itemHeight + CardArea.GUTTER_Y);
this.setPreferredSize(section.getBounds().getSize());
this.sections.add(section);
}
private void buildPiles() {
}
@Override
public final void paintComponent(final Graphics g) {
if (this.items.isEmpty()) { return; }
final Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
final int itemWidth = this.items.get(0).getBounds().width;
final int selBorderSize = Math.max(1, Math.round(itemWidth * GAP_SCALE_FACTOR / 2) - 1);
final int borderSize = Math.round(itemWidth * CardPanel.BLACK_BORDER_SIZE);
final int cornerSize = Math.max(4, Math.round(itemWidth * CardPanel.ROUNDED_CORNER_SIZE));
int sectionIdx = 0, pileIdx = 0;
final int scrollTop = ImageView.this.getScroller().getVerticalScrollBar().getValue();
final int scrollBottom = scrollTop + getVisibleSize().height;
switch (ImageView.this.layoutType) {
case Spreadsheet:
pileIdx = scrollTop / this.sections.get(0).piles.get(0).getBounds().height;
break;
case Piles:
break;
}
for (; sectionIdx < this.sections.size(); sectionIdx++, pileIdx = 0) {
Section section = this.sections.get(sectionIdx);
if (section.getBounds().y >= scrollBottom) {
break;
}
if (this.sections.size() > 1) {
//TODO: Draw section name/border
if (section.isCollapsed) {
continue;
}
}
for (; pileIdx < section.piles.size(); pileIdx++) {
Pile pile = section.piles.get(pileIdx);
if (pile.getBounds().y >= scrollBottom) {
break;
}
for (ItemInfo itemInfo : pile.items) {
Rectangle bounds = itemInfo.getBounds();
if (itemInfo.selected) {
g2d.setColor(Color.green);
g2d.fillRoundRect(bounds.x - selBorderSize, bounds.y - selBorderSize,
bounds.width + 2 * selBorderSize, bounds.height + 2 * selBorderSize,
cornerSize + selBorderSize, cornerSize + selBorderSize);
}
g2d.setColor(Color.black);
g2d.fillRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, cornerSize, cornerSize);
BufferedImage img = ImageCache.getImage(itemInfo.item, bounds.width - 2 * borderSize, bounds.height - 2 * borderSize);
if (img != null) {
g2d.drawImage(img, null, bounds.x + borderSize, bounds.y + borderSize);
}
else {
g2d.setColor(Color.white);
Shape clip = g2d.getClip();
g2d.setClip(bounds.x, bounds.y, bounds.width, bounds.height);
g2d.drawString(itemInfo.item.getName(), bounds.x + 10, bounds.y + 20);
g2d.setClip(clip);
}
}
}
}
}
}
}

View File

@@ -60,6 +60,7 @@ import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FSkin.SkinBorder; import forge.gui.toolbox.FSkin.SkinBorder;
import forge.gui.toolbox.FSkin.SkinColor; import forge.gui.toolbox.FSkin.SkinColor;
import forge.gui.toolbox.FSkin.SkinFont; import forge.gui.toolbox.FSkin.SkinFont;
import forge.gui.toolbox.FSkin.SkinImage;
import forge.gui.toolbox.FSkin.SkinnedTable; import forge.gui.toolbox.FSkin.SkinnedTable;
import forge.gui.toolbox.FSkin.SkinnedTableHeader; import forge.gui.toolbox.FSkin.SkinnedTableHeader;
import forge.gui.toolbox.itemmanager.ItemManager; import forge.gui.toolbox.itemmanager.ItemManager;
@@ -174,6 +175,11 @@ public final class ItemListView<T extends InventoryItem> extends ItemView<T> {
return this.table.getTableHeader().getLocationOnScreen(); //use table header's location since that stays in place return this.table.getTableHeader().getLocationOnScreen(); //use table header's location since that stays in place
} }
@Override
protected SkinImage getIcon() {
return FSkin.getIcon(FSkin.InterfaceIcons.ICO_LIST);
}
@Override @Override
protected String getCaption() { protected String getCaption() {
return "List View"; return "List View";
@@ -262,6 +268,10 @@ public final class ItemListView<T extends InventoryItem> extends ItemView<T> {
return this.table.rowAtPoint(p); return this.table.rowAtPoint(p);
} }
@Override
protected void onResize() {
}
@Override @Override
protected void onRefresh() { protected void onRefresh() {
this.tableModel.refreshSort(); this.tableModel.refreshSort();
@@ -496,27 +506,17 @@ public final class ItemListView<T extends InventoryItem> extends ItemView<T> {
return -1; return -1;
} }
public void onSelectionChange() {
final int row = getSelectedIndex();
if (row != -1) {
ListSelectionEvent event = new ListSelectionEvent(getItemManager(), row, row, false);
for (ListSelectionListener listener : getItemManager().getSelectionListeners()) {
listener.valueChanged(event);
}
}
}
private final ListSelectionListener listSelectionListener = new ListSelectionListener() { private final ListSelectionListener listSelectionListener = new ListSelectionListener() {
@Override @Override
public void valueChanged(final ListSelectionEvent arg0) { public void valueChanged(final ListSelectionEvent arg0) {
ItemTableModel.this.onSelectionChange(); ItemListView.this.onSelectionChange();
} }
}; };
private final FocusAdapter focusAdapter = new FocusAdapter() { private final FocusAdapter focusAdapter = new FocusAdapter() {
@Override @Override
public void focusGained(final FocusEvent e) { public void focusGained(final FocusEvent e) {
ItemTableModel.this.onSelectionChange(); ItemListView.this.onSelectionChange();
} }
}; };

View File

@@ -24,6 +24,8 @@ import javax.swing.PopupFactory;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.Timer; import javax.swing.Timer;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -31,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.SkinImage;
import forge.gui.toolbox.ToolTipListener; import forge.gui.toolbox.ToolTipListener;
import forge.gui.toolbox.itemmanager.ItemManager; import forge.gui.toolbox.itemmanager.ItemManager;
import forge.item.InventoryItem; import forge.item.InventoryItem;
@@ -38,6 +41,7 @@ import forge.item.InventoryItem;
public abstract class ItemView<T extends InventoryItem> { public abstract class ItemView<T extends InventoryItem> {
private final ItemManager<T> itemManager; private final ItemManager<T> itemManager;
private final FScrollPane scroller; private final FScrollPane scroller;
private final FLabel button;
private int heightBackup; private int heightBackup;
private boolean isIncrementalSearchActive = false; private boolean isIncrementalSearchActive = false;
@@ -45,11 +49,14 @@ public abstract class ItemView<T extends InventoryItem> {
this.itemManager = itemManager0; this.itemManager = itemManager0;
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(FSkin.getColor(FSkin.Colors.CLR_TEXT)));
this.button = new FLabel.Builder().hoverable().selectable(true)
.icon(getIcon()).iconScaleAuto(false)
.tooltip(getCaption()).build();
} }
public void initialize() { public void initialize(final int index) {
final JComponent comp = this.getComponent(); final JComponent comp = this.getComponent();
//hook incremental search functionality //hook incremental search functionality
final IncrementalSearch incrementalSearch = new IncrementalSearch(); final IncrementalSearch incrementalSearch = new IncrementalSearch();
comp.addFocusListener(new FocusAdapter() { comp.addFocusListener(new FocusAdapter() {
@@ -60,11 +67,19 @@ public abstract class ItemView<T extends InventoryItem> {
}); });
comp.addKeyListener(incrementalSearch); comp.addKeyListener(incrementalSearch);
this.button.setCommand(new Runnable() {
@Override
public void run() {
itemManager.setViewIndex(index);
}
});
this.scroller.setViewportView(comp); this.scroller.setViewportView(comp);
this.scroller.getVerticalScrollBar().addAdjustmentListener(new ToolTipListener()); this.scroller.getVerticalScrollBar().addAdjustmentListener(new ToolTipListener());
this.scroller.addComponentListener(new ComponentAdapter() { this.scroller.addComponentListener(new ComponentAdapter() {
@Override @Override
public void componentResized(ComponentEvent e) { public void componentResized(ComponentEvent e) {
onResize();
//scroll selection into view whenever view height changes //scroll selection into view whenever view height changes
int height = e.getComponent().getHeight(); int height = e.getComponent().getHeight();
if (height != heightBackup) { if (height != heightBackup) {
@@ -79,6 +94,10 @@ public abstract class ItemView<T extends InventoryItem> {
return this.itemManager; return this.itemManager;
} }
public FLabel getButton() {
return this.button;
}
public FScrollPane getScroller() { public FScrollPane getScroller() {
return this.scroller; return this.scroller;
} }
@@ -91,6 +110,7 @@ public abstract class ItemView<T extends InventoryItem> {
onRefresh(); onRefresh();
fixSelection(itemsToSelect, backupIndexToSelect); fixSelection(itemsToSelect, backupIndexToSelect);
} }
protected abstract void onResize();
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) {
@@ -115,7 +135,7 @@ public abstract class ItemView<T extends InventoryItem> {
} }
return items; return items;
} }
public final boolean setSelectedItem(T item) { public final boolean setSelectedItem(T item) {
return setSelectedItem(item, true); return setSelectedItem(item, true);
} }
@@ -199,6 +219,16 @@ public abstract class ItemView<T extends InventoryItem> {
} }
} }
protected void onSelectionChange() {
final int index = getSelectedIndex();
if (index != -1) {
ListSelectionEvent event = new ListSelectionEvent(getItemManager(), index, index, false);
for (ListSelectionListener listener : itemManager.getSelectionListeners()) {
listener.valueChanged(event);
}
}
}
public void scrollSelectionIntoView() { public void scrollSelectionIntoView() {
Container parent = getComponent().getParent(); Container parent = getComponent().getParent();
if (parent instanceof JViewport) { if (parent instanceof JViewport) {
@@ -233,6 +263,7 @@ public abstract class ItemView<T extends InventoryItem> {
public abstract int getCount(); public abstract int getCount();
public abstract int getSelectionCount(); public abstract int getSelectionCount();
public abstract int getIndexAtPoint(Point p); public abstract int getIndexAtPoint(Point p);
protected abstract SkinImage getIcon();
protected abstract String getCaption(); protected abstract String getCaption();
protected abstract void onSetSelectedIndex(int index); protected abstract void onSetSelectedIndex(int index);
protected abstract void onSetSelectedIndices(Iterable<Integer> indices); protected abstract void onSetSelectedIndices(Iterable<Integer> indices);

View File

@@ -38,12 +38,12 @@ public class PlayerDetailsPanel extends JPanel {
private Player player; private Player player;
// Info labels // Info labels
private FLabel lblHand = getBuiltFLabel(FSkin.ZoneImages.ICO_HAND, "99", "Cards in hand"); private FLabel lblHand = getBuiltFLabel(FSkin.ZoneImages.IMG_HAND, "99", "Cards in hand");
private FLabel lblGraveyard = getBuiltFLabel(FSkin.ZoneImages.ICO_GRAVEYARD, "99", "Cards in graveyard"); private FLabel lblGraveyard = getBuiltFLabel(FSkin.ZoneImages.IMG_GRAVEYARD, "99", "Cards in graveyard");
private FLabel lblLibrary = getBuiltFLabel(FSkin.ZoneImages.ICO_LIBRARY, "99", "Cards in library"); private FLabel lblLibrary = getBuiltFLabel(FSkin.ZoneImages.IMG_LIBRARY, "99", "Cards in library");
private FLabel lblExile = getBuiltFLabel(FSkin.ZoneImages.ICO_EXILE, "99", "Exiled cards"); private FLabel lblExile = getBuiltFLabel(FSkin.ZoneImages.IMG_EXILE, "99", "Exiled cards");
private FLabel lblFlashback = getBuiltFLabel(FSkin.ZoneImages.ICO_FLASHBACK, "99", "Flashback cards"); private FLabel lblFlashback = getBuiltFLabel(FSkin.ZoneImages.IMG_FLASHBACK, "99", "Flashback cards");
private FLabel lblPoison = getBuiltFLabel(FSkin.ZoneImages.ICO_POISON, "99", "Poison counters"); private FLabel lblPoison = getBuiltFLabel(FSkin.ZoneImages.IMG_POISON, "99", "Poison counters");
private final List<Pair<FLabel, Byte>> manaLabels = new ArrayList<Pair<FLabel,Byte>>(); private final List<Pair<FLabel, Byte>> manaLabels = new ArrayList<Pair<FLabel,Byte>>();
private FLabel getBuiltFLabel(SkinProp p0, String s0, String s1) { private FLabel getBuiltFLabel(SkinProp p0, String s0, String s1) {

View File

@@ -76,11 +76,11 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
private static CardPanel dragAnimationPanel; private static CardPanel dragAnimationPanel;
/** Constant <code>ROUNDED_CORNER_SIZE=0.1f</code>. */ /** Constant <code>ROUNDED_CORNER_SIZE=0.1f</code>. */
private static final float ROUNDED_CORNER_SIZE = 0.1f; public static final float ROUNDED_CORNER_SIZE = 0.1f;
/** Constant <code>SELECTED_BORDER_SIZE=0.01f</code>. */ /** Constant <code>SELECTED_BORDER_SIZE=0.01f</code>. */
private static final float SELECTED_BORDER_SIZE = 0.01f; public static final float SELECTED_BORDER_SIZE = 0.01f;
/** Constant <code>BLACK_BORDER_SIZE=0.03f</code>. */ /** Constant <code>BLACK_BORDER_SIZE=0.03f</code>. */
private static final float BLACK_BORDER_SIZE = 0.03f; public static final float BLACK_BORDER_SIZE = 0.03f;
/** /**
* Constant * Constant