You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.5 KiB
158 lines
4.5 KiB
/*
|
|
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
package javax.swing;
|
|
|
|
import java.beans.PropertyChangeEvent;
|
|
import java.beans.PropertyChangeListener;
|
|
import java.io.*;
|
|
import java.lang.ref.WeakReference;
|
|
import java.lang.ref.ReferenceQueue;
|
|
|
|
/**
|
|
* A package-private PropertyChangeListener which listens for
|
|
* property changes on an Action and updates the properties
|
|
* of an ActionEvent source.
|
|
* <p>
|
|
* Subclasses must override the actionPropertyChanged method,
|
|
* which is invoked from the propertyChange method as long as
|
|
* the target is still valid.
|
|
* </p>
|
|
* <p>
|
|
* WARNING WARNING WARNING WARNING WARNING WARNING:<br>
|
|
* Do NOT create an annonymous inner class that extends this! If you do
|
|
* a strong reference will be held to the containing class, which in most
|
|
* cases defeats the purpose of this class.
|
|
*
|
|
* @param T the type of JComponent the underlying Action is attached to
|
|
*
|
|
* @author Georges Saab
|
|
* @see AbstractButton
|
|
*/
|
|
abstract class ActionPropertyChangeListener<T extends JComponent>
|
|
implements PropertyChangeListener, Serializable {
|
|
private static ReferenceQueue<JComponent> queue;
|
|
|
|
// WeakReference's aren't serializable.
|
|
private transient OwnedWeakReference<T> target;
|
|
// The Component's that reference an Action do so through a strong
|
|
// reference, so that there is no need to check for serialized.
|
|
private Action action;
|
|
|
|
private static ReferenceQueue<JComponent> getQueue() {
|
|
synchronized(ActionPropertyChangeListener.class) {
|
|
if (queue == null) {
|
|
queue = new ReferenceQueue<JComponent>();
|
|
}
|
|
}
|
|
return queue;
|
|
}
|
|
|
|
public ActionPropertyChangeListener(T c, Action a) {
|
|
super();
|
|
setTarget(c);
|
|
this.action = a;
|
|
}
|
|
|
|
/**
|
|
* PropertyChangeListener method. If the target has been gc'ed this
|
|
* will remove the <code>PropertyChangeListener</code> from the Action,
|
|
* otherwise this will invoke actionPropertyChanged.
|
|
*/
|
|
public final void propertyChange(PropertyChangeEvent e) {
|
|
T target = getTarget();
|
|
if (target == null) {
|
|
getAction().removePropertyChangeListener(this);
|
|
} else {
|
|
actionPropertyChanged(target, getAction(), e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Invoked when a property changes on the Action and the target
|
|
* still exists.
|
|
*/
|
|
protected abstract void actionPropertyChanged(T target, Action action,
|
|
PropertyChangeEvent e);
|
|
|
|
private void setTarget(T c) {
|
|
ReferenceQueue<JComponent> queue = getQueue();
|
|
// Check to see whether any old buttons have
|
|
// been enqueued for GC. If so, look up their
|
|
// PCL instance and remove it from its Action.
|
|
OwnedWeakReference<?> r;
|
|
while ((r = (OwnedWeakReference)queue.poll()) != null) {
|
|
ActionPropertyChangeListener<?> oldPCL = r.getOwner();
|
|
Action oldAction = oldPCL.getAction();
|
|
if (oldAction!=null) {
|
|
oldAction.removePropertyChangeListener(oldPCL);
|
|
}
|
|
}
|
|
this.target = new OwnedWeakReference<T>(c, queue, this);
|
|
}
|
|
|
|
public T getTarget() {
|
|
if (target == null) {
|
|
// Will only happen if serialized and real target was null
|
|
return null;
|
|
}
|
|
return this.target.get();
|
|
}
|
|
|
|
public Action getAction() {
|
|
return action;
|
|
}
|
|
|
|
private void writeObject(ObjectOutputStream s) throws IOException {
|
|
s.defaultWriteObject();
|
|
s.writeObject(getTarget());
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private void readObject(ObjectInputStream s)
|
|
throws IOException, ClassNotFoundException {
|
|
s.defaultReadObject();
|
|
T target = (T)s.readObject();
|
|
if (target != null) {
|
|
setTarget(target);
|
|
}
|
|
}
|
|
|
|
|
|
private static class OwnedWeakReference<U extends JComponent> extends
|
|
WeakReference<U> {
|
|
private ActionPropertyChangeListener<?> owner;
|
|
|
|
OwnedWeakReference(U target, ReferenceQueue<? super U> queue,
|
|
ActionPropertyChangeListener<?> owner) {
|
|
super(target, queue);
|
|
this.owner = owner;
|
|
}
|
|
|
|
public ActionPropertyChangeListener<?> getOwner() {
|
|
return owner;
|
|
}
|
|
}
|
|
}
|