/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package javax.swing;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.
Component;
import java.awt.
Container;
import java.awt.
Window;
import java.beans.
PropertyChangeListener;
import java.beans.
PropertyChangeEvent;
import java.io.
Serializable;
/**
* @author Dave Moore
*/
@
SuppressWarnings("serial")
class
AncestorNotifier implements
ComponentListener,
PropertyChangeListener,
Serializable
{
transient
Component firstInvisibleAncestor;
EventListenerList listenerList = new
EventListenerList();
JComponent root;
AncestorNotifier(
JComponent root) {
this.
root =
root;
addListeners(
root, true);
}
void
addAncestorListener(
AncestorListener l) {
listenerList.
add(
AncestorListener.class,
l);
}
void
removeAncestorListener(
AncestorListener l) {
listenerList.
remove(
AncestorListener.class,
l);
}
AncestorListener[]
getAncestorListeners() {
return
listenerList.
getListeners(
AncestorListener.class);
}
/**
* Notify all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void
fireAncestorAdded(
JComponent source, int
id,
Container ancestor,
Container ancestorParent) {
// Guaranteed to return a non-null array
Object[]
listeners =
listenerList.
getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int
i =
listeners.length-2;
i>=0;
i-=2) {
if (
listeners[
i]==
AncestorListener.class) {
// Lazily create the event:
AncestorEvent ancestorEvent =
new
AncestorEvent(
source,
id,
ancestor,
ancestorParent);
((
AncestorListener)
listeners[
i+1]).
ancestorAdded(
ancestorEvent);
}
}
}
/**
* Notify all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void
fireAncestorRemoved(
JComponent source, int
id,
Container ancestor,
Container ancestorParent) {
// Guaranteed to return a non-null array
Object[]
listeners =
listenerList.
getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int
i =
listeners.length-2;
i>=0;
i-=2) {
if (
listeners[
i]==
AncestorListener.class) {
// Lazily create the event:
AncestorEvent ancestorEvent =
new
AncestorEvent(
source,
id,
ancestor,
ancestorParent);
((
AncestorListener)
listeners[
i+1]).
ancestorRemoved(
ancestorEvent);
}
}
}
/**
* Notify all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
* @see EventListenerList
*/
protected void
fireAncestorMoved(
JComponent source, int
id,
Container ancestor,
Container ancestorParent) {
// Guaranteed to return a non-null array
Object[]
listeners =
listenerList.
getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int
i =
listeners.length-2;
i>=0;
i-=2) {
if (
listeners[
i]==
AncestorListener.class) {
// Lazily create the event:
AncestorEvent ancestorEvent =
new
AncestorEvent(
source,
id,
ancestor,
ancestorParent);
((
AncestorListener)
listeners[
i+1]).
ancestorMoved(
ancestorEvent);
}
}
}
void
removeAllListeners() {
removeListeners(
root);
}
void
addListeners(
Component ancestor, boolean
addToFirst) {
Component a;
firstInvisibleAncestor = null;
for (
a =
ancestor;
firstInvisibleAncestor == null;
a =
a.
getParent()) {
if (
addToFirst ||
a !=
ancestor) {
a.
addComponentListener(this);
if (
a instanceof
JComponent) {
JComponent jAncestor = (
JComponent)
a;
jAncestor.
addPropertyChangeListener(this);
}
}
if (!
a.
isVisible() ||
a.
getParent() == null ||
a instanceof
Window) {
firstInvisibleAncestor =
a;
}
}
if (
firstInvisibleAncestor instanceof
Window &&
firstInvisibleAncestor.
isVisible()) {
firstInvisibleAncestor = null;
}
}
void
removeListeners(
Component ancestor) {
Component a;
for (
a =
ancestor;
a != null;
a =
a.
getParent()) {
a.
removeComponentListener(this);
if (
a instanceof
JComponent) {
JComponent jAncestor = (
JComponent)
a;
jAncestor.
removePropertyChangeListener(this);
}
if (
a ==
firstInvisibleAncestor ||
a instanceof
Window) {
break;
}
}
}
public void
componentResized(
ComponentEvent e) {}
public void
componentMoved(
ComponentEvent e) {
Component source =
e.
getComponent();
fireAncestorMoved(
root,
AncestorEvent.
ANCESTOR_MOVED,
(
Container)
source,
source.
getParent());
}
public void
componentShown(
ComponentEvent e) {
Component ancestor =
e.
getComponent();
if (
ancestor ==
firstInvisibleAncestor) {
addListeners(
ancestor, false);
if (
firstInvisibleAncestor == null) {
fireAncestorAdded(
root,
AncestorEvent.
ANCESTOR_ADDED,
(
Container)
ancestor,
ancestor.
getParent());
}
}
}
public void
componentHidden(
ComponentEvent e) {
Component ancestor =
e.
getComponent();
boolean
needsNotify =
firstInvisibleAncestor == null;
if ( !(
ancestor instanceof
Window) ) {
removeListeners(
ancestor.
getParent());
}
firstInvisibleAncestor =
ancestor;
if (
needsNotify) {
fireAncestorRemoved(
root,
AncestorEvent.
ANCESTOR_REMOVED,
(
Container)
ancestor,
ancestor.
getParent());
}
}
public void
propertyChange(
PropertyChangeEvent evt) {
String s =
evt.
getPropertyName();
if (
s!=null && (
s.
equals("parent") ||
s.
equals("ancestor"))) {
JComponent component = (
JComponent)
evt.
getSource();
if (
evt.
getNewValue() != null) {
if (
component ==
firstInvisibleAncestor) {
addListeners(
component, false);
if (
firstInvisibleAncestor == null) {
fireAncestorAdded(
root,
AncestorEvent.
ANCESTOR_ADDED,
component,
component.
getParent());
}
}
} else {
boolean
needsNotify =
firstInvisibleAncestor == null;
Container oldParent = (
Container)
evt.
getOldValue();
removeListeners(
oldParent);
firstInvisibleAncestor =
component;
if (
needsNotify) {
fireAncestorRemoved(
root,
AncestorEvent.
ANCESTOR_REMOVED,
component,
oldParent);
}
}
}
}
}