Start breaking off files for CardListView

This commit is contained in:
drdev
2013-08-08 03:17:55 +00:00
parent f32a1455fd
commit 07c38892f9
16 changed files with 2670 additions and 0 deletions

15
.gitattributes vendored
View File

@@ -14794,6 +14794,21 @@ src/main/java/forge/gui/MultiLineLabelUI.java svneol=native#text/plain
src/main/java/forge/gui/SOverlayUtils.java -text
src/main/java/forge/gui/UnsortedListModel.java -text
src/main/java/forge/gui/WrapLayout.java -text
src/main/java/forge/gui/cardlistview/AlwaysShowToolTip.java -text
src/main/java/forge/gui/cardlistview/EditorTableModel.java -text
src/main/java/forge/gui/cardlistview/EditorTableView.java -text
src/main/java/forge/gui/cardlistview/ITableContainer.java -text
src/main/java/forge/gui/cardlistview/IntegerRenderer.java -text
src/main/java/forge/gui/cardlistview/ManaCostRenderer.java -text
src/main/java/forge/gui/cardlistview/SCardListViewIO.java -text
src/main/java/forge/gui/cardlistview/SCardListViewUtil.java -text
src/main/java/forge/gui/cardlistview/SColumnUtil.java -text
src/main/java/forge/gui/cardlistview/SFilterUtil.java -text
src/main/java/forge/gui/cardlistview/SetCodeRenderer.java -text
src/main/java/forge/gui/cardlistview/TableColumnInfo.java -text
src/main/java/forge/gui/cardlistview/TableSorter.java -text
src/main/java/forge/gui/cardlistview/TableSorterCascade.java -text
src/main/java/forge/gui/cardlistview/package-info.java -text
src/main/java/forge/gui/deckeditor/CDeckEditorUI.java -text
src/main/java/forge/gui/deckeditor/DeckImport.java -text
src/main/java/forge/gui/deckeditor/SEditorIO.java -text

View File

@@ -0,0 +1,25 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
/**
* A marker interface for indicating that tooltips should always be shown for
* cells rendered with the marked renderer.
*/
interface AlwaysShowToolTip {
}

View File

@@ -0,0 +1,401 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011
import forge.gui.deckeditor.views.VDeckEditorUI;
Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.awt.Cursor;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Map.Entry;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import org.apache.commons.lang3.ArrayUtils;
import forge.gui.cardlistview.SColumnUtil.ColumnName;
import forge.gui.cardlistview.SColumnUtil.SortState;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.item.InventoryItem;
import forge.item.ItemPool;
import forge.item.ItemPoolView;
/**
* <p>
* EditorTableModel class.
* </p>
*
* @param <T>
* the generic type
* @author Forge
* @version $Id: EditorTableModel.java 19857 2013-02-24 08:49:52Z Max mtg $
*/
@SuppressWarnings("serial")
public final class EditorTableModel<T extends InventoryItem> extends AbstractTableModel {
private final ItemPool<T> data;
private final JTable table;
private final CascadeManager cascadeManager = new CascadeManager();
private final int maxSortDepth = 3;
private boolean infiniteSupply;
/**
* Instantiates a new table model, using a JTable,
* a column set, and a data set of generic type <T>.
*
* @param table0 &emsp; {@link javax.swing.JTable}
* @param class0 &emsp; Generic type <T>
*/
public EditorTableModel(final JTable table0, final Class<T> class0) {
this.table = table0;
this.data = new ItemPool<T>(class0);
}
/** */
@SuppressWarnings("unchecked")
public void setup() {
final Enumeration<TableColumn> e = table.getColumnModel().getColumns();
final TableColumn[] sortcols = new TableColumn[table.getColumnCount()];
// Assemble priority sort.
while (e.hasMoreElements()) {
final TableColumnInfo<InventoryItem> col = (TableColumnInfo<InventoryItem>) e.nextElement();
if (col.getSortPriority() > 0) {
sortcols[col.getSortPriority()] = col;
}
}
final boolean isDeckTable = ((TableColumnInfo<InventoryItem>) table.getColumnModel()
.getColumn(0)).getEnumValue().substring(0, 4).equals("DECK")
? true : false;
if (sortcols[1] == null) {
if (isDeckTable) {
cascadeManager.add((TableColumnInfo<T>) SColumnUtil.getColumn(ColumnName.DECK_NAME));
}
else {
cascadeManager.add((TableColumnInfo<T>) SColumnUtil.getColumn(ColumnName.CAT_NAME));
}
}
else {
ArrayUtils.reverse(sortcols);
for (int i = 1; i < sortcols.length; i++) {
if (sortcols[i] != null) {
cascadeManager.add((TableColumnInfo<T>) sortcols[i]);
}
}
}
}
/**
* Clears all data in the model.
*/
public void clear() {
this.data.clear();
}
/**
* Gets all cards in the model.
*
* @return the cards
*/
public ItemPoolView<T> getCards() {
return this.data.getView();
}
/**
* Removes a card from the model.
*
* @param card0 &emsp; {@link forge.Card} object
*/
public void removeCard(final T card0, int qty) {
if ( isInfinite() )
return;
final boolean wasThere = this.data.count(card0) > 0;
if (wasThere) {
this.data.remove(card0, qty);
this.fireTableDataChanged();
}
}
/**
* Adds a card to the model.
*
* @param card0 &emsp; {@link forge.Card} object.
*/
public void addCard(final T card0, int qty) {
this.data.add(card0, qty);
this.fireTableDataChanged();
}
/**
* Adds multiple copies of multiple cards to the model.
*
* @param cards0 &emsp; {@link java.lang.Iterable}<Entry<T, Integer>>
*/
public void addCards(final Iterable<Entry<T, Integer>> cards0) {
this.data.addAll(cards0);
this.fireTableDataChanged();
}
/**
* Row to card.
*
* @param row
* the row
* @return the entry
*/
public Entry<T, Integer> rowToCard(final int row) {
final List<Entry<T, Integer>> model = this.data.getOrderedList();
return (row >= 0) && (row < model.size()) ? model.get(row) : null;
}
/**
* Show selected card.
*
* @param table
* the table
*/
public void showSelectedCard(final JTable table) {
final int row = table.getSelectedRow();
if (row != -1) {
Entry<T, Integer> card = this.rowToCard(row);
CDeckEditorUI.SINGLETON_INSTANCE.setCard(null != card ? card.getKey() : null);
}
}
/**
* <p>
* addListeners.
* </p>
*/
public void addListeners() {
// updates card detail, listens to any key strokes
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(final ListSelectionEvent arg0) {
if (table.isFocusOwner()) {
EditorTableModel.this.showSelectedCard(table);
}
}
});
table.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(final FocusEvent e) {
EditorTableModel.this.showSelectedCard(table);
}
});
final JTableHeader header = table.getTableHeader();
header.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
if (Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR) != header.getCursor()) {
headerClicked(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
SCardListViewIO.savePreferences();
}
});
} // addCardListener()
/**
* Resort.
*/
public void refreshSort() {
if (this.data.getOrderedList().size() == 0) { return; }
Collections.sort(this.data.getOrderedList(), new MyComparator());
}
@SuppressWarnings("unchecked")
private void headerClicked(final MouseEvent e) {
final TableColumnModel colModel = EditorTableModel.this.table.getColumnModel();
final int columnModelIndex = colModel.getColumnIndexAtX(e.getX());
final int modelIndex = colModel.getColumn(columnModelIndex).getModelIndex();
if (modelIndex < 0) {
return;
}
// This will invert if needed
// 2012/07/21 - Changed from modelIndex to ColumnModelIndex due to a crash
// Crash was: Hide 2 columns, then search by last column.
EditorTableModel.this.cascadeManager.add((TableColumnInfo<T>) this.table.getColumnModel().getColumn(columnModelIndex));
EditorTableModel.this.refreshSort();
EditorTableModel.this.table.tableChanged(new TableModelEvent(EditorTableModel.this));
EditorTableModel.this.table.repaint();
if (EditorTableModel.this.table.getRowCount() > 0) {
EditorTableModel.this.table.setRowSelectionInterval(0, 0);
}
SCardListViewIO.savePreferences();
}
//========== Overridden from AbstractTableModel
/** {@inheritDoc} */
@Override
public int findColumn(final String name0) {
return table.getColumnModel().getColumnIndex(name0);
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getColumnCount()
*/
@Override
public int getColumnCount() {
return table.getColumnCount();
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getRowCount()
*/
@Override
public int getRowCount() {
return this.data.countDistinct();
}
/* (non-Javadoc)
* @see javax.swing.table.TableModel#getValueAt(int, int)
*/
@Override
@SuppressWarnings("unchecked")
public Object getValueAt(int iRow, int iCol) {
Entry<T, Integer> card = this.rowToCard(iRow);
if (null == card) {
return null;
}
return ((TableColumnInfo<T>) table.getColumnModel().getColumn(table.convertColumnIndexToView(iCol))).getFnDisplay().apply(card);
}
//========= Custom class handling
/**
* Manages sorting orders for multiple depths of sorting.
*/
private final class CascadeManager {
private final List<TableColumnInfo<InventoryItem>> colsToSort = new ArrayList<TableColumnInfo<InventoryItem>>(3);
private TableSorterCascade<InventoryItem> sorter = null;
// Adds a column to sort cascade list.
// If column is first in the cascade, inverts direction of sort.
// Otherwise, sorts in ascending direction.
@SuppressWarnings("unchecked")
public void add(final TableColumnInfo<T> col0) {
this.sorter = null;
// Found at top level, should invert
if (colsToSort.size() > 0 && colsToSort.get(0).equals(col0)) {
this.colsToSort.get(0).setSortState(
this.colsToSort.get(0).getSortState() == SortState.ASC
? SortState.DESC : SortState.ASC);
this.colsToSort.get(0).setSortPriority(1);
}
// Found somewhere: move down others, this one to top.
else if (colsToSort.contains(col0)) {
col0.setSortState(SortState.ASC);
this.colsToSort.remove(col0);
this.colsToSort.add(0, (TableColumnInfo<InventoryItem>) col0);
}
// No column in list; add directly.
else {
col0.setSortState(SortState.ASC);
this.colsToSort.add(0, (TableColumnInfo<InventoryItem>) col0);
this.colsToSort.get(0).setSortPriority(1);
}
// Decrement sort priority on remaining columns
for (int i = 1; i < maxSortDepth; i++) {
if (colsToSort.size() == i) { break; }
if (colsToSort.get(i).getSortPriority() != 0) {
colsToSort.get(i).setSortPriority(i + 1);
}
}
// Unset and remove boundary columns.
if (this.colsToSort.size() > maxSortDepth) {
this.colsToSort.get(maxSortDepth).setSortState(SortState.NONE);
this.colsToSort.get(maxSortDepth).setSortPriority(0);
this.colsToSort.remove(maxSortDepth);
}
}
public TableSorterCascade<InventoryItem> getSorter() {
if (this.sorter == null) {
this.sorter = createSorter();
}
return this.sorter;
}
private TableSorterCascade<InventoryItem> createSorter() {
final List<TableSorter<InventoryItem>> oneColSorters
= new ArrayList<TableSorter<InventoryItem>>(maxSortDepth);
for (final TableColumnInfo<InventoryItem> col : this.colsToSort) {
oneColSorters.add(new TableSorter<InventoryItem>(
col.getFnSort(),
col.getSortState().equals(SortState.ASC) ? true : false));
}
return new TableSorterCascade<InventoryItem>(oneColSorters);
}
}
private class MyComparator implements Comparator<Entry<T, Integer>> {
/* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public int compare(Entry<T, Integer> o1, Entry<T, Integer> o2) {
return EditorTableModel.this.cascadeManager.getSorter().compare(
(Entry<InventoryItem, Integer>) o1, (Entry<InventoryItem, Integer>) o2);
}
}
/**
* Sets whether this table's pool of cards is in infinite supply. If false, cards in the
* table have a limited number of copies.
*/
public void setInfinite(boolean infinite) {
this.infiniteSupply = infinite;
}
public boolean isInfinite() {
return infiniteSupply;
}
} // CardTableModel

View File

@@ -0,0 +1,576 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.awt.Color;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import forge.gui.deckeditor.SEditorUtil;
import forge.gui.deckeditor.views.ITableContainer;
import forge.gui.toolbox.FSkin;
import forge.item.InventoryItem;
import forge.item.ItemPool;
import forge.item.ItemPoolView;
import forge.util.Aggregates;
/**
* TableWithCards.
*
* @param <T>
* the generic type
*/
public final class EditorTableView<T extends InventoryItem> {
private ItemPool<T> pool;
private EditorTableModel<T> model;
private final JTable table;
private Predicate<T> filter = null;
private boolean wantUnique = false;
private boolean alwaysNonUnique = false;
private final Class<T> genericType;
/**
*
* getTable.
*
* @return JTable
*/
public JTable getTable() {
return this.table;
}
/**
* TableWithCards.
*
* @param type0 the class of item that this table will contain
*/
public EditorTableView(final Class<T> type0) {
this(false, type0);
}
/**
* TableWithCards Constructor.
*
* @param forceUnique whether this table should display only one item with the same name
* @param type0 the class of item that this table will contain
*/
@SuppressWarnings("serial")
public EditorTableView(final boolean forceUnique, final Class<T> type0) {
this.genericType = type0;
this.wantUnique = forceUnique;
// subclass JTable to show tooltips when hovering over column headers
// and cell data that are truncated due to too-small column widths
table = new JTable() {
private String _getCellTooltip(
TableCellRenderer renderer, int row, int col, Object val) {
Component cell = renderer.getTableCellRendererComponent(
table, val, false, false, row, col);
// if we're conditionally showing the tooltip, check to see
// if we shouldn't show it
if (!(cell instanceof AlwaysShowToolTip))
{
// if there's enough room (or there's no value), no tooltip
// we use '>' here instead of '>=' since that seems to be the
// threshold for where the ellipses appear for the default
// JTable renderer
int requiredWidth = cell.getPreferredSize().width;
TableColumn tableColumn = columnModel.getColumn(col);
if (null == val || tableColumn.getWidth() > requiredWidth) {
return null;
}
}
// use a pre-set tooltip if it exists
if (cell instanceof JComponent)
{
JComponent jcell = (JComponent)cell;
String tip = jcell.getToolTipText();
if (null != tip)
{
return tip;
}
}
// otherwise, show the full text in the tooltip
return String.valueOf(val);
}
// column headers
@Override
protected JTableHeader createDefaultTableHeader() {
return new JTableHeader(columnModel) {
public String getToolTipText(MouseEvent e) {
int col = columnModel.getColumnIndexAtX(e.getPoint().x);
TableColumn tableColumn = columnModel.getColumn(col);
TableCellRenderer headerRenderer = tableColumn.getHeaderRenderer();
if (null == headerRenderer) {
headerRenderer = getDefaultRenderer();
}
return _getCellTooltip(
headerRenderer, -1, col, tableColumn.getHeaderValue());
}
};
}
// cell data
@Override
public String getToolTipText(MouseEvent e) {
Point p = e.getPoint();
int row = rowAtPoint(p);
int col = columnAtPoint(p);
if (col >= table.getColumnCount() || row >= table.getRowCount()) {
return null;
}
Object val = table.getValueAt(row, col);
if (null == val) {
return null;
}
return _getCellTooltip(getCellRenderer(row, col), row, col, val);
}
private int lastTooltipRow = -1;
private int lastTooltipCol = -1;
private Point lastTooltipPt;
@Override
public Point getToolTipLocation(MouseEvent e) {
Point p = e.getPoint();
final int row = rowAtPoint(p);
final int col = columnAtPoint(p);
if (row == lastTooltipRow && col == lastTooltipCol) {
p = lastTooltipPt;
} else {
lastTooltipRow = row;
lastTooltipCol = col;
lastTooltipPt = p;
}
return new Point(p.x + 10, p.y + 20);
}
};
// use different selection highlight colors for focused vs. unfocused tables
table.setSelectionBackground(FSkin.getColor(FSkin.Colors.CLR_INACTIVE));
table.setSelectionForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
table.addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
if (!e.isTemporary()) {
table.setSelectionBackground(FSkin.getColor(FSkin.Colors.CLR_INACTIVE));
}
}
@Override
public void focusGained(FocusEvent e) {
table.setSelectionBackground(FSkin.getColor(FSkin.Colors.CLR_ACTIVE));
// if nothing selected when we gain focus, select the first row (if exists)
if (-1 == table.getSelectedRow() && 0 < table.getRowCount()) {
table.setRowSelectionInterval(0, 0);
}
}
});
table.setFont(FSkin.getFont(12));
table.setBorder(null);
table.getTableHeader().setBorder(null);
table.setRowHeight(18);
table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
// prevent tables from intercepting tab focus traversals
table.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
table.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
}
/**
* Applies a EditorTableModel and a model listener to this instance's JTable.
*
* @param view0 &emsp; the {@link javax.gui.deckeditor.views.ITableCOntainer}
* @param cols0 &emsp; List<TableColumnInfo<InventoryItem>> of additional columns for this
*/
public void setup(final ITableContainer view0, final List<TableColumnInfo<InventoryItem>> cols0) {
final DefaultTableColumnModel colmodel = new DefaultTableColumnModel();
for (TableColumnInfo<InventoryItem> item : cols0) {
item.setModelIndex(colmodel.getColumnCount());
if (item.isShowing()) { colmodel.addColumn(item); }
}
this.model = new EditorTableModel<T>(this.table, this.genericType);
this.model.addListeners();
this.table.setModel(this.model);
this.table.setColumnModel(colmodel);
this.model.setup();
this.model.refreshSort();
this.table.getTableHeader().setBackground(new Color(200, 200, 200));
// Update stats each time table changes
this.model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(final TableModelEvent ev) {
SEditorUtil.setStats(EditorTableView.this.model.getCards(), view0);
}
});
}
public void setAvailableColumns(final List<TableColumnInfo<InventoryItem>> cols0) {
final DefaultTableColumnModel colmodel = new DefaultTableColumnModel();
for (TableColumnInfo<InventoryItem> item : cols0) {
item.setModelIndex(colmodel.getColumnCount());
if (item.isShowing()) { colmodel.addColumn(item); }
}
this.table.setColumnModel(colmodel);
}
/**
*
* fixSelection. Call this after deleting an item from table.
*
* @param rowLastSelected
* an int
*/
public void fixSelection(final int rowLastSelected) {
if (0 > rowLastSelected) {
return;
}
// 3 cases: 0 cards left, select the same row, select prev row
int numRows = model.getRowCount();
if (numRows == 0) {
return;
}
int newRow = rowLastSelected;
if (numRows <= newRow) {
// move selection away from the last, already missing, option
newRow = numRows - 1;
}
selectAndScrollTo(newRow);
}
/**
*
* setDeck.
*
* @param cards
* an Iterable<InventoryITem>
*/
public void setDeck(final Iterable<InventoryItem> cards) {
this.setDeckImpl(ItemPool.createFrom(cards, this.genericType), false);
}
/**
* setDeck.
*
* @param poolView
* an ItemPoolView
*/
public void setDeck(final ItemPoolView<T> poolView, boolean infinite) {
this.setDeckImpl(ItemPool.createFrom(poolView, this.genericType), infinite);
}
public void setDeck(final ItemPoolView<T> poolView) {
this.setDeck(poolView, false);
}
/**
* Sets the deck.
*
* @param pool
* the new deck
*/
public void setDeck(final ItemPool<T> pool) {
this.setDeckImpl(pool, false);
}
/**
*
* setDeckImpl.
*
* @param thePool
* an ItemPool
*/
protected void setDeckImpl(final ItemPool<T> thePool, boolean infinite) {
this.model.clear();
this.pool = thePool;
this.model.addCards(this.pool);
this.model.setInfinite(infinite);
this.updateView(true);
}
/**
*
* getSelectedCard.
*
* @return InventoryItem
*/
public InventoryItem getSelectedCard() {
final int iRow = this.table.getSelectedRow();
return iRow >= 0 ? this.model.rowToCard(iRow).getKey() : null;
}
/**
* returns all selected cards
*/
public List<InventoryItem> getSelectedCards() {
List<InventoryItem> items = new ArrayList<InventoryItem>();
for (int row : table.getSelectedRows()) {
items.add(model.rowToCard(row).getKey());
}
return items;
}
private boolean isUnfiltered() {
return this.filter == null;
}
/**
*
* setFilter.
*
* @param filterToSet
* a Predicate
*/
public void setFilter(final Predicate<T> filterToSet) {
this.filter = filterToSet;
if (null != pool) {
this.updateView(true);
}
}
/**
*
* addCard.
*
* @param card
* an InventoryItem
*/
public void addCard(final T card, int qty) {
final int n = this.table.getSelectedRow();
this.pool.add(card, qty);
if (this.isUnfiltered()) {
this.model.addCard(card, qty);
}
this.updateView(false);
this.fixSelection(n);
}
public void addCards(Iterable<Map.Entry<T, Integer>> cardsToAdd) {
final int n = this.table.getSelectedRow();
for (Map.Entry<T, Integer> item : cardsToAdd) {
this.pool.add(item.getKey(), item.getValue());
if (this.isUnfiltered()) {
this.model.addCard(item.getKey(), item.getValue());
}
}
this.updateView(false);
this.fixSelection(n);
}
public void addCards(Collection<T> cardsToAdd) {
final int n = this.table.getSelectedRow();
for (T item : cardsToAdd) {
this.pool.add(item, 1);
if (this.isUnfiltered()) {
this.model.addCard(item, 1);
}
}
this.updateView(false);
this.fixSelection(n);
}
/**
*
* removeCard.
*
* @param card
* an InventoryItem
*/
public void removeCard(final T card, int qty) {
final int n = this.table.getSelectedRow();
this.pool.remove(card, qty);
if (this.isUnfiltered()) {
this.model.removeCard(card, qty);
}
this.updateView(false);
this.fixSelection(n);
}
public void removeCards(List<Map.Entry<T, Integer>> cardsToRemove) {
final int n = this.table.getSelectedRow();
for (Map.Entry<T, Integer> item : cardsToRemove) {
this.pool.remove(item.getKey(), item.getValue());
if (this.isUnfiltered()) {
this.model.removeCard(item.getKey(), item.getValue());
}
}
this.updateView(false);
this.fixSelection(n);
}
public int getCardCount(final T card) {
return model.isInfinite() ? Integer.MAX_VALUE : this.pool.count(card);
}
public Predicate<T> getFilter() {
return filter;
}
/**
*
* updateView.
*
* @param bForceFilter
* a boolean
*/
public void updateView(final boolean bForceFilter) {
final boolean useFilter = (bForceFilter && (this.filter != null)) || !isUnfiltered();
if (useFilter || this.wantUnique || bForceFilter) {
this.model.clear();
}
if (useFilter && this.wantUnique) {
Predicate<Entry<T, Integer>> filterForPool = Predicates.compose(this.filter, this.pool.FN_GET_KEY);
Iterable<Entry<T, Integer>> cards = Aggregates.uniqueByLast(Iterables.filter(this.pool, filterForPool), this.pool.FN_GET_NAME);
this.model.addCards(cards);
} else if (useFilter) {
Predicate<Entry<T, Integer>> pred = Predicates.compose(this.filter, this.pool.FN_GET_KEY);
this.model.addCards(Iterables.filter(this.pool, pred));
} else if (this.wantUnique) {
Iterable<Entry<T, Integer>> cards = Aggregates.uniqueByLast(this.pool, this.pool.FN_GET_NAME);
this.model.addCards(cards);
} else if (!useFilter && bForceFilter) {
this.model.addCards(this.pool);
}
this.model.refreshSort();
}
/**
*
* getCards.
*
* @return ItemPoolView
*/
public ItemPoolView<T> getCards() {
return this.pool;
}
/**
*
* getWantUnique.
*
* @return true if the editor is in "unique card names only" mode.
*/
public boolean getWantUnique() {
return this.wantUnique;
}
/**
*
* setWantUnique.
*
* @param unique if true, the editor will be set to the "unique card names only" mode.
*/
public void setWantUnique(boolean unique) {
this.wantUnique = this.alwaysNonUnique ? false : unique;
}
/**
*
* getAlwaysNonUnique.
*
* @return if ture, this editor must always show non-unique cards (e.g. quest editor).
*/
public boolean getAlwaysNonUnique() {
return this.alwaysNonUnique;
}
/**
*
* setAlwaysNonUnique.
*
* @param nonUniqueOnly if true, this editor must always show non-unique cards (e.g. quest editor).
*/
public void setAlwaysNonUnique(boolean nonUniqueOnly) {
this.alwaysNonUnique = nonUniqueOnly;
}
public void setWantElasticColumns(boolean value) {
table.setAutoResizeMode(value ? JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS : JTable.AUTO_RESIZE_NEXT_COLUMN);
}
public void selectAndScrollTo(int rowIdx) {
if (!(table.getParent() instanceof JViewport)) {
return;
}
JViewport viewport = (JViewport)table.getParent();
// compute where we're going and where we are
Rectangle targetRect = table.getCellRect(rowIdx, 0, true);
Rectangle curViewRect = viewport.getViewRect();
// if the target cell is not visible, attempt to jump to a location where it is
// visible but not on the edge of the viewport
if (targetRect.y + targetRect.height > curViewRect.y + curViewRect.height) {
// target is below us, move to position 3 rows below target
targetRect.setLocation(targetRect.x, targetRect.y + (targetRect.height * 3));
} else if (targetRect.y < curViewRect.y) {
// target is above is, move to position 3 rows above target
targetRect.setLocation(targetRect.x, targetRect.y - (targetRect.height * 3));
}
table.scrollRectToVisible(targetRect);
table.setRowSelectionInterval(rowIdx, rowIdx);
}
}

