/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * 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 2 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, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package org.andork.swing; import javax.swing.RowFilter; import javax.swing.RowFilter.Entry; /** * <code>RowAnnotator</code> is used to annotate entries from the model with * some object. The view may customize the rendering of an entry based upon its * annotation. For example, a <code>RowAnnotator</code> associated with a * <code>JTable</code> might annotate rows with invalid data entries with an * error messages. The meaning of <em>entry</em> depends on the component type. * For example, when a filter is associated with a <code>JTable</code>, an entry * corresponds to a row; when associated with a <code>JTree</code>, an entry * corresponds to a node. * <p> * Subclasses must override the <code>annotate</code> method to annotate a given * entry. The <code>Entry</code> argument can be used to obtain the values in * each of the columns in that entry. The following example shows an * <code>annotate</code> method that annotates entries with a count of how many * values start with the string "a": * * <pre> * RowAnnotator<Object, Object, Integer> startsWithAAnnotator = new RowAnnotator<Object, Object, Integer>() { * public Integer annotate(Entry<? extends Object, ? extends Object> entry) { * int count = 0; * * for (int i = entry.getValueCount() - 1; i >= 0; i--) { * if (entry.getStringValue(i).startsWith("a")) { * count++; * } * } * return count; * } * }; * </pre> * * @param <M> * the type of the model; for example <code>PersonModel</code> * @param <I> * the type of the identifier; when using * <code>AnnotatingTableRowSorter</code> this will be * <code>Integer</code> * @param <A> * the type of the annotation * @see AnnotatingRowSorter */ public abstract class RowAnnotator<M, I> { private static class FilterAnnotator<M, I> extends RowAnnotator<M, I> { private final RowFilter<M, I>[] filters; @SuppressWarnings("unchecked") public FilterAnnotator(RowFilter<M, I>... filters) { super(); this.filters = filters; } @Override public RowFilter<M, I> annotate(Entry<? extends M, ? extends I> entry) { int resultCount = 0; for (RowFilter<M, I> filter : filters) { if (filter.include(entry)) { return filter; } } return null; } } public static <M, I> RowAnnotator<M, I> filterAnnotator(RowFilter<M, I>... filters) { return new FilterAnnotator<M, I>(filters); } /** * Returns a non-null {@code A} if the specified entry should be annotated; * returns {@code null} if the entry should not be annotated. * <p> * The <code>entry</code> argument is valid only for the duration of the * invocation. Using <code>entry</code> after the call returns results in * undefined behavior. * * @param entry * a non-<code>null</code> object that wraps the underlying * object from the model * @return a non-null {@code A} if the entry should be annotated */ public abstract Object annotate(Entry<? extends M, ? extends I> entry); }