Path: blob/master/src/java.desktop/share/classes/javax/swing/AncestorNotifier.java
41153 views
/*1* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.swing;262728import javax.swing.event.*;29import java.awt.event.*;3031import java.awt.Component;32import java.awt.Container;33import java.awt.Window;34import java.beans.PropertyChangeListener;35import java.beans.PropertyChangeEvent;3637import java.io.Serializable;383940/**41* @author Dave Moore42*/4344@SuppressWarnings("serial")45class AncestorNotifier implements ComponentListener, PropertyChangeListener, Serializable46{47transient Component firstInvisibleAncestor;48EventListenerList listenerList = new EventListenerList();49JComponent root;5051AncestorNotifier(JComponent root) {52this.root = root;53addListeners(root, true);54}5556void addAncestorListener(AncestorListener l) {57listenerList.add(AncestorListener.class, l);58}5960void removeAncestorListener(AncestorListener l) {61listenerList.remove(AncestorListener.class, l);62}6364AncestorListener[] getAncestorListeners() {65return listenerList.getListeners(AncestorListener.class);66}6768/**69* Notify all listeners that have registered interest for70* notification on this event type. The event instance71* is lazily created using the parameters passed into72* the fire method.73* @see EventListenerList74*/75protected void fireAncestorAdded(JComponent source, int id, Container ancestor, Container ancestorParent) {76// Guaranteed to return a non-null array77Object[] listeners = listenerList.getListenerList();78// Process the listeners last to first, notifying79// those that are interested in this event80for (int i = listeners.length-2; i>=0; i-=2) {81if (listeners[i]==AncestorListener.class) {82// Lazily create the event:83AncestorEvent ancestorEvent =84new AncestorEvent(source, id, ancestor, ancestorParent);85((AncestorListener)listeners[i+1]).ancestorAdded(ancestorEvent);86}87}88}8990/**91* Notify all listeners that have registered interest for92* notification on this event type. The event instance93* is lazily created using the parameters passed into94* the fire method.95* @see EventListenerList96*/97protected void fireAncestorRemoved(JComponent source, int id, Container ancestor, Container ancestorParent) {98// Guaranteed to return a non-null array99Object[] listeners = listenerList.getListenerList();100// Process the listeners last to first, notifying101// those that are interested in this event102for (int i = listeners.length-2; i>=0; i-=2) {103if (listeners[i]==AncestorListener.class) {104// Lazily create the event:105AncestorEvent ancestorEvent =106new AncestorEvent(source, id, ancestor, ancestorParent);107((AncestorListener)listeners[i+1]).ancestorRemoved(ancestorEvent);108}109}110}111/**112* Notify all listeners that have registered interest for113* notification on this event type. The event instance114* is lazily created using the parameters passed into115* the fire method.116* @see EventListenerList117*/118protected void fireAncestorMoved(JComponent source, int id, Container ancestor, Container ancestorParent) {119// Guaranteed to return a non-null array120Object[] listeners = listenerList.getListenerList();121// Process the listeners last to first, notifying122// those that are interested in this event123for (int i = listeners.length-2; i>=0; i-=2) {124if (listeners[i]==AncestorListener.class) {125// Lazily create the event:126AncestorEvent ancestorEvent =127new AncestorEvent(source, id, ancestor, ancestorParent);128((AncestorListener)listeners[i+1]).ancestorMoved(ancestorEvent);129}130}131}132133void removeAllListeners() {134removeListeners(root);135}136137void addListeners(Component ancestor, boolean addToFirst) {138Component a;139140firstInvisibleAncestor = null;141for (a = ancestor;142firstInvisibleAncestor == null;143a = a.getParent()) {144if (addToFirst || a != ancestor) {145a.addComponentListener(this);146147if (a instanceof JComponent) {148JComponent jAncestor = (JComponent)a;149150jAncestor.addPropertyChangeListener(this);151}152}153if (!a.isVisible() || a.getParent() == null || a instanceof Window) {154firstInvisibleAncestor = a;155}156}157if (firstInvisibleAncestor instanceof Window &&158firstInvisibleAncestor.isVisible()) {159firstInvisibleAncestor = null;160}161}162163void removeListeners(Component ancestor) {164Component a;165for (a = ancestor; a != null; a = a.getParent()) {166a.removeComponentListener(this);167if (a instanceof JComponent) {168JComponent jAncestor = (JComponent)a;169jAncestor.removePropertyChangeListener(this);170}171if (a == firstInvisibleAncestor || a instanceof Window) {172break;173}174}175}176177public void componentResized(ComponentEvent e) {}178179public void componentMoved(ComponentEvent e) {180Component source = e.getComponent();181182fireAncestorMoved(root, AncestorEvent.ANCESTOR_MOVED,183(Container)source, source.getParent());184}185186public void componentShown(ComponentEvent e) {187Component ancestor = e.getComponent();188189if (ancestor == firstInvisibleAncestor) {190addListeners(ancestor, false);191if (firstInvisibleAncestor == null) {192fireAncestorAdded(root, AncestorEvent.ANCESTOR_ADDED,193(Container)ancestor, ancestor.getParent());194}195}196}197198public void componentHidden(ComponentEvent e) {199Component ancestor = e.getComponent();200boolean needsNotify = firstInvisibleAncestor == null;201202if ( !(ancestor instanceof Window) ) {203removeListeners(ancestor.getParent());204}205firstInvisibleAncestor = ancestor;206if (needsNotify) {207fireAncestorRemoved(root, AncestorEvent.ANCESTOR_REMOVED,208(Container)ancestor, ancestor.getParent());209}210}211212public void propertyChange(PropertyChangeEvent evt) {213String s = evt.getPropertyName();214215if (s!=null && (s.equals("parent") || s.equals("ancestor"))) {216JComponent component = (JComponent)evt.getSource();217218if (evt.getNewValue() != null) {219if (component == firstInvisibleAncestor) {220addListeners(component, false);221if (firstInvisibleAncestor == null) {222fireAncestorAdded(root, AncestorEvent.ANCESTOR_ADDED,223component, component.getParent());224}225}226} else {227boolean needsNotify = firstInvisibleAncestor == null;228Container oldParent = (Container)evt.getOldValue();229230removeListeners(oldParent);231firstInvisibleAncestor = component;232if (needsNotify) {233fireAncestorRemoved(root, AncestorEvent.ANCESTOR_REMOVED,234component, oldParent);235}236}237}238}239}240241242