View File

@@ -0,0 +1,25 @@
package forge.gui.cardlistview;
import javax.swing.JTable;
import forge.gui.deckeditor.SEditorUtil;
import forge.gui.toolbox.FLabel;
/**
* Dictates methods needed for a class to act as a container for
* a EditorTableView deck editing component.
*
* <br><br><i>(I at beginning of class name denotes an interface.)</i>
*
*/
public interface ITableContainer {
/**
* Sets the table used for displaying cards in this
* deck editor container.
*
* @param tbl0 &emsp; {@link forge.gui.deckeditor.tables.EditorTableView}
*/
void setTableView(JTable tbl0);
FLabel getStatLabel(SCardListViewUtil.StatTypes s);
}

View File

@@ -0,0 +1,44 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
/**
* A quick converter to avoid -1 being displayed for unapplicable values.
*/
@SuppressWarnings("serial")
public class IntegerRenderer extends DefaultTableCellRenderer {
/*
* (non-Javadoc)
*
* @see
* javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent
* (javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
*/
@Override
public final Component getTableCellRendererComponent(final JTable table, Object value0,
final boolean isSelected, final boolean hasFocus, final int row, final int column) {
if ((Integer) value0 == -1) { value0 = "-"; }
return super.getTableCellRendererComponent(table, value0, isSelected, hasFocus, row, column);
}
}

View File

