001 /* 002 * Created on Oct 8, 2007 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 005 * the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 011 * specific language governing permissions and limitations under the License. 012 * 013 * Copyright @2007-2010 the original author or authors. 014 */ 015 package org.fest.swing.listener; 016 017 import java.awt.AWTEvent; 018 import java.awt.Toolkit; 019 import java.awt.event.AWTEventListener; 020 import java.lang.ref.WeakReference; 021 022 import org.fest.util.VisibleForTesting; 023 024 /** 025 * Understands an event listener that wraps a given <code>{@link AWTEventListener}</code> and: 026 * <ul> 027 * <li>attaches itself to the default toolkit</li> 028 * <li>dispatches any given event to the wrapped listener</li> 029 * <li>removes itself from the default toolkit when the wrapped listener gets garbage-collected</li> 030 * </ul> 031 * 032 * @author Alex Ruiz 033 * @author Yvonne Wang 034 */ 035 public final class WeakEventListener implements AWTEventListener { 036 037 private final WeakReference<AWTEventListener> listenerReference; 038 private final Toolkit toolkit; 039 040 /** 041 * Creates a new <code>{@link WeakEventListener}</code> and adds it to the given <code>{@link Toolkit}</code> using 042 * the given event mask. The created <code>{@link WeakEventListener}</code> simply "decorates" the given 043 * <code>{@link AWTEventListener}</code>. All events dispatched to the <code>{@link WeakEventListener}</code> are 044 * re-routed to the underlying <code>{@link AWTEventListener}</code>. When the underlying 045 * <code>{@link AWTEventListener}</code> is garbage-collected, the <code>{@link WeakEventListener}</code> will remove 046 * itself from the toolkit. 047 * @param toolkit the given AWT <code>Toolkit</code>. 048 * @param listener the underlying listener to wrap. 049 * @param eventMask the event mask to use to attach the <code>WeakEventListener</code> to the toolkit. 050 * @return the created <code>WeakEventListener</code>. 051 */ 052 public static WeakEventListener attachAsWeakEventListener(Toolkit toolkit, AWTEventListener listener, long eventMask) { 053 WeakEventListener l = new WeakEventListener(toolkit, listener); 054 toolkit.addAWTEventListener(l, eventMask); 055 return l; 056 } 057 058 private WeakEventListener(Toolkit toolkit, AWTEventListener listener) { 059 listenerReference = new WeakReference<AWTEventListener>(listener); 060 this.toolkit = toolkit; 061 } 062 063 /** 064 * Returns the underlying listener. 065 * @return the underlying listener. 066 */ 067 public AWTEventListener underlyingListener() { 068 return listenerReference.get(); 069 } 070 071 /** 072 * Dispatches the given event to the wrapped event listener. If the wrapped listener is <code>null</code> 073 * (garbage-collected,) this listener will remove itself from the default toolkit. 074 * @param e the event dispatched in the AWT. 075 */ 076 public void eventDispatched(AWTEvent e) { 077 AWTEventListener listener = listenerReference.get(); 078 if (listener == null) { 079 dispose(); 080 return; 081 } 082 listener.eventDispatched(e); 083 } 084 085 /** Removes itself from the <code>{@link Toolkit}</code> this listener is attached to. */ 086 public void dispose() { 087 toolkit.removeAWTEventListener(this); 088 } 089 090 /** 091 * Removes the wrapped listener from the <code>{@link WeakReference}</code> (to simulate garbage collection). This 092 * method should be used only for <strong>testing only</strong>. 093 */ 094 @VisibleForTesting 095 void simulateUnderlyingListenerIsGarbageCollected() { 096 listenerReference.clear(); 097 } 098 }