implement basic find-as-you-type for deck editor tables

This commit is contained in:
myk
2013-02-10 10:08:12 +00:00
parent 16f3008014
commit a2a15a4740
2 changed files with 101 additions and 23 deletions

View File

@@ -70,16 +70,6 @@ public final class EditorTableModel<T extends InventoryItem> extends AbstractTab
private final int maxSortDepth = 3; private final int maxSortDepth = 3;
private boolean infiniteSupply; private boolean infiniteSupply;
/**
* @return the infiniteSupply
*/
public boolean isInfinite() {
return infiniteSupply;
}
/** /**
* Instantiates a new table model, using a JTable, * Instantiates a new table model, using a JTable,
* a column set, and a data set of generic type <T>. * a column set, and a data set of generic type <T>.
@@ -101,7 +91,6 @@ public final class EditorTableModel<T extends InventoryItem> extends AbstractTab
// Assemble priority sort. // Assemble priority sort.
while (e.hasMoreElements()) { while (e.hasMoreElements()) {
final TableColumnInfo<InventoryItem> col = (TableColumnInfo<InventoryItem>) e.nextElement(); final TableColumnInfo<InventoryItem> col = (TableColumnInfo<InventoryItem>) e.nextElement();
if (col.getSortPriority() > 0) { if (col.getSortPriority() > 0) {
sortcols[col.getSortPriority()] = col; sortcols[col.getSortPriority()] = col;
} }
@@ -408,11 +397,14 @@ public final class EditorTableModel<T extends InventoryItem> extends AbstractTab
} }
/** /**
* TODO: Write javadoc for this method. * Sets whether this table's pool of cards is in infinite supply. If false, cards in the
* @param infinite * table have a limited number of copies.
*/ */
public void setInfinite(boolean infinite) { public void setInfinite(boolean infinite) {
// TODO Auto-generated method stub
this.infiniteSupply = infinite; this.infiniteSupply = infinite;
} }
public boolean isInfinite() {
return infiniteSupply;
}
} // CardTableModel } // CardTableModel

View File

@@ -21,17 +21,22 @@ import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.KeyboardFocusManager; import java.awt.KeyboardFocusManager;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.event.FocusListener; import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener; import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.DefaultTableColumnModel;
@@ -81,19 +86,17 @@ public final class EditorTableView<T extends InventoryItem> {
/** /**
* TableWithCards. * TableWithCards.
* *
* @param cls * @param type0 the class of item that this table will contain
* the cls
*/ */
public EditorTableView(final Class<T> cls) { public EditorTableView(final Class<T> type0) {
this(false, cls); this(false, type0);
} }
/** /**
* TableWithCards Constructor. * TableWithCards Constructor.
* *
* @param forceUnique * @param forceUnique whether this table should display only one item with the same name
* a boolean * @param type0 the class of item that this table will contain
* @param type0 the cls
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public EditorTableView(final boolean forceUnique, final Class<T> type0) { public EditorTableView(final boolean forceUnique, final Class<T> type0) {
@@ -197,6 +200,65 @@ public final class EditorTableView<T extends InventoryItem> {
// prevent tables from intercepting tab focus traversals // prevent tables from intercepting tab focus traversals
table.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null); table.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
table.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null); table.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
// highlight items as the user types a portion of their names
table.addKeyListener(new _FindAsYouType());
}
private class _FindAsYouType extends KeyAdapter {
private StringBuilder str = new StringBuilder();
private long lastUpdatedTimestamp;
private void _findNextMatch(int startIdx) {
int numItems = model.getRowCount();
if (0 == numItems) {
return;
}
// find the next item that matches the string
startIdx %= numItems;
int stopIdx = (startIdx - 1 + numItems) % numItems;
String searchStr = str.toString().toLowerCase(Locale.ENGLISH);
for (int idx = startIdx; idx != stopIdx; idx = (idx + 1) % numItems) {
if (model.rowToCard(idx).getKey().getName().toLowerCase(Locale.ENGLISH).contains(searchStr)) {
selectAndScrollTo(idx);
break;
}
}
}
@Override
public void keyPressed(KeyEvent e) {
if (KeyEvent.VK_F3 == e.getKeyCode()) {
_findNextMatch(table.getSelectedRow() + 1);
}
}
@Override
public void keyTyped(KeyEvent e) {
long curTime = System.currentTimeMillis();
if (5000 < curTime - lastUpdatedTimestamp) {
// too long since last update; clear the search string
str = new StringBuilder();
}
lastUpdatedTimestamp = curTime;
switch (e.getKeyChar()) {
case KeyEvent.CHAR_UNDEFINED:
return;
case KeyEvent.VK_BACK_SPACE:
if (!str.toString().isEmpty()) {
str.deleteCharAt(str.toString().length() - 1);
}
break;
default:
str.append(e.getKeyChar());
}
_findNextMatch(Math.max(0, table.getSelectedRow()));
}
} }
/** /**
@@ -267,7 +329,7 @@ public final class EditorTableView<T extends InventoryItem> {
newRow = numRows - 1; newRow = numRows - 1;
} }
table.setRowSelectionInterval(newRow, newRow); selectAndScrollTo(newRow);
} }
/** /**
@@ -521,4 +583,28 @@ public final class EditorTableView<T extends InventoryItem> {
public void setWantElasticColumns(boolean value) { public void setWantElasticColumns(boolean value) {
table.setAutoResizeMode(value ? JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS : JTable.AUTO_RESIZE_NEXT_COLUMN); 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);
}
} }