@@ -0,0 +1,135 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.awt.Component;
import java.awt.Graphics;
import java.util.List;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.gui.toolbox.CardFaceSymbols;
/**
* Displays mana cost as symbols.
*/
public class ManaCostRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1770527102334163549L;
static final int elemtWidth = 13;
static final int elemtGap = 0;
static final int padding0 = 1;
static final int spaceBetweenSplitCosts = 3;
private ManaCost v1;
private ManaCost v2;
/*
* (non-Javadoc)
*
* @see
* javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent
* (javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
*/
@Override
public final Component getTableCellRendererComponent(final JTable table, final Object value,
final boolean isSelected, final boolean hasFocus, final int row, final int column) {
CardRules v = value instanceof CardRules ? (CardRules) value : null;
this.v1 = v == null ? ManaCost.NO_COST : v.getMainPart().getManaCost();
this.v2 = v == null || v.getSplitType() != CardSplitType.Split ? null : v.getOtherPart().getManaCost();
this.setToolTipText(v2 == null ? v1.toString() : v1.toString() + " / " + v2.toString());
return super.getTableCellRendererComponent(table, "", isSelected, hasFocus, row, column);
}
/*
* (non-Javadoc)
*
* @see javax.swing.JComponent#paint(java.awt.Graphics)
*/
@Override
public final void paint(final Graphics g) {
super.paint(g);
final int cellWidth = this.getWidth();
if ( null == v2 )
drawCost(g, v1, padding0, cellWidth);
else
{
int shards1 = v1.isPureGeneric() || v1.getGenericCost() > 0 ? 1 : 0;
int shards2 = v2.isPureGeneric() || v2.getGenericCost() > 0 ? 1 : 0;
shards1 += v1.getShards().size();
shards2 += v2.getShards().size();
int perGlyph = (cellWidth - padding0 - spaceBetweenSplitCosts) / (shards1 + shards2);
perGlyph = Math.min(perGlyph, elemtWidth + elemtGap);
drawCost(g, v1, padding0, padding0 + perGlyph * shards1);
drawCost(g, v2, cellWidth - perGlyph * shards2, cellWidth );
}
}
/**
* TODO: Write javadoc for this method.
* @param g
* @param padding
* @param cellWidth
*/
private void drawCost(final Graphics g, ManaCost value, final int padding, final int cellWidth) {
float xpos = padding;
final int genericManaCost = value.getGenericCost();
final int xManaCosts = value.countX();
final boolean hasGeneric = (genericManaCost > 0) || this.v1.isPureGeneric();
final List<ManaCostShard> shards = value.getShards();
final int cntGlyphs = hasGeneric ? shards.size() + 1 : shards.size();
final float offsetIfNoSpace = cntGlyphs > 1 ? (cellWidth - padding - elemtWidth) / (cntGlyphs - 1f)
: elemtWidth + elemtGap;
final float offset = Math.min(elemtWidth + elemtGap, offsetIfNoSpace);
// Display X Mana before any other type of mana
if (xManaCosts > 0) {
for (int i = 0; i < xManaCosts; i++) {
CardFaceSymbols.drawSymbol(ManaCostShard.X.getImageKey(), g, (int) xpos, 1);
xpos += offset;
}
}
// Display colorless mana before colored mana
if (hasGeneric) {
final String sGeneric = Integer.toString(genericManaCost);
CardFaceSymbols.drawSymbol(sGeneric, g, (int) xpos, 1);
xpos += offset;
}
for (final ManaCostShard s : shards) {
if (s.equals(ManaCostShard.X)) {
// X costs already drawn up above
continue;
}
CardFaceSymbols.drawSymbol(s.getImageKey(), g, (int) xpos, 1);
xpos += offset;
}
}
}

View File

@@ -0,0 +1,239 @@
package forge.gui.cardlistview;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import forge.gui.cardlistview.SColumnUtil.ColumnName;
import forge.item.InventoryItem;
import forge.properties.NewConstants;
/**
* Handles editor preferences saving and loading.
*
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
*/
public class SCardListViewIO {
/** Used in the XML IO to extract properties from PREFS file. */
private enum ColumnProperty { /** */
enumval, /** */
identifier, /** */
show, /** */
sortpriority, /** */
sortstate, /** */
width
}
/** Preferences (must match with PREFS file). */
public enum EditorPreference {
stats_deck,
display_unique_only,
elastic_columns
}
private static final XMLEventFactory EVENT_FACTORY = XMLEventFactory.newInstance();
private static final XMLEvent NEWLINE = EVENT_FACTORY.createDTD("\n");
private static final XMLEvent TAB = EVENT_FACTORY.createDTD("\t");
private static final Map<EditorPreference, Boolean> PREFS
= new HashMap<EditorPreference, Boolean>();
private static final Map<ColumnName, TableColumnInfo<InventoryItem>> COLS
= new TreeMap<ColumnName, TableColumnInfo<InventoryItem>>();
/**
* Retrieve a preference from the editor preference map.
*
* @param name0 &emsp; {@link forge.gui.deckeditor.SCardListViewUtil.EditorPreference}
* @return TableColumnInfo<InventoryItem>
*/
public static boolean getPref(final EditorPreference name0) {
return PREFS.get(name0);
}
/**
* Set a preference in the editor preference map.
*
* @param name0 &emsp; {@link forge.gui.deckeditor.SCardListViewUtil.EditorPreference}
* @param val0 &emsp; boolean
*/
public static void setPref(final EditorPreference name0, final boolean val0) {
PREFS.put(name0, val0);
}
/**
* Retrieve a custom column.
*
* @param name0 &emsp; {@link forge.gui.deckeditor.SCardListViewUtil.CatalogColumnName}
* @return TableColumnInfo<InventoryItem>
*/
public static TableColumnInfo<InventoryItem> getColumn(final ColumnName name0) {
return COLS.get(name0);
}
/** Publicly-accessible save method, to neatly handle exception handling. */
public static void savePreferences() {
try { save(); }
catch (final Exception e) { e.printStackTrace(); }
}
/** Publicly-accessible load method, to neatly handle exception handling. */
public static void loadPreferences() {
try { load(); }
catch (final Exception e) { e.printStackTrace(); }
}
/**
*
* TODO: Write javadoc for this method.
*
* @param <TItem> extends InventoryItem
* @param <TModel> extends DeckBase
*/
private static void save() throws Exception {
final XMLOutputFactory out = XMLOutputFactory.newInstance();
final XMLEventWriter writer = out.createXMLEventWriter(new FileOutputStream(NewConstants.EDITOR_PREFERENCES_FILE.userPrefLoc));
writer.add(EVENT_FACTORY.createStartDocument());
writer.add(NEWLINE);
writer.add(EVENT_FACTORY.createStartElement("", "", "preferences"));
writer.add(EVENT_FACTORY.createAttribute("type", "editor"));
writer.add(NEWLINE);
for (final EditorPreference p : PREFS.keySet()) {
writer.add(TAB);
writer.add(EVENT_FACTORY.createStartElement("", "", "pref"));
writer.add(EVENT_FACTORY.createAttribute(
"name", p.toString()));
writer.add(EVENT_FACTORY.createAttribute(
"value", PREFS.get(p).toString()));
writer.add(EVENT_FACTORY.createEndElement("", "", "pref"));
writer.add(NEWLINE);
}
for (final ColumnName c : COLS.keySet()) {
// If column is not in view, retain previous model index for the next time
// that the column will be in the view.
int index = SColumnUtil.getColumnViewIndex(c);
if (index == -1) {
index = COLS.get(c).getModelIndex();
}
writer.add(TAB);
writer.add(EVENT_FACTORY.createStartElement("", "", "col"));
writer.add(EVENT_FACTORY.createAttribute(
ColumnProperty.enumval.toString(), COLS.get(c).getEnumValue()));
writer.add(EVENT_FACTORY.createAttribute(
ColumnProperty.identifier.toString(), COLS.get(c).getIdentifier().toString()));
writer.add(EVENT_FACTORY.createAttribute(
ColumnProperty.show.toString(), String.valueOf(COLS.get(c).isShowing())));
writer.add(EVENT_FACTORY.createAttribute(
ColumnProperty.sortpriority.toString(), String.valueOf(COLS.get(c).getSortPriority())));
writer.add(EVENT_FACTORY.createAttribute(
ColumnProperty.sortstate.toString(), String.valueOf(COLS.get(c).getSortState())));
writer.add(EVENT_FACTORY.createAttribute(
ColumnProperty.width.toString(), String.valueOf(COLS.get(c).getWidth())));
writer.add(EVENT_FACTORY.createEndElement("", "", "col"));
writer.add(NEWLINE);
}
writer.add(EVENT_FACTORY.createEndDocument());
writer.flush();
writer.close();
}
private static void load() throws Exception {
final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
PREFS.clear();
COLS.clear();
// read in defaults
loadPrefs(inputFactory.createXMLEventReader(new FileInputStream(NewConstants.EDITOR_PREFERENCES_FILE.defaultLoc)));
try {
// overwrite defaults with user preferences, if they exist
loadPrefs(inputFactory.createXMLEventReader(new FileInputStream(NewConstants.EDITOR_PREFERENCES_FILE.userPrefLoc)));
} catch (FileNotFoundException e) {
/* ignore; it's ok if this file doesn't exist */
} finally {
SColumnUtil.attachSortAndDisplayFunctions();
}
}
private static void loadPrefs(final XMLEventReader reader) throws XMLStreamException {
XMLEvent event;
StartElement element;
Iterator<?> attributes;
Attribute attribute;
EditorPreference pref;
TableColumnInfo<InventoryItem> tempcol;
String tagname;
while (reader.hasNext()) {
event = reader.nextEvent();
if (event.isStartElement()) {
element = event.asStartElement();
tagname = element.getName().getLocalPart();
// Assemble preferences
if (tagname.equals("pref")) {
// Retrieve name of pref
attributes = element.getAttributes();
try {
pref = EditorPreference.valueOf(((Attribute) attributes.next()).getValue());
// Add to map
PREFS.put(pref, Boolean.valueOf(((Attribute) attributes.next()).getValue()));
} catch (IllegalArgumentException e) { /* ignore; just don't use */ }
}
// Assemble columns
else if (tagname.equals("col")) {
attributes = element.getAttributes();
tempcol = new TableColumnInfo<InventoryItem>();
while (attributes.hasNext()) {
attribute = (Attribute) attributes.next();
if (attribute.getName().toString().equals(ColumnProperty.enumval.toString())) {
try { COLS.put(ColumnName.valueOf(attribute.getValue()), tempcol); }
catch (final Exception e) { /* ignore invalid entries */ }
tempcol.setEnumValue(attribute.getValue());
}
else if (attribute.getName().toString().equals(ColumnProperty.identifier.toString())) {
tempcol.setIdentifier(attribute.getValue());
tempcol.setHeaderValue(attribute.getValue());
}
else if (attribute.getName().toString().equals(ColumnProperty.width.toString())) {
tempcol.setPreferredWidth(Integer.valueOf(attribute.getValue()));
}
else if (attribute.getName().toString().equals(ColumnProperty.show.toString())) {
tempcol.setShowing(Boolean.valueOf(attribute.getValue()));
}
else if (attribute.getName().toString().equals(ColumnProperty.sortpriority.toString())) {
tempcol.setSortPriority(Integer.valueOf(attribute.getValue()));
}
else if (attribute.getName().toString().equals(ColumnProperty.sortstate.toString())) {
tempcol.setSortState(SortState.valueOf(attribute.getValue().toString()));
}
}
}
}
}
}
}

