Complexity++!
Turns out when I went to use TabbedDSetEditor in my scary real-world application instead of nice small test cases, I wanted to do fancier stuff where I hide certain fields for some groups, etc. Break things up into chunks so it's possible to override the various exciting bits of functionality and do things like that. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5781 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -95,7 +95,7 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
||||||
ObjectEditorTable.FieldInterpreter interp)
|
ObjectEditorTable.FieldInterpreter interp)
|
||||||
{
|
{
|
||||||
this(setter, setName, entryClass, editableFields, interp, null);
|
this(setter, setName, entryClass, editableFields, interp, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,11 +106,12 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
* @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.
|
||||||
|
* @param displayFields The fields to display, or null for all.
|
||||||
* @param entryFilter The Predicate to use.
|
* @param entryFilter The Predicate to use.
|
||||||
*/
|
*/
|
||||||
public DSetEditor (
|
public DSetEditor (
|
||||||
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
||||||
ObjectEditorTable.FieldInterpreter interp, Predicate<E> entryFilter)
|
ObjectEditorTable.FieldInterpreter interp, String[] displayFields, Predicate<E> entryFilter)
|
||||||
{
|
{
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ public class DSetEditor<E extends DSet.Entry> extends JPanel
|
|||||||
_set = _setter.getSet(setName);
|
_set = _setter.getSet(setName);
|
||||||
_entryFilter = entryFilter;
|
_entryFilter = entryFilter;
|
||||||
|
|
||||||
_table = new ObjectEditorTable(entryClass, editableFields, interp);
|
_table = new ObjectEditorTable(entryClass, editableFields, interp, displayFields);
|
||||||
|
|
||||||
add(new JScrollPane(_table), BorderLayout.CENTER);
|
add(new JScrollPane(_table), BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
package com.threerings.admin.client;
|
package com.threerings.admin.client;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.HashSet;
|
import java.util.Comparator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.JTabbedPane;
|
||||||
@@ -30,7 +31,9 @@ import javax.swing.JTabbedPane;
|
|||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import com.samskivert.util.Comparators;
|
||||||
import com.samskivert.util.Logger;
|
import com.samskivert.util.Logger;
|
||||||
|
import com.samskivert.util.QuickSort;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.samskivert.swing.ObjectEditorTable;
|
import com.samskivert.swing.ObjectEditorTable;
|
||||||
@@ -44,58 +47,135 @@ import com.threerings.presents.dobj.DSet;
|
|||||||
*/
|
*/
|
||||||
public class TabbedDSetEditor<E extends DSet.Entry> extends JPanel
|
public class TabbedDSetEditor<E extends DSet.Entry> extends JPanel
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Used to divide various entires into different groups.
|
||||||
|
*/
|
||||||
|
public static abstract class EntryGrouper<E extends DSet.Entry>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Record & return the group for a given entry.
|
||||||
|
*/
|
||||||
|
public String getGroup (E entry)
|
||||||
|
{
|
||||||
|
String group = computeGroup(entry);
|
||||||
|
_allGroups.add(group);
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses implement the actual logic to figure out a group name from an entry here.
|
||||||
|
*/
|
||||||
|
protected abstract String computeGroup (E entry);
|
||||||
|
|
||||||
|
protected Predicate<E> getPredicate (final String group) {
|
||||||
|
return new Predicate<E>() {
|
||||||
|
public boolean apply (E entry) {
|
||||||
|
return group.equals(getGroup(entry));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grinds through the
|
||||||
|
* @param entries
|
||||||
|
*/
|
||||||
|
public void computeGroups (Iterable<E> entries) {
|
||||||
|
for (E entry : entries) {
|
||||||
|
getGroup(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the groups we know about, ordered as they should be displayed.
|
||||||
|
*/
|
||||||
|
public String[] getAllGroups () {
|
||||||
|
String[] list = _allGroups.toArray(new String[_allGroups.size()]);
|
||||||
|
QuickSort.sort(list, getComparator());
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Comparator<Object> getComparator () {
|
||||||
|
return Comparators.LEXICAL_CASE_INSENSITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Set<String> _allGroups = Sets.newHashSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FieldGrouper<E extends DSet.Entry> extends EntryGrouper<E>
|
||||||
|
{
|
||||||
|
public FieldGrouper (String fieldName, Class<?> entryClass) {
|
||||||
|
try {
|
||||||
|
_field = entryClass.getField(fieldName);
|
||||||
|
} catch (NoSuchFieldException nsfe) {
|
||||||
|
throw new IllegalArgumentException(Logger.format(
|
||||||
|
"Group field not found in prototype class!",
|
||||||
|
"proto", entryClass, "groupField", fieldName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String computeGroup (E entry) {
|
||||||
|
try {
|
||||||
|
return StringUtil.toString(_field.get(entry));
|
||||||
|
} catch (IllegalAccessException iae) {
|
||||||
|
// This ain't good, but let's soldier on.
|
||||||
|
return "<bogus>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final Field _field;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to make an edittor that groups based on the values of a given field.
|
||||||
|
*/
|
||||||
|
public TabbedDSetEditor (
|
||||||
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
||||||
|
ObjectEditorTable.FieldInterpreter interp, String groupField)
|
||||||
|
{
|
||||||
|
this(setter, setName, entryClass, editableFields, interp,
|
||||||
|
new FieldGrouper<E>(groupField, entryClass));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of tabs containing DSetEditors grouping entries by the String value stored in
|
* A set of tabs containing DSetEditors grouping entries by the String value stored in
|
||||||
* a given field of the Entry.
|
* a given field of the Entry.
|
||||||
*/
|
*/
|
||||||
public TabbedDSetEditor (
|
public TabbedDSetEditor (
|
||||||
DObject setter, String setName, Class<?> entryClass,
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
||||||
String[] editableFields, ObjectEditorTable.FieldInterpreter interp, String groupField)
|
ObjectEditorTable.FieldInterpreter interp, EntryGrouper<E> grouper)
|
||||||
{
|
{
|
||||||
DSet<E> set = setter.getSet(setName);
|
grouper.computeGroups(setter.<E>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();
|
JTabbedPane tabs = new JTabbedPane();
|
||||||
add(tabs);
|
add(tabs);
|
||||||
|
|
||||||
|
String[] groups = grouper.getAllGroups();
|
||||||
for (String group : groups) {
|
for (String group : groups) {
|
||||||
tabs.addTab(group, new DSetEditor<E>(setter, setName, entryClass, editableFields,
|
tabs.addTab(group,
|
||||||
interp, createPredicate(field, group)));
|
createEditor(setter, setName, entryClass, editableFields, interp, grouper, group));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Predicate<E> createPredicate (final Field field, final String group)
|
/**
|
||||||
|
* Creates a DSetEditor for displaying the given group.
|
||||||
|
*/
|
||||||
|
protected DSetEditor<E> createEditor (
|
||||||
|
DObject setter, String setName, Class<?> entryClass, String[] editableFields,
|
||||||
|
ObjectEditorTable.FieldInterpreter interp, EntryGrouper<E> grouper, String group)
|
||||||
{
|
{
|
||||||
return new Predicate<E>() {
|
return new DSetEditor<E>(setter, setName, entryClass, editableFields,
|
||||||
public boolean apply (E entry) {
|
interp, getDisplayFields(group), grouper.getPredicate(group));
|
||||||
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);
|
/**
|
||||||
}
|
* Choose which fields to display for the given group.
|
||||||
};
|
*/
|
||||||
|
protected String[] getDisplayFields (String group)
|
||||||
|
{
|
||||||
|
return null; // Override to display only a subset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user