Let us filter what entries a DSetEditor shows with a Predicate.
And then build on that to make TabbedDSetEditor so that we can easily break up gigantic lists of entries into smaller & more manageable buckets. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5775 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
// $Id$
|
// $Id$
|
||||||
//
|
//
|
||||||
// Narya library - tools for developing networked games
|
// Narya library - tools for developing networked games
|
||||||
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
// Copyright (C) 2002-2009 Three Rings Design, Inc., All Rights Reserved
|
||||||
// http://www.threerings.net/code/narya/
|
// http://www.threerings.net/code/narya/
|
||||||
//
|
//
|
||||||
// This library is free software; you can redistribute it and/or modify it
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
@@ -25,11 +25,17 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Iterators;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import com.samskivert.util.ComparableArrayList;
|
import com.samskivert.util.ComparableArrayList;
|
||||||
|
|
||||||
import com.samskivert.swing.ObjectEditorTable;
|
import com.samskivert.swing.ObjectEditorTable;
|
||||||
@@ -55,7 +61,7 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
*
|
*
|
||||||
* @param setter The object that contains the set.
|
* @param setter The object that contains the set.
|
||||||
* @param setName The name of the set in the object.
|
* @param setName The name of the set in the object.
|
||||||
* @param entryClass the Class of the DSet.Entry elements contained in the set.
|
* @param entryClass The Class of the DSet.Entry elements contained in the set.
|
||||||
*/
|
*/
|
||||||
public DSetEditor (DObject setter, String setName, Class<?> entryClass)
|
public DSetEditor (DObject setter, String setName, Class<?> entryClass)
|
||||||
{
|
{
|
||||||
@@ -67,11 +73,11 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
*
|
*
|
||||||
* @param setter The object that contains the set.
|
* @param setter The object that contains the set.
|
||||||
* @param setName The name of the set in the object.
|
* @param setName The name of the set in the object.
|
||||||
* @param entryClass the Class of the DSet.Entry elements contained in the set.
|
* @param entryClass The Class of the DSet.Entry elements contained in the set.
|
||||||
* @param editableFields the names of the fields in the entryClass that should be editable.
|
* @param editableFields the names of the fields in the entryClass that should be editable.
|
||||||
*/
|
*/
|
||||||
public DSetEditor (DObject setter, String setName, Class<?> entryClass,
|
public DSetEditor (
|
||||||
String[] editableFields)
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields)
|
||||||
{
|
{
|
||||||
this(setter, setName, entryClass, editableFields, null);
|
this(setter, setName, entryClass, editableFields, null);
|
||||||
}
|
}
|
||||||
@@ -82,17 +88,36 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
* @param setter The object that contains the set.
|
* @param setter The object that contains the set.
|
||||||
* @param setName The name of the set in the object.
|
* @param setName The name of the set in the object.
|
||||||
* @param entryClass the Class of the DSet.Entry elements contained in the set.
|
* @param entryClass the Class of the DSet.Entry elements contained in the set.
|
||||||
* @param editableFields the names of the fields in the entryClass that should be editable.
|
* @param editableFields The names of the fields in the entryClass that should be editable.
|
||||||
* @param interp The FieldInterpreter to use.
|
* @param interp The FieldInterpreter to use.
|
||||||
*/
|
*/
|
||||||
public DSetEditor (DObject setter, String setName, Class<?> entryClass,
|
public DSetEditor (
|
||||||
String[] editableFields, ObjectEditorTable.FieldInterpreter interp)
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
||||||
|
ObjectEditorTable.FieldInterpreter interp)
|
||||||
|
{
|
||||||
|
this(setter, setName, entryClass, editableFields, interp, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a DSetEditor that only displays entries that match the given Predicate.
|
||||||
|
*
|
||||||
|
* @param setter The object that contains the set.
|
||||||
|
* @param setName The name of the set in the object.
|
||||||
|
* @param entryClass The Class of the DSet.Entry elements contained in the set.
|
||||||
|
* @param editableFields The names of the fields in the entryClass that should be editable.
|
||||||
|
* @param interp The FieldInterpreter to use.
|
||||||
|
* @param entryFilter The Predicate to use.
|
||||||
|
*/
|
||||||
|
public DSetEditor (
|
||||||
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
||||||
|
ObjectEditorTable.FieldInterpreter interp, Predicate<E> entryFilter)
|
||||||
{
|
{
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
|
|
||||||
_setter = setter;
|
_setter = setter;
|
||||||
_setName = setName;
|
_setName = setName;
|
||||||
_set = _setter.getSet(setName);
|
_set = _setter.getSet(setName);
|
||||||
|
_entryFilter = entryFilter;
|
||||||
|
|
||||||
_table = new ObjectEditorTable(entryClass, editableFields, interp);
|
_table = new ObjectEditorTable(entryClass, editableFields, interp);
|
||||||
|
|
||||||
@@ -142,13 +167,34 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
super.removeNotify();
|
super.removeNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the addition of an entry, assuming our filter allows it.
|
||||||
|
*/
|
||||||
|
protected void addEntry (E entry)
|
||||||
|
{
|
||||||
|
if (_entryFilter == null || _entryFilter.apply(entry)) {
|
||||||
|
int index = _keys.insertSorted(getKey(entry));
|
||||||
|
_table.insertDatum(entry, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes care of removing a key from
|
||||||
|
*/
|
||||||
|
protected void removeKey (Comparable<?> key)
|
||||||
|
{
|
||||||
|
int index = _keys.indexOf(key);
|
||||||
|
if (index != -1) {
|
||||||
|
_keys.remove(index);
|
||||||
|
_table.removeDatum(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// documentation inherited from interface SetListener
|
// documentation inherited from interface SetListener
|
||||||
public void entryAdded (EntryAddedEvent<E> event)
|
public void entryAdded (EntryAddedEvent<E> event)
|
||||||
{
|
{
|
||||||
if (event.getName().equals(_setName)) {
|
if (event.getName().equals(_setName)) {
|
||||||
E entry = event.getEntry();
|
addEntry(event.getEntry());
|
||||||
int index = _keys.insertSorted(getKey(entry));
|
|
||||||
_table.insertDatum(entry, index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,10 +202,7 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
public void entryRemoved (EntryRemovedEvent<E> event)
|
public void entryRemoved (EntryRemovedEvent<E> event)
|
||||||
{
|
{
|
||||||
if (event.getName().equals(_setName)) {
|
if (event.getName().equals(_setName)) {
|
||||||
Comparable<?> key = event.getKey();
|
removeKey(event.getKey());
|
||||||
int index = _keys.indexOf(key);
|
|
||||||
_keys.remove(index);
|
|
||||||
_table.removeDatum(index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +212,18 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
if (event.getName().equals(_setName)) {
|
if (event.getName().equals(_setName)) {
|
||||||
E entry = event.getEntry();
|
E entry = event.getEntry();
|
||||||
int index = _keys.indexOf(entry.getKey());
|
int index = _keys.indexOf(entry.getKey());
|
||||||
_table.updateDatum(entry, index);
|
if (index != -1) {
|
||||||
|
// We have it, so either update or remove
|
||||||
|
if (_entryFilter == null || _entryFilter.apply(entry)) {
|
||||||
|
_table.updateDatum(entry, index);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
removeKey(entry.getKey());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We DON'T have it, so try to add it in case we care about it
|
||||||
|
addEntry(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +247,26 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
protected void refreshData ()
|
protected void refreshData ()
|
||||||
{
|
{
|
||||||
_keys = new ComparableArrayList<Comparable<Object>>();
|
_keys = new ComparableArrayList<Comparable<Object>>();
|
||||||
@SuppressWarnings("unchecked") E[] entries = (E[])new DSet.Entry[_set.size()];
|
E[] entries;
|
||||||
_set.toArray(entries);
|
|
||||||
for (int ii = 0; ii < entries.length; ii++) {
|
if (_entryFilter == null) {
|
||||||
_keys.insertSorted(getKey(entries[ii]));
|
@SuppressWarnings("unchecked") E[] tmp = (E[])new DSet.Entry[_set.size()];
|
||||||
|
entries = tmp;
|
||||||
|
_set.toArray(entries);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Do some shuffling to get out a filtered array.
|
||||||
|
Iterator<E> itr = Iterators.filter(_set.iterator(), _entryFilter);
|
||||||
|
ArrayList<E> list = Lists.newArrayList();
|
||||||
|
Iterators.addAll(list, itr);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") E[] tmp = (E[])new DSet.Entry[list.size()];
|
||||||
|
entries = tmp;
|
||||||
|
list.toArray(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (E entry : entries) {
|
||||||
|
_keys.insertSorted(getKey(entry));
|
||||||
}
|
}
|
||||||
_table.setData(entries); // this works because DSet itself is sorted
|
_table.setData(entries); // this works because DSet itself is sorted
|
||||||
}
|
}
|
||||||
@@ -213,6 +283,9 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
/** The name of the set in that object. */
|
/** The name of the set in that object. */
|
||||||
protected String _setName;
|
protected String _setName;
|
||||||
|
|
||||||
|
/** An optional predicate to decide whether actually care about displaying a given entry. */
|
||||||
|
protected Predicate<E> _entryFilter;
|
||||||
|
|
||||||
/** The set itself. */
|
/** The set itself. */
|
||||||
protected DSet<E> _set;
|
protected DSet<E> _set;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// Narya library - tools for developing networked games
|
||||||
|
// Copyright (C) 2002-2009 Three Rings Design, Inc., All Rights Reserved
|
||||||
|
// http://www.threerings.net/code/narya/
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library 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
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
package com.threerings.admin.client;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTabbedPane;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import com.samskivert.util.Logger;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.samskivert.swing.ObjectEditorTable;
|
||||||
|
|
||||||
|
import com.threerings.presents.dobj.DObject;
|
||||||
|
import com.threerings.presents.dobj.DSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows simple editing of DSets within a distributed object and easily groups entries into tabs
|
||||||
|
* based on the content of some field.
|
||||||
|
*/
|
||||||
|
public class TabbedDSetEditor<E extends DSet.Entry> extends JPanel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A set of tabs containing DSetEditors grouping entries by the String value stored in
|
||||||
|
* a given field of the Entry.
|
||||||
|
*/
|
||||||
|
public TabbedDSetEditor (
|
||||||
|
DObject setter, String setName, Class<?> entryClass,
|
||||||
|
String[] editableFields, ObjectEditorTable.FieldInterpreter interp, String groupField)
|
||||||
|
{
|
||||||
|
DSet<E> set = setter.getSet(setName);
|
||||||
|
|
||||||
|
Field field;
|
||||||
|
|
||||||
|
try {
|
||||||
|
field = entryClass.getField(groupField);
|
||||||
|
} catch (NoSuchFieldException nsfe) {
|
||||||
|
throw new IllegalArgumentException(Logger.format(
|
||||||
|
"Group field not found in prototype class!",
|
||||||
|
"proto", entryClass, "groupField", groupField));
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<String> groups = Sets.newHashSet();
|
||||||
|
try {
|
||||||
|
for (E entry : set) {
|
||||||
|
groups.add(StringUtil.toString(field.get(entry)));
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException iae) {
|
||||||
|
throw new IllegalArgumentException(Logger.format(
|
||||||
|
"Could not access group field on entry", "groupField", groupField, iae));
|
||||||
|
}
|
||||||
|
|
||||||
|
JTabbedPane tabs = new JTabbedPane();
|
||||||
|
add(tabs);
|
||||||
|
|
||||||
|
for (String group : groups) {
|
||||||
|
tabs.addTab(group, new DSetEditor<E>(setter, setName, entryClass, editableFields,
|
||||||
|
interp, createPredicate(field, group)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Predicate<E> createPredicate (final Field field, final String group)
|
||||||
|
{
|
||||||
|
return new Predicate<E>() {
|
||||||
|
public boolean apply (E entry) {
|
||||||
|
String val = null;
|
||||||
|
try {
|
||||||
|
val = StringUtil.toString(field.get(entry));
|
||||||
|
} catch (IllegalAccessException iae) {
|
||||||
|
// Badness, but let's just compare to the null string and be done
|
||||||
|
}
|
||||||
|
|
||||||
|
return group.equals(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user