package com.onaro.util.jfc; import java.awt.Component; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JComponent; /** * Factor that provides a Highlight implementation to JComponents. * The implementation adds an isHighlighted property to the components. */ public enum Highlighter { // Our single instance INSTANCE; public static boolean debug = false; /** * Property added to JComponent to store its highlight state. */ private static final String PROP_IS_HIGHLIGHTED = "isHighlighted"; //$NON-NLS-1$ /** * Returns true if this component is highlighted. * * @param comp the component to test. * @return true if this component is highlighted. */ public static boolean isHighlighted(JComponent comp) { return isHighlighted(comp, false); } /** * Returns true if this component is highlighted. * * @param comp the component to test. * @param recurse if true then test the children recursively if they are highlighted. Return as soon as you find one that is. * @return true if this component is highlighted. */ public static boolean isHighlighted(JComponent comp, boolean recurse) { if(comp == null) { return(false); } if(Boolean.TRUE.equals(comp.getClientProperty(PROP_IS_HIGHLIGHTED))) { return true; } if(!recurse) { return false; } return hasHighlightedChildren(comp); } /** * Returns true if this component has any highlighted children. * * @param comp the component to test. * @return true if this component has any highlighted children. */ public static boolean hasHighlightedChildren(JComponent comp) { if(comp == null) { return(false); } for(Component childComp : comp.getComponents()) { if(childComp instanceof JComponent) { if(isHighlighted((JComponent)childComp, true)) { return true; } } } return false; } /** * Sets highlight property of a component. * @param comp * @param isHighlighted */ public static void setHighlighted(JComponent comp, boolean isHighlighted) { comp.putClientProperty(PROP_IS_HIGHLIGHTED, Boolean.valueOf(isHighlighted)); } /** * Adds listener to component that listens for change to highlight property. * @param comp * @param listener */ public static void addListener(JComponent comp, PropertyChangeListener listener) { comp.addPropertyChangeListener (PROP_IS_HIGHLIGHTED, listener); } /** * Add a listener that sets the highlight status of the given field based on the highlight status changes for the given child component. This * will cause the given container component to fire/forward the event. */ public static void addForwardingListener(final IHighlighting field, final JComponent comp) { final JComponent fieldComp = (JComponent)field; comp.addPropertyChangeListener(PROP_IS_HIGHLIGHTED, new PropertyChangeListener() { @Override public void propertyChange (PropertyChangeEvent event) { boolean compoundIsHighlighted = field.isHighlighted(); // If the compound field highlight is different that the component if(!Boolean.valueOf(compoundIsHighlighted).equals(event.getNewValue())) { boolean anyFieldIsHighlighted = Highlighter.hasHighlightedChildren(fieldComp); // If the compound field highlight status does not match the children if(compoundIsHighlighted != anyFieldIsHighlighted) { // Set the highlight status of the compound field to match the children. field.setHighlight(anyFieldIsHighlighted); // Notify anyone listening fieldComp.firePropertyChange(PROP_IS_HIGHLIGHTED, compoundIsHighlighted, anyFieldIsHighlighted); } } } }); } }