View File

@@ -0,0 +1,135 @@
package forge.gui.cardlistview;
import javax.swing.ImageIcon;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.toolbox.FSkin;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.item.ItemPoolView;
import forge.util.Aggregates;
import forge.util.TextUtil;
/**
* Static methods for working with top-level editor methods,
* included but not limited to preferences IO, icon generation,
* and stats analysis.
*
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*
*/
public final class SCardListViewUtil {
/** An enum to encapsulate metadata for the stats/filter objects. */
public static enum StatTypes {
TOTAL (FSkin.ZoneImages.ICO_HAND, null, 0),
WHITE (FSkin.ManaImages.IMG_WHITE, CardRulesPredicates.Presets.IS_WHITE, 1),
BLUE (FSkin.ManaImages.IMG_BLUE, CardRulesPredicates.Presets.IS_BLUE, 1),
BLACK (FSkin.ManaImages.IMG_BLACK, CardRulesPredicates.Presets.IS_BLACK, 1),
RED (FSkin.ManaImages.IMG_RED, CardRulesPredicates.Presets.IS_RED, 1),
GREEN (FSkin.ManaImages.IMG_GREEN, CardRulesPredicates.Presets.IS_GREEN, 1),
COLORLESS (FSkin.ManaImages.IMG_COLORLESS, CardRulesPredicates.Presets.IS_COLORLESS, 1),
MULTICOLOR (FSkin.EditorImages.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR, 1),
PACK (FSkin.EditorImages.IMG_PACK, null, 2),
LAND (FSkin.EditorImages.IMG_LAND, CardRulesPredicates.Presets.IS_LAND, 2),
ARTIFACT (FSkin.EditorImages.IMG_ARTIFACT, CardRulesPredicates.Presets.IS_ARTIFACT, 2),
CREATURE (FSkin.EditorImages.IMG_CREATURE, CardRulesPredicates.Presets.IS_CREATURE, 2),
ENCHANTMENT (FSkin.EditorImages.IMG_ENCHANTMENT, CardRulesPredicates.Presets.IS_ENCHANTMENT, 2),
PLANESWALKER (FSkin.EditorImages.IMG_PLANESWALKER, CardRulesPredicates.Presets.IS_PLANESWALKER, 2),
INSTANT (FSkin.EditorImages.IMG_INSTANT, CardRulesPredicates.Presets.IS_INSTANT, 2),
SORCERY (FSkin.EditorImages.IMG_SORCERY, CardRulesPredicates.Presets.IS_SORCERY, 2);
public final ImageIcon img;
public final Predicate<CardRules> predicate;
public final int group;
StatTypes(FSkin.SkinProp prop, Predicate<CardRules> pred, int grp) {
img = new ImageIcon(FSkin.getImage(prop, 18, 18));
predicate = pred;
group = grp;
}
public String toLabelString() {
if (this == PACK) {
return "Card packs and prebuilt decks";
}
return TextUtil.enumToLabel(this) + " cards";
}
}
/**
* Divides X by Y, multiplies by 100, rounds, returns.
*
* @param x0 &emsp; Numerator (int)
* @param y0 &emsp; Denominator (int)
* @return rounded result (int)
*/
public static int calculatePercentage(final int x0, final int y0) {
return (int) Math.round((double) (x0 * 100) / (double) y0);
}
private static final Predicate<Object> totalPred = Predicates.instanceOf(PaperCard.class);
private static final Predicate<Object> packPred = Predicates.not(totalPred);
/**
* setStats.
*
* @param <T> &emsp; the generic type
* @param items &emsp; ItemPoolView<InventoryITem>
* @param view &emsp; {@link forge.gui.deckeditor.views.ITableContainer}
*/
public static <T extends InventoryItem> void setStats(final ItemPoolView<T> items, final ITableContainer view) {
for (StatTypes s : StatTypes.values()) {
switch (s) {
case TOTAL:
view.getStatLabel(s).setText(String.valueOf(
Aggregates.sum(Iterables.filter(items, Predicates.compose(totalPred, items.FN_GET_KEY)), items.FN_GET_COUNT)));
break;
case PACK:
view.getStatLabel(s).setText(String.valueOf(
Aggregates.sum(Iterables.filter(items, Predicates.compose(packPred, items.FN_GET_KEY)), items.FN_GET_COUNT)));
break;
default:
view.getStatLabel(s).setText(String.valueOf(items.countAll(Predicates.compose(s.predicate, PaperCard.FN_GET_RULES), PaperCard.class)));
}
}
}
/**
* Resets components that may have been changed
* by various configurations of the deck editor.
*/
public static void resetUI() {
VCardCatalog.SINGLETON_INSTANCE.getBtnAdd4().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnRemove4().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnSave().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnSaveAs().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnNew().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnOpen().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().setEnabled(true);
VCardCatalog.SINGLETON_INSTANCE.getPnlHeader().setVisible(false);
VCardCatalog.SINGLETON_INSTANCE.getLblTitle().setText("");
VCurrentDeck.SINGLETON_INSTANCE.getPnlHeader().setVisible(true);
VCardCatalog.SINGLETON_INSTANCE.getTabLabel().setText("Card Catalog");
VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getBtnDoSideboard().setVisible(false);
VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().setVisible(true);
VCurrentDeck.SINGLETON_INSTANCE.getLblTitle().setText("Title:");
}
}

View File

@@ -0,0 +1,585 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import com.google.common.base.Function;
import forge.Singletons;
import forge.card.CardAiHints;
import forge.card.CardEdition;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.ColorSet;
import forge.card.mana.ManaCost;
import forge.deck.DeckBase;
import forge.game.limited.DraftRankCache;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.controllers.ACEditorBase;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.item.InventoryItem;
import forge.item.InventoryItemFromSet;
/**
* A collection of methods pertaining to columns in card catalog and
* current deck tables, for use in the deck editor.
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*
*/
public final class SColumnUtil {
/**
* Each catalog column identified in the XML file is
* referenced using these names. Its name in the XML
* should match the name in the enum. Underscores
* will be replaced with spaces in the display.
* <br><br>
* Note: To add a new column, put an enum here, and also add in the XML prefs file.
*/
public enum ColumnName { /** */
CAT_QUANTITY, /** */
CAT_NAME, /** */
CAT_COST, /** */
CAT_COLOR, /** */
CAT_TYPE, /** */
CAT_POWER, /** */
CAT_TOUGHNESS, /** */
CAT_CMC, /** */
CAT_RARITY, /** */
CAT_SET, /** */
CAT_AI, /** */
CAT_NEW, /** */
CAT_PURCHASE_PRICE, /** */
CAT_OWNED, /** */
CAT_RANKING,
DECK_QUANTITY, /** */
DECK_NAME, /** */
DECK_COST, /** */
DECK_COLOR, /** */
DECK_TYPE, /** */
DECK_POWER, /** */
DECK_TOUGHNESS, /** */
DECK_CMC, /** */
DECK_RARITY, /** */
DECK_SET, /** */
DECK_AI, /** */
DECK_NEW, /** */
DECK_SALE_PRICE, /** */
DECK_DECKS,
DECK_RANKING;
}
/** Possible states of data sorting in a column: none, ascending, or descending. */
public enum SortState { /** */
NONE, /** */
ASC, /** */
DESC
}
/** @return List<TableColumnInfo<InventoryItem>> */
public static List<TableColumnInfo<InventoryItem>> getCatalogDefaultColumns() {
final List<TableColumnInfo<InventoryItem>> columns = new ArrayList<TableColumnInfo<InventoryItem>>();
columns.add(SColumnUtil.getColumn(ColumnName.CAT_QUANTITY));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_NAME));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_COST));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_COLOR));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_TYPE));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_POWER));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_TOUGHNESS));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_CMC));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_RARITY));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_SET));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_AI));
columns.add(SColumnUtil.getColumn(ColumnName.CAT_RANKING));
return columns;
}
/** @return List<TableColumnInfo<InventoryItem>> */
public static List<TableColumnInfo<InventoryItem>> getDeckDefaultColumns() {
final List<TableColumnInfo<InventoryItem>> columns = new ArrayList<TableColumnInfo<InventoryItem>>();
columns.add(SColumnUtil.getColumn(ColumnName.DECK_QUANTITY));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_NAME));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_COST));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_COLOR));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_TYPE));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_POWER));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_TOUGHNESS));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_CMC));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_RARITY));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_SET));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_AI));
columns.add(SColumnUtil.getColumn(ColumnName.DECK_RANKING));
return columns;
}
/** Should be called after column preferences has run, which has created a new column list. */
public static void attachSortAndDisplayFunctions() {
SColumnUtil.getColumn(ColumnName.CAT_QUANTITY).setSortAndDisplayFunctions(
SColumnUtil.FN_QTY_COMPARE, SColumnUtil.FN_QTY_GET);
SColumnUtil.getColumn(ColumnName.CAT_NAME).setSortAndDisplayFunctions(
SColumnUtil.FN_NAME_COMPARE, SColumnUtil.FN_NAME_GET);
SColumnUtil.getColumn(ColumnName.CAT_COST).setSortAndDisplayFunctions(
SColumnUtil.FN_COST_COMPARE, SColumnUtil.FN_COST_GET);
SColumnUtil.getColumn(ColumnName.CAT_COLOR).setSortAndDisplayFunctions(
SColumnUtil.FN_COLOR_COMPARE, SColumnUtil.FN_COLOR_GET);
SColumnUtil.getColumn(ColumnName.CAT_TYPE).setSortAndDisplayFunctions(
SColumnUtil.FN_TYPE_COMPARE, SColumnUtil.FN_TYPE_GET);
SColumnUtil.getColumn(ColumnName.CAT_POWER).setSortAndDisplayFunctions(
SColumnUtil.FN_POWER_COMPARE, SColumnUtil.FN_POWER_GET);
SColumnUtil.getColumn(ColumnName.CAT_TOUGHNESS).setSortAndDisplayFunctions(
SColumnUtil.FN_TOUGHNESS_COMPARE, SColumnUtil.FN_TOUGHNESS_GET);
SColumnUtil.getColumn(ColumnName.CAT_CMC).setSortAndDisplayFunctions(
SColumnUtil.FN_CMC_COMPARE, SColumnUtil.FN_CMC_GET);
SColumnUtil.getColumn(ColumnName.CAT_RARITY).setSortAndDisplayFunctions(
SColumnUtil.FN_RARITY_COMPARE, SColumnUtil.FN_RARITY_GET);
SColumnUtil.getColumn(ColumnName.CAT_SET).setSortAndDisplayFunctions(
SColumnUtil.FN_SET_COMPARE, SColumnUtil.FN_SET_GET);
SColumnUtil.getColumn(ColumnName.CAT_AI).setSortAndDisplayFunctions(
SColumnUtil.FN_AI_STATUS_COMPARE, SColumnUtil.FN_AI_STATUS_GET);
SColumnUtil.getColumn(ColumnName.CAT_RANKING).setSortAndDisplayFunctions(
SColumnUtil.FN_RANKING_COMPARE, SColumnUtil.FN_RANKING_GET);
SColumnUtil.getColumn(ColumnName.DECK_QUANTITY).setSortAndDisplayFunctions(
SColumnUtil.FN_QTY_COMPARE, SColumnUtil.FN_QTY_GET);
SColumnUtil.getColumn(ColumnName.DECK_NAME).setSortAndDisplayFunctions(
SColumnUtil.FN_NAME_COMPARE, SColumnUtil.FN_NAME_GET);
SColumnUtil.getColumn(ColumnName.DECK_COST).setSortAndDisplayFunctions(
SColumnUtil.FN_COST_COMPARE, SColumnUtil.FN_COST_GET);
SColumnUtil.getColumn(ColumnName.DECK_COLOR).setSortAndDisplayFunctions(
SColumnUtil.FN_COLOR_COMPARE, SColumnUtil.FN_COLOR_GET);
SColumnUtil.getColumn(ColumnName.DECK_TYPE).setSortAndDisplayFunctions(
SColumnUtil.FN_TYPE_COMPARE, SColumnUtil.FN_TYPE_GET);
SColumnUtil.getColumn(ColumnName.DECK_POWER).setSortAndDisplayFunctions(
SColumnUtil.FN_POWER_COMPARE, SColumnUtil.FN_POWER_GET);
SColumnUtil.getColumn(ColumnName.DECK_TOUGHNESS).setSortAndDisplayFunctions(
SColumnUtil.FN_TOUGHNESS_COMPARE, SColumnUtil.FN_TOUGHNESS_GET);
SColumnUtil.getColumn(ColumnName.DECK_CMC).setSortAndDisplayFunctions(
SColumnUtil.FN_CMC_COMPARE, SColumnUtil.FN_CMC_GET);
SColumnUtil.getColumn(ColumnName.DECK_RARITY).setSortAndDisplayFunctions(
SColumnUtil.FN_RARITY_COMPARE, SColumnUtil.FN_RARITY_GET);
SColumnUtil.getColumn(ColumnName.DECK_SET).setSortAndDisplayFunctions(
SColumnUtil.FN_SET_COMPARE, SColumnUtil.FN_SET_GET);
SColumnUtil.getColumn(ColumnName.DECK_AI).setSortAndDisplayFunctions(
SColumnUtil.FN_AI_STATUS_COMPARE, SColumnUtil.FN_AI_STATUS_GET);
SColumnUtil.getColumn(ColumnName.DECK_RANKING).setSortAndDisplayFunctions(
SColumnUtil.FN_RANKING_COMPARE, SColumnUtil.FN_RANKING_GET);
SColumnUtil.getColumn(ColumnName.CAT_COST).setCellRenderer(new ManaCostRenderer());
SColumnUtil.getColumn(ColumnName.CAT_POWER).setCellRenderer(new IntegerRenderer());
SColumnUtil.getColumn(ColumnName.CAT_TOUGHNESS).setCellRenderer(new IntegerRenderer());
SColumnUtil.getColumn(ColumnName.CAT_CMC).setCellRenderer(new IntegerRenderer());
SColumnUtil.getColumn(ColumnName.CAT_SET).setCellRenderer(new SetCodeRenderer());
SColumnUtil.getColumn(ColumnName.DECK_COST).setCellRenderer(new ManaCostRenderer());
SColumnUtil.getColumn(ColumnName.DECK_POWER).setCellRenderer(new IntegerRenderer());
SColumnUtil.getColumn(ColumnName.DECK_TOUGHNESS).setCellRenderer(new IntegerRenderer());
SColumnUtil.getColumn(ColumnName.DECK_CMC).setCellRenderer(new IntegerRenderer());
SColumnUtil.getColumn(ColumnName.DECK_SET).setCellRenderer(new SetCodeRenderer());
}
/**
* Hides/shows a table column.
*
* @param col0 TableColumnInfo<InventoryItem>
* @param <TItem> extends InventoryItem
* @param <TModel> extends DeckBase
*/
@SuppressWarnings("unchecked")
public static <TItem extends InventoryItem, TModel extends DeckBase>
void toggleColumn(final TableColumnInfo<InventoryItem> col0) {
final ACEditorBase<TItem, TModel> ed = (ACEditorBase<TItem, TModel>)
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController();
final JTable tbl = (col0.getEnumValue().substring(0, 4).equals("DECK"))
? ed.getTableDeck().getTable()
: ed.getTableCatalog().getTable();
final TableColumnModel colmodel = tbl.getColumnModel();
if (col0.isShowing()) {
col0.setShowing(false);
colmodel.removeColumn(col0);
}
else {
col0.setShowing(true);
colmodel.addColumn(col0);
if (col0.getModelIndex() < colmodel.getColumnCount()) {
colmodel.moveColumn(colmodel.getColumnIndex(col0.getIdentifier()), col0.getModelIndex());
Enumeration<TableColumn> cols = colmodel.getColumns();
int index = 0;
// If you're getting renderer "can't cast T to U" errors, that's
// a sign that the model index needs updating.
while (cols.hasMoreElements()) {
cols.nextElement().setModelIndex(index++);
}
}
else {
col0.setModelIndex(colmodel.getColumnCount());
}
}
}
/**
* Retrieve a custom column (uses identical method in SEditorIO).
*
* @param id0 &emsp; {@link forge.gui.deckeditor.SCardListViewUtil.CatalogColumnName}
* @return TableColumnInfo<InventoryItem>
*/
public static TableColumnInfo<InventoryItem> getColumn(final ColumnName id0) {
return SCardListViewIO.getColumn(id0);
}
/**
* Convenience method to get a column's index in the view (that is,
* in the TableColumnModel).
*
* @param id0 &emsp; {@link forge.gui.deckeditor.SCardListViewUtil.CatalogColumnName}
* @return int
* @param <TItem> extends InventoryItem
* @param <TModel> extends InventoryItem
*/
@SuppressWarnings("unchecked")
public static <TItem extends InventoryItem, TModel extends DeckBase>
int getColumnViewIndex(final ColumnName id0) {
final ACEditorBase<TItem, TModel> ed = (ACEditorBase<TItem, TModel>)
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController();
final JTable tbl = (id0.toString().substring(0, 4).equals("DECK"))
? ed.getTableDeck().getTable()
: ed.getTableCatalog().getTable();
int index = -1;
try {
index = tbl.getColumnModel().getColumnIndex(SColumnUtil.getColumn(id0).getIdentifier());
}
catch (final Exception e) { }
return index;
}
/**
* Convenience method to get a column's index in the model (that is,
* in the EditorTableModel, NOT the TableColumnModel).
*
* @param id0 &emsp; {@link forge.gui.deckeditor.SCardListViewUtil.CatalogColumnName}
* @return int
* @param <TItem> extends InventoryItem
* @param <TModel> extends InventoryItem
*/
@SuppressWarnings("unchecked")
public static <TItem extends InventoryItem, TModel extends DeckBase>
int getColumnModelIndex(final ColumnName id0) {
final ACEditorBase<TItem, TModel> ed = (ACEditorBase<TItem, TModel>)
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController();
final JTable tbl = (id0.toString().substring(0, 4).equals("DECK"))
? ed.getTableDeck().getTable()
: ed.getTableCatalog().getTable();
return tbl.getColumn(SColumnUtil.getColumn(id0).getIdentifier()).getModelIndex();
}
//========== Display functions
private static final Pattern AE_FINDER = Pattern.compile("AE", Pattern.LITERAL);
private static ManaCost toManaCost(final InventoryItem i) {
return i instanceof IPaperCard ? ((IPaperCard) i).getRules().getManaCost() : ManaCost.NO_COST;
}
private static CardRules toCardRules(final InventoryItem i) {
return i instanceof IPaperCard ? ((IPaperCard) i).getRules() : null;
}
private static ColorSet toColor(final InventoryItem i) {
return i instanceof IPaperCard ? ((IPaperCard) i).getRules().getColor() : ColorSet.getNullColor();
}
private static int toPower(final InventoryItem i) {
int result = -1;
if (i instanceof PaperCard) {
result = ((IPaperCard) i).getRules().getIntPower();
if (result == -1) {
result = ((IPaperCard) i).getRules().getInitialLoyalty();
}
}
return result;
}
private static int toToughness(final InventoryItem i) {
return i instanceof PaperCard ? ((IPaperCard) i).getRules().getIntToughness() : -1;
}
private static Integer toCMC(final InventoryItem i) {
return i instanceof PaperCard ? ((IPaperCard) i).getRules().getManaCost().getCMC() : -1;
}
private static CardRarity toRarity(final InventoryItem i) {
return i instanceof PaperCard ? ((IPaperCard) i).getRarity() : CardRarity.Unknown;
}
private static CardEdition toSetCmp(final InventoryItem i) {
return i instanceof InventoryItemFromSet ? Singletons.getModel().getEditions()
.get(((InventoryItemFromSet) i).getEdition()) : CardEdition.UNKNOWN;
}
private static String toSetStr(final InventoryItem i) {
return i instanceof InventoryItemFromSet ? ((InventoryItemFromSet) i).getEdition() : "n/a";
}
private static Integer toAiCmp(final InventoryItem i) {
return i instanceof PaperCard ? ((IPaperCard) i).getRules().getAiHints().getAiStatusComparable() : Integer.valueOf(-1);
}
private static String toAiStr(final InventoryItem i) {
if (!(i instanceof PaperCard))
return "n/a";
IPaperCard cp = (IPaperCard) i;
CardAiHints ai = cp.getRules().getAiHints();
return ai.getRemAIDecks() ? (ai.getRemRandomDecks() ? "AI ?" : "AI")
: (ai.getRemRandomDecks() ? "?" : "");
}
private static Double toRankingCmp(final InventoryItem i) {
Double ranking = 500D;
if (i != null && i instanceof PaperCard){
PaperCard cp = (PaperCard) i;
ranking = DraftRankCache.getRanking(cp.getName(), cp.getEdition());
if ( ranking == null )
ranking = 500D;
}
return ranking;
}
//==========
/** Lamda sort fnQtyCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_QTY_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return from.getValue();
}
};
/** Lamda sort fnQtyGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_QTY_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return from.getValue();
}
};
/** Lamda sort fnNameCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_NAME_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return from.getKey().getName();
}
};
/** Lamda sort fnNameGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_NAME_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
final String name = from.getKey().getName();
return name.contains("AE") ? SColumnUtil.AE_FINDER.matcher(name).replaceAll("\u00C6") : name;
}
};
/** Lamda sort fnCostCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_COST_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toManaCost(from.getKey());
}
};
/** Lamda sort fnCostGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_COST_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toCardRules(from.getKey());
}
};
/** Lamda sort fnColorCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_COLOR_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toColor(from.getKey());
}
};
/** Lamda sort fnColorGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_COLOR_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toColor(from.getKey());
}
};
/** Lamda sort fnTypeCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_TYPE_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
InventoryItem i = from.getKey();
return i instanceof PaperCard ? ((IPaperCard)i).getRules().getType().toString() : i.getItemType();
}
};
/** Lamda sort fnTypeGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_TYPE_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
InventoryItem i = from.getKey();
return i instanceof PaperCard ? ((IPaperCard)i).getRules().getType().toString() : i.getItemType();
}
};
/** Lamda sort fnPowerCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_POWER_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return Integer.valueOf(SColumnUtil.toPower(from.getKey()));
}
};
/** Lamda sort fnPowerGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_POWER_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return Integer.valueOf(SColumnUtil.toPower(from.getKey()));
}
};
/** Lamda sort fnToughnessCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_TOUGHNESS_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return Integer.valueOf(SColumnUtil.toToughness(from.getKey()));
}
};
/** Lamda sort fnToughnessGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_TOUGHNESS_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return Integer.valueOf(SColumnUtil.toToughness(from.getKey()));
}
};
/** Lamda sort fnCMCCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_CMC_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toCMC(from.getKey());
}
};
/** Lamda sort fnCMCGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_CMC_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toCMC(from.getKey());
}
};
/** Lamda sort fnRarityCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_RARITY_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toRarity(from.getKey());
}
};
/** Lamda sort fnRarityGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_RARITY_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toRarity(from.getKey());
}
};
/** Lamda sort fnSetCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_SET_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toSetCmp(from.getKey());
}
};
/** Lamda sort fnSetGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_SET_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toSetStr(from.getKey());
}
};
/** Lamda sort fnAiStatusCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_AI_STATUS_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toAiCmp(from.getKey());
}
};
/** Lamda sort fnAiStatusGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_AI_STATUS_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toAiStr(from.getKey());
}
};
/** Lamda sort fnRankingCompare. */
private static final Function<Entry<InventoryItem, Integer>, Comparable<?>> FN_RANKING_COMPARE = new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
return SColumnUtil.toRankingCmp(from.getKey());
}
};
/** Lamda sort fnRankingGet. */
private static final Function<Entry<InventoryItem, Integer>, Object> FN_RANKING_GET = new Function<Entry<InventoryItem, Integer>, Object>() {
@Override
public Object apply(final Entry<InventoryItem, Integer> from) {
return String.valueOf(SColumnUtil.toRankingCmp(from.getKey()));
}
};
}

View File

@@ -0,0 +1,144 @@
package forge.gui.cardlistview;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCardCatalog.RangeTypes;
import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSpinner;
import forge.item.PaperCard;
import forge.util.ComparableOp;
import forge.util.PredicateString.StringOp;
/**
* Static factory; holds blocks of form elements and predicates
* which are used in various editing environments.
* <br><br>
* <i>(S at beginning of class name denotes a static factory.)</i>
*/
public class SFilterUtil {
/**
* queries color filters for state and returns a predicate.
* <br><br>
* Handles "multicolor" label, which is quite tricky.
*/
public static Predicate<PaperCard> buildColorAndTypeFilter(Map<SCardListViewUtil.StatTypes, FLabel> statLabels) {
final List<Predicate<CardRules>> colors = new ArrayList<Predicate<CardRules>>();
final List<Predicate<CardRules>> types = new ArrayList<Predicate<CardRules>>();
boolean wantMulticolor = false;
Predicate<CardRules> preExceptMulti = null;
for (SCardListViewUtil.StatTypes s : SCardListViewUtil.StatTypes.values()) {
switch (s) {
case WHITE: case BLUE: case BLACK: case RED: case GREEN: case COLORLESS:
if (statLabels.get(s).getSelected()) { colors.add(s.predicate); }
break;
case MULTICOLOR:
wantMulticolor = statLabels.get(s).getSelected();
preExceptMulti = wantMulticolor ? null : Predicates.not(s.predicate);
break;
case LAND: case ARTIFACT: case CREATURE: case ENCHANTMENT: case PLANESWALKER: case INSTANT: case SORCERY:
if (statLabels.get(s).getSelected()) { types.add(s.predicate); }
break;
case TOTAL: case PACK:
// ignore
break;
default:
throw new RuntimeException("unhandled enum value: " + s);
}
}
Predicate<CardRules> preColors = colors.size() == 6 ? null : Predicates.or(colors);
Predicate<CardRules> preFinal = colors.isEmpty() && wantMulticolor ?
CardRulesPredicates.Presets.IS_MULTICOLOR : optimizedAnd(preExceptMulti, preColors);
if (null == preFinal && 7 == types.size()) {
return Predicates.alwaysTrue();
}
Predicate<PaperCard> typesFinal = Predicates.compose(Predicates.or(types), PaperCard.FN_GET_RULES);
if (null == preFinal) {
return typesFinal;
}
Predicate<PaperCard> colorFinal = Predicates.compose(preFinal, PaperCard.FN_GET_RULES);
if (7 == types.size()) {
return colorFinal;
}
return Predicates.and(colorFinal, typesFinal);
}
/**
* builds a string search filter
*/
public static Predicate<PaperCard> buildTextFilter(String text, boolean invert, boolean inName, boolean inType, boolean inText) {
if (text.trim().isEmpty()) {
return Predicates.alwaysTrue();
}
String[] splitText = text.replaceAll(",", "").replaceAll(" ", " ").split(" ");
List<Predicate<CardRules>> terms = new ArrayList<Predicate<CardRules>>();
for (String s : splitText) {
List<Predicate<CardRules>> subands = new ArrayList<Predicate<CardRules>>();
if (inName) { subands.add(CardRulesPredicates.name(StringOp.CONTAINS_IC, s)); }
if (inType) { subands.add(CardRulesPredicates.joinedType(StringOp.CONTAINS_IC, s)); }
if (inText) { subands.add(CardRulesPredicates.rules(StringOp.CONTAINS_IC, s)); }
terms.add(Predicates.or(subands));
}
Predicate<CardRules> textFilter = invert ? Predicates.not(Predicates.or(terms)) : Predicates.and(terms);
return Predicates.compose(textFilter, PaperCard.FN_GET_RULES);
}
private static Predicate<CardRules> getCardRulesFieldPredicate(int min, int max, CardRulesPredicates.LeafNumber.CardField field) {
boolean hasMin = 0 != min;
boolean hasMax = 10 != max;
Predicate<CardRules> pMin = !hasMin ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.GT_OR_EQUAL, min);
Predicate<CardRules> pMax = !hasMax ? null : new CardRulesPredicates.LeafNumber(field, ComparableOp.LT_OR_EQUAL, max);
return optimizedAnd(pMin, pMax);
}
private static <T> Predicate<T> optimizedAnd(Predicate<T> p1, Predicate<T> p2)
{
return p1 == null ? p2 : (p2 == null ? p1 : Predicates.and(p1, p2));
}
/**
* builds a filter for an interval on a card field
*/
public static Predicate<PaperCard> buildIntervalFilter(
Map<RangeTypes, Pair<FSpinner, FSpinner>> spinners, VCardCatalog.RangeTypes field) {
Pair<FSpinner, FSpinner> sPair = spinners.get(field);
Predicate<CardRules> fieldFilter = getCardRulesFieldPredicate(
Integer.valueOf(sPair.getLeft().getValue().toString()),
Integer.valueOf(sPair.getRight().getValue().toString()), field.cardField);
if (null != fieldFilter && VCardCatalog.RangeTypes.CMC != field)
{
fieldFilter = Predicates.and(fieldFilter, CardRulesPredicates.Presets.IS_CREATURE);
}
if (fieldFilter == null) {
return Predicates.alwaysTrue();
} else {
return Predicates.compose(fieldFilter, PaperCard.FN_GET_RULES);
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import javax.swing.table.DefaultTableCellRenderer;
import forge.Singletons;
import forge.card.EditionCollection;
/**
* A wrapper to show explanatory tooltips for edition set abbreviations.
*/
@SuppressWarnings("serial")
public class SetCodeRenderer extends DefaultTableCellRenderer implements AlwaysShowToolTip {
@Override
public String getToolTipText() {
String setAbbrev = getText();
String setFullName = "Unknown set";
EditionCollection editions = Singletons.getModel().getEditions();
if (null != setAbbrev && editions.contains(setAbbrev)) {
setFullName = editions.get(setAbbrev).getName();
}
return String.format("%s (%s)", setFullName, setAbbrev);
}
}

View File

@@ -0,0 +1,143 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.util.Map.Entry;
import javax.swing.table.TableColumn;
import com.google.common.base.Function;
import forge.gui.deckeditor.tables.SColumnUtil.SortState;
/**
* A column object in a EditorTableModel in the card editor.
* Requires a sorting function and a display function
* (to extract information as appropriate for table row data).
*
* @param <T> a generic type
*/
public class TableColumnInfo<T> extends TableColumn {
private static final long serialVersionUID = 3749431834643427572L;
private SortState sortstate = SortState.NONE;
private int sortPriority = 0;
private boolean show = true;
private String enumval;
private Function<Entry<T, Integer>, Comparable<?>> fnSort;
private Function<Entry<T, Integer>, Object> fnDisplay;
/** */
public TableColumnInfo() {
super();
}
/**
* Unique identifier in SColumnUtil.ColumnName enum.
*
* @return {@link java.lang.String}
*/
public String getEnumValue() {
return enumval;
}
/**
* Unique identifier in SColumnUtil.ColumnName enum.
*
* @param val0 &emsp; {@link java.lang.String}
*/
public void setEnumValue(final String val0) {
this.enumval = val0;
}
/**
* Position in sort cascade, 0 for no priority.
*
* @return int
*/
public int getSortPriority() {
return sortPriority;
}
/**
* Position in sort cascade, 0 for no priority.
*
* @param position0 &emsp; int
*/
public void setSortPriority(final int position0) {
this.sortPriority = position0;
}
/** @return {@link forge.gui.deckeditor.tables.EditorTableModel.SortState} */
public SortState getSortState() {
return this.sortstate;
}
/** @param state0 &emsp; {@link forge.gui.deckeditor.tables.TableColumnInfo.SortState} */
public void setSortState(final SortState state0) {
this.sortstate = state0;
}
/** @return boolean */
public boolean isShowing() {
return this.show;
}
/** @param boolean0 &emsp; show/hide this column */
public void setShowing(final boolean boolean0) {
this.show = boolean0;
}
/**
* Lambda closure used to sort this column.
*
* @return the fnSort
*/
public Function<Entry<T, Integer>, Comparable<?>> getFnSort() {
if (fnSort == null) {
throw new NullPointerException("A sort function hasn't been set for "
+ "Column " + TableColumnInfo.this.getIdentifier());
}
return this.fnSort;
}
/**
* Gets the fn display.
*
* @return the fnDisplay
*/
public Function<Entry<T, Integer>, Object> getFnDisplay() {
if (fnSort == null) {
throw new NullPointerException("A display function hasn't been set for "
+ "Column " + TableColumnInfo.this.getIdentifier());
}
return this.fnDisplay;
}
/**
* Lambda closure used to sort this column, and fn display.
*
* @param lambda0 the fnSort
* @param lambda1 the fnDisplay
*/
public void setSortAndDisplayFunctions(final Function<Entry<T, Integer>, Comparable<?>> lambda0, final Function<Entry<T, Integer>, Object> lambda1) {
this.fnSort = lambda0;
this.fnDisplay = lambda1;
}
}

View File

@@ -0,0 +1,86 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.util.Comparator;
import java.util.Map.Entry;
import com.google.common.base.Function;
import forge.item.PaperCard;
/**
* <p>
* TableSorter class.
* </p>
*
* @param <T>
* the generic type
* @author Forge
* @version $Id: TableSorter.java 21966 2013-06-05 06:58:32Z Max mtg $
*/
@SuppressWarnings("unchecked")
// Comparable needs <type>
public class TableSorter<T> implements Comparator<Entry<T, Integer>> {
private final boolean ascending;
private final Function<Entry<T, Integer>, Comparable<?>> field;
/**
* <p>
* Constructor for TableSorter.
* </p>
*
* @param field
* the field
* @param inAscending
* a boolean.
*/
public TableSorter(final Function<Entry<T, Integer>, Comparable<?>> field, final boolean inAscending) {
this.field = field;
this.ascending = inAscending;
}
/** The Constant byNameThenSet. */
public static final TableSorter<PaperCard> BY_NAME_THEN_SET = new TableSorter<PaperCard>(
new Function<Entry<PaperCard, Integer>, Comparable<?>>() {
@Override
public Comparable<?> apply(final Entry<PaperCard, Integer> from) {
return from.getKey();
}
}, true);
/*
* (non-Javadoc)
*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@SuppressWarnings("rawtypes")
@Override
public final int compare(final Entry<T, Integer> arg0, final Entry<T, Integer> arg1) {
final Comparable obj1 = this.field.apply(arg0);
final Comparable obj2 = this.field.apply(arg1);
if (obj1 == null) {
return -1;
}
if (obj2 == null) {
return 1;
}
//System.out.println(String.format("%s vs %s _______ %s vs %s", arg0, arg1, obj1, obj2));
return this.ascending ? obj1.compareTo(obj2) : obj2.compareTo(obj1);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.gui.cardlistview;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import forge.item.InventoryItem;
/**
* <p>
* TableSorter class.
* </p>
*
* @param <T>
* extends InventoryItem
* @author Forge
* @version $Id: TableSorter.java 10146 2011-09-01 18:11:00Z Max mtg $
*/
public class TableSorterCascade<T extends InventoryItem> implements Comparator<Entry<T, Integer>> {
private final List<TableSorter<T>> sorters;
private final int cntFields;
/**
*
* TableSorterCascade Constructor.
*
* @param sortersCascade
* a List<TableSorter<T>>
*/
public TableSorterCascade(final List<TableSorter<T>> sortersCascade) {
this.sorters = sortersCascade;
this.cntFields = sortersCascade.size();
}
/*
* (non-Javadoc)
*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@Override
public final int compare(final Entry<T, Integer> arg0, final Entry<T, Integer> arg1) {
int lastCompare = 0;
int iField = -1;
while ((++iField < this.cntFields) && (lastCompare == 0)) { // reverse
// iteration
final TableSorter<T> sorter = this.sorters.get(iField);
if (sorter == null) {
break;
}
lastCompare = sorter.compare(arg0, arg1);
}
return lastCompare;
}
}

View File

@@ -0,0 +1,3 @@
/** Forge Card Game. */
package forge.gui.cardlistview;