mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Start breaking off files for CardListView
This commit is contained in:
15
.gitattributes
vendored
15
.gitattributes
vendored
@@ -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
|
||||
|
||||
25
src/main/java/forge/gui/cardlistview/AlwaysShowToolTip.java
Normal file
25
src/main/java/forge/gui/cardlistview/AlwaysShowToolTip.java
Normal 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 {
|
||||
}
|
||||
401
src/main/java/forge/gui/cardlistview/EditorTableModel.java
Normal file
401
src/main/java/forge/gui/cardlistview/EditorTableModel.java
Normal 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   {@link javax.swing.JTable}
|
||||
* @param class0   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   {@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   {@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   {@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
|
||||
576
src/main/java/forge/gui/cardlistview/EditorTableView.java
Normal file
576
src/main/java/forge/gui/cardlistview/EditorTableView.java
Normal 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   the {@link javax.gui.deckeditor.views.ITableCOntainer}
|
||||
* @param cols0   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);
|
||||
}
|
||||
}
|
||||
25
src/main/java/forge/gui/cardlistview/ITableContainer.java
Normal file
25
src/main/java/forge/gui/cardlistview/ITableContainer.java
Normal 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   {@link forge.gui.deckeditor.tables.EditorTableView}
|
||||
*/
|
||||
void setTableView(JTable tbl0);
|
||||
|
||||
FLabel getStatLabel(SCardListViewUtil.StatTypes s);
|
||||
}
|
||||
44
src/main/java/forge/gui/cardlistview/IntegerRenderer.java
Normal file
44
src/main/java/forge/gui/cardlistview/IntegerRenderer.java
Normal 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);
|
||||
}
|
||||
}
|
||||
135
src/main/java/forge/gui/cardlistview/ManaCostRenderer.java
Normal file
135
src/main/java/forge/gui/cardlistview/ManaCostRenderer.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
239
src/main/java/forge/gui/cardlistview/SCardListViewIO.java
Normal file
239
src/main/java/forge/gui/cardlistview/SCardListViewIO.java
Normal 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   {@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   {@link forge.gui.deckeditor.SCardListViewUtil.EditorPreference}
|
||||
* @param val0   boolean
|
||||
*/
|
||||
public static void setPref(final EditorPreference name0, final boolean val0) {
|
||||
PREFS.put(name0, val0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a custom column.
|
||||
*
|
||||
* @param name0   {@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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
135
src/main/java/forge/gui/cardlistview/SCardListViewUtil.java
Normal file
135
src/main/java/forge/gui/cardlistview/SCardListViewUtil.java
Normal 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   Numerator (int)
|
||||
* @param y0   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>   the generic type
|
||||
* @param items   ItemPoolView<InventoryITem>
|
||||
* @param view   {@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:");
|
||||
}
|
||||
}
|
||||
585
src/main/java/forge/gui/cardlistview/SColumnUtil.java
Normal file
585
src/main/java/forge/gui/cardlistview/SColumnUtil.java
Normal 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   {@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   {@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   {@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()));
|
||||
}
|
||||
};
|
||||
}
|
||||
144
src/main/java/forge/gui/cardlistview/SFilterUtil.java
Normal file
144
src/main/java/forge/gui/cardlistview/SFilterUtil.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/main/java/forge/gui/cardlistview/SetCodeRenderer.java
Normal file
43
src/main/java/forge/gui/cardlistview/SetCodeRenderer.java
Normal 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);
|
||||
}
|
||||
}
|
||||
143
src/main/java/forge/gui/cardlistview/TableColumnInfo.java
Normal file
143
src/main/java/forge/gui/cardlistview/TableColumnInfo.java
Normal 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   {@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   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   {@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   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;
|
||||
}
|
||||
}
|
||||
86
src/main/java/forge/gui/cardlistview/TableSorter.java
Normal file
86
src/main/java/forge/gui/cardlistview/TableSorter.java
Normal 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);
|
||||
}
|
||||
}
|
||||
71
src/main/java/forge/gui/cardlistview/TableSorterCascade.java
Normal file
71
src/main/java/forge/gui/cardlistview/TableSorterCascade.java
Normal 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;
|
||||
}
|
||||
}
|
||||
3
src/main/java/forge/gui/cardlistview/package-info.java
Normal file
3
src/main/java/forge/gui/cardlistview/package-info.java
Normal file
@@ -0,0 +1,3 @@
|
||||
/** Forge Card Game. */
|
||||
package forge.gui.cardlistview;
|
||||
|
||||
Reference in New Issue
Block a user