Package org.jdesktop.swingx.event

Source Code of org.jdesktop.swingx.event.CompoundFocusListener

/*
* Created on 23.04.2009
*
*/
package org.jdesktop.swingx.event;

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JComponent;

import org.jdesktop.beans.AbstractBean;
import org.jdesktop.swingx.SwingXUtilities;
import org.jdesktop.swingx.util.Contract;

/**
* An convenience class which maps focusEvents received
* from a container hierarchy to a bound read-only property. Registered
* PropertyChangeListeners are notified if the focus is transfered into/out of
* the hierarchy of a given root.
* <p>
*
* F.i, client code which wants to get notified if focus enters/exits the hierarchy below
* panel would install the compound focus listener like:
*
* <pre>
* <code>
*         // add some components inside
*         panel.add(new JTextField(&quot;something to .... focus&quot;));
*         panel.add(new JXDatePicker(new Date()));
*         JComboBox combo = new JComboBox(new Object[] {&quot;dooooooooo&quot;, 1, 2, 3, 4 });
*         combo.setEditable(true);
*         panel.add(new JButton(&quot;something else to ... focus&quot;));
*         panel.add(combo);
*         panel.setBorder(new TitledBorder(&quot;has focus dispatcher&quot;));
*         // register the compound dispatcher
*         CompoundFocusListener report = new CompoundFocusListener(panel);
*         PropertyChangeListener l = new PropertyChangeListener() {
*
*             public void propertyChange(PropertyChangeEvent evt) {
*                 // do something useful here
*                
*             }};
*         report.addPropertyChangeListener(l);   
*        
* </code>
* </pre>
*
* PENDING JW: change of current instance of KeyboardFocusManager?
*
*/
public class CompoundFocusListener extends AbstractBean {
   
    /** the root of the component hierarchy.
     * PENDING JW: weak reference and auto-release listener?
     */
    private JComponent root;
    /** PropertyChangeListener registered with the current keyboardFocusManager. */
    private PropertyChangeListener managerListener;
    private boolean focused;

    /**
     * Instantiates a CompoundFocusListener on the component hierarchy below the given
     * component.
     *
     * @param root the root of a component hierarchy
     * @throws NullPointerException if the root is null
     */
    public CompoundFocusListener(JComponent root) {
        this.root = Contract.asNotNull(root, "root must not be null");
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        addManagerListener(manager);
        permanentFocusOwnerChanged(manager.getPermanentFocusOwner());
    }


    /**
     * Return true if the root or any of its descendants is focused. This is a
     * read-only bound property, that is property change event is fired if focus
     * is transfered into/out of root's hierarchy.
     *
     * @return a boolean indicating whether or not any component in the
     *         container hierarchy below root is permanent focus owner.
     */
    public boolean isFocused() {
        return focused;
    }

    /**
     * Releases all listeners and internal references.<p>
     *
     * <b>Note</b>: this instance must not be used after calling this method.
     * 
     */
    public void release() {
        removeManagerListener(KeyboardFocusManager.getCurrentKeyboardFocusManager());
        removeAllListeners();
        this.root = null;
    }
   
    /**
     * Removes all property change listeners which are registered with this instance.
     */
    private void removeAllListeners() {
        for (PropertyChangeListener l : getPropertyChangeListeners()) {
            removePropertyChangeListener(l);
        }
    }

    /**
     * Updates focused property depending on whether or not the given component
     * is below the root's hierarchy. <p>
     *
     * Note: Does nothing if the component is null. This might not be entirely correct,
     * but property change events from the focus manager come in pairs, with only
     * one of the new/old value not-null.
     *
     * @param focusOwner the component with is the current focusOwner.
     */
    protected void permanentFocusOwnerChanged(Component focusOwner) {
        if (focusOwner == null) return;
        setFocused(SwingXUtilities.isDescendingFrom(focusOwner, root));
    }
   
    private void setFocused(boolean focused) {
        boolean old = isFocused();
        this.focused = focused;
        firePropertyChange("focused", old, isFocused());
    }

   
    /**
     * Adds all listeners to the given KeyboardFocusManager. <p>
     *
     * @param manager the KeyboardFocusManager to add internal listeners to.
     * @see #removeManagerListener(KeyboardFocusManager)
     */
    private void addManagerListener(KeyboardFocusManager manager) {
        manager.addPropertyChangeListener("permanentFocusOwner", getManagerListener());
    }

    /**
     * Removes all listeners this instance has installed from the given KeyboardFocusManager.<p>
     *
     * @param manager the KeyboardFocusManager to remove internal listeners from.
     * @see #addManagerListener(KeyboardFocusManager)
     */
    private void removeManagerListener(KeyboardFocusManager manager) {
        manager.removePropertyChangeListener("permanentFocusOwner", getManagerListener());
    }

    /**
     * Lazily creates and returns a property change listener to be registered on the
     * KeyboardFocusManager.
     *
     * @return a property change listener to be registered on the KeyboardFocusManager.
     */
    private PropertyChangeListener getManagerListener() {
        if (managerListener == null) {
            managerListener = new PropertyChangeListener() {

                public void propertyChange(PropertyChangeEvent evt) {
                    if ("permanentFocusOwner".equals(evt.getPropertyName())) {
                        permanentFocusOwnerChanged((Component) evt.getNewValue());
                    }
                   
                }};
        }
        return managerListener;
    }


}
TOP

Related Classes of org.jdesktop.swingx.event.CompoundFocusListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.