All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jdesktop.swingx.decorator.AbstractHighlighter Maven / Gradle / Ivy

The newest version!
/*
 * $Id: AbstractHighlighter.java 3927 2011-02-22 16:34:11Z kleopatra $
 *
 * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.jdesktop.swingx.decorator;

import java.awt.Component;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.jdesktop.swingx.event.WeakEventListenerList;

/**
 * Abstract Highlighter implementation which manages change 
 * notification and supports conditional highlighting. 
 * Subclasses are required to fire ChangeEvents on internal changes which might
 * effect the highlight. The HighlightPredicate controls whether or not
 * a highlight should be applied for the given ComponentAdapter, 
 * subclasses must guarantee to respect its decision. 
 * 

* * Concrete custom implementations should focus on a single (or few) visual * attribute to highlight. This allows easy re-use by composition. F.i. a custom * FontHighlighter: * *


 * public static class FontHighlighter extends AbstractHighlighter {
 * 
 *     private Font font;
 * 
 *     public FontHighlighter(HighlightPredicate predicate, Font font) {
 *         super(predicate);
 *         setFont(font);
 *     }
 * 
 *     @Override
 *     protected Component doHighlight(Component component,
 *             ComponentAdapter adapter) {
 *         component.setFont(font);
 *         return component;
 *     }
 *     
 *     public final void setFont(Font font) {
 *        if (equals(font, this.font)) return;
 *        this.font = font;
 *        fireStateChanged();
 *     }
 *     
 * 
 * }
 * 
 * 
* * Client code can combine the effect with a f.i. Color decoration, and use a * shared HighlightPredicate to apply both for the same condition. * *

 * HighlightPredicate predicate = new HighlightPredicate() {
 *     public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
 *         Object value = adapter.getFilteredValueAt(adapter.row, adapter.column);
 *         return (value instanceof Number) && ((Number) value).intValue() < 0;
 *     }
 * };
 * table.setHighlighters(
 *         new ColorHighlighter(predicate, Color.RED, null),
 *         new FontHighlighter(predicate, myBoldFont));
 * 
* * @author Jeanette Winzenburg * * @see HighlightPredicate * @see org.jdesktop.swingx.renderer.ComponentProvider */ public abstract class AbstractHighlighter implements Highlighter { /** * Only one ChangeEvent is needed per model instance since the * event's only (read-only) state is the source property. The source * of events generated here is always "this". */ private transient ChangeEvent changeEvent; /** The listeners waiting for model changes. */ protected WeakEventListenerList listenerList = new WeakEventListenerList(); /** the HighlightPredicate to use. */ private HighlightPredicate predicate; /** * Instantiates a Highlighter with default HighlightPredicate. * * @see #setHighlightPredicate(HighlightPredicate) */ public AbstractHighlighter() { this(null); } /** * Instantiates a Highlighter with the given * HighlightPredicate.

* * @param predicate the HighlightPredicate to use. * * @see #setHighlightPredicate(HighlightPredicate) */ public AbstractHighlighter(HighlightPredicate predicate) { setHighlightPredicate(predicate); } /** * Set the HighlightPredicate used to decide whether a cell should * be highlighted. If null, sets the predicate to HighlightPredicate.ALWAYS. * * The default value is HighlightPredicate.ALWAYS. * * @param predicate the HighlightPredicate to use. */ public void setHighlightPredicate(HighlightPredicate predicate) { if (predicate == null) { predicate = HighlightPredicate.ALWAYS; } if (areEqual(predicate, getHighlightPredicate())) return; this.predicate = predicate; fireStateChanged(); } /** * Returns the HighlightPredicate used to decide whether a cell * should be highlighted. Guaranteed to be never null. * * @return the HighlightPredicate to use, never null. */ public HighlightPredicate getHighlightPredicate() { return predicate; } //----------------------- implement predicate respecting highlight /** * {@inheritDoc} * * This calls doHighlight to apply the decoration if both HighlightPredicate * isHighlighted and canHighlight return true. Returns the undecorated component otherwise. * * @param component the cell renderer component that is to be decorated * @param adapter the ComponentAdapter for this decorate operation * * @see #canHighlight(Component, ComponentAdapter) * @see #doHighlight(Component, ComponentAdapter) * @see #getHighlightPredicate() */ @Override public Component highlight(Component component, ComponentAdapter adapter) { if (canHighlight(component, adapter) && getHighlightPredicate().isHighlighted(component, adapter)) { component = doHighlight(component, adapter); } return component; } /** * Subclasses may override to further limit the highlighting based * on Highlighter state, f.i. a PainterHighlighter can only be applied * to PainterAware components.

* * This implementation returns true always. * * @param component * @param adapter * @return a boolean indication if the adapter can be highlighted based * general state. This implementation returns true always. */ protected boolean canHighlight(Component component, ComponentAdapter adapter) { return true; } /** * Apply the highlights. * * @param component the cell renderer component that is to be decorated * @param adapter the ComponentAdapter for this decorate operation * * @see #highlight(Component, ComponentAdapter) */ protected abstract Component doHighlight(Component component, ComponentAdapter adapter); /** * Returns true if the to objects are either both null or equal * each other. * * @param oneItem one item * @param anotherItem another item * @return true if both are null or equal other, false otherwise. */ protected boolean areEqual(Object oneItem, Object anotherItem) { if ((oneItem == null) && (anotherItem == null)) return true; if (anotherItem != null) { return anotherItem.equals(oneItem); } return false; } //------------------------ implement Highlighter change notification /** * Adds a ChangeListener. ChangeListeners are * notified after changes of any attribute. * * @param l the ChangeListener to add * @see #removeChangeListener */ @Override public final void addChangeListener(ChangeListener l) { listenerList.add(ChangeListener.class, l); } /** * Removes a ChangeListenere. * * @param l the ChangeListener to remove * @see #addChangeListener */ @Override public final void removeChangeListener(ChangeListener l) { listenerList.remove(ChangeListener.class, l); } /** * Returns an array of all the change listeners * registered on this Highlighter. * * @return all of this model's ChangeListeners * or an empty * array if no change listeners are currently registered * * @see #addChangeListener * @see #removeChangeListener * * @since 1.4 */ @Override public final ChangeListener[] getChangeListeners() { return listenerList.getListeners(ChangeListener.class); } /** * Notifies registered ChangeListeners about * state changes.

* * Note: subclasses should be polite and implement any property * setters to fire only if the property is really changed. * */ protected final void fireStateChanged() { Object[] listeners = listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ChangeListener.class) { if (changeEvent == null) { changeEvent = new ChangeEvent(this); } ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy