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

org.jdesktop.swingx.event.CompoundFocusListener Maven / Gradle / Ivy

/*
 * 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.
 * 

* * F.i, client code which wants to get notified if focus enters/exits the hierarchy below * panel would install the compound focus listener like: * *

 * 
 *         // add some components inside
 *         panel.add(new JTextField("something to .... focus"));
 *         panel.add(new JXDatePicker(new Date()));
 *         JComboBox combo = new JComboBox(new Object[] {"dooooooooo", 1, 2, 3, 4 });
 *         combo.setEditable(true);
 *         panel.add(new JButton("something else to ... focus"));
 *         panel.add(combo);
 *         panel.setBorder(new TitledBorder("has focus dispatcher"));
 *         // 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);    
 *         
 * 
 * 
* * 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.

* * Note: 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.

* * 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.

* * @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.

* * @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; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy