blob: 3493fe9543701bfbee8dd93a73ebab0bf8c9f233 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Matthew Hall - bug 146397
*******************************************************************************/
package org.eclipse.core.databinding.observable;
/**
* Class that provides listener handling for three types: ChangeEvent,
* StaleEvent, and DisposeEvent. This class can be used as-is or can be
* extended. There are two reasons why you should extend this class:
* <P>
* 1. To add more listener types 2. To override the addFirstListener and
* removeLastListener methods
* <P>
* This class can be inherited (e.g. AbstractObservable) or can be delegated to
* (e.g. ObservableList).
*
* @since 1.0
*
*/
public abstract class ChangeSupport {
/**
* @since 1.5
*/
protected ListenerList<IChangeListener> genericListenerList = null;
/**
* @since 1.5
*/
protected ListenerList<IStaleListener> staleListenerList = null;
/**
* @since 1.5
*/
protected ListenerList<IDisposeListener> disposeListenerList = null;
/**
* @param realm
*
* @deprecated Realm is no longer used by this class, remove the parameter
*/
public ChangeSupport(Realm realm) {
this();
}
/**
* @since 1.5
*/
public ChangeSupport() {
}
/**
*
* @param listenerType
* @param listener
* @deprecated use one of the more specific methods, addChangeListener,
* addStaleListener, addDisposeListener
*/
public void addListener(Object listenerType,
IObservablesListener<?> listener) {
if (listenerType == AbstractChangeEvent.TYPE) {
addChangeListener((IChangeListener) listener);
} else if (listenerType == StaleEvent.TYPE) {
addStaleListener((IStaleListener) listener);
} else if (listenerType == DisposeEvent.TYPE) {
addDisposeListener((IDisposeListener) listener);
} else {
// This class does not fire any other types.
}
}
/**
* @param listenerType
* @param listener
* @deprecated use one of the more specific methods, removeChangeListener,
* removeStaleListener, removeDisposeListener
*/
public void removeListener(Object listenerType,
IObservablesListener<?> listener) {
if (listenerType == AbstractChangeEvent.TYPE) {
removeChangeListener((IChangeListener) listener);
} else if (listenerType == StaleEvent.TYPE) {
removeStaleListener((IStaleListener) listener);
} else if (listenerType == DisposeEvent.TYPE) {
removeDisposeListener((IDisposeListener) listener);
} else {
// This class does not fire any other types.
}
}
/**
* @param event
* @deprecated use one of the more specific methods, fireValueChange,
* fireStale, fireDispose
*/
// It is OK to suppress warnings in deprecated methods
@SuppressWarnings("unchecked")
public <EV extends ObservableEvent<EV, L>, L extends IObservablesListener<L>> void fireEvent(
ObservableEvent<EV, L> event) {
if (event.getListenerType() == AbstractChangeEvent.TYPE) {
if (genericListenerList != null) {
genericListenerList
.fireEvent((ObservableEvent<ChangeEvent, IChangeListener>) event);
}
} else if (event.getListenerType() == StaleEvent.TYPE) {
if (staleListenerList != null) {
staleListenerList
.fireEvent((ObservableEvent<StaleEvent, IStaleListener>) event);
}
} else if (event.getListenerType() == DisposeEvent.TYPE) {
if (disposeListenerList != null) {
disposeListenerList
.fireEvent((ObservableEvent<DisposeEvent, IDisposeListener>) event);
}
} else {
// This class does not fire any other types.
throw new IllegalArgumentException();
}
}
/**
* @param listener
*/
public synchronized void addChangeListener(IChangeListener listener) {
addListener(getGenericListenerList(), listener);
}
/**
* @param listener
*/
public synchronized void removeChangeListener(IChangeListener listener) {
if (genericListenerList != null) {
removeListener(genericListenerList, listener);
}
}
/**
* @param listener
*/
public synchronized void addStaleListener(IStaleListener listener) {
addListener(getStaleListenerList(), listener);
}
/**
* @param listener
*/
public synchronized void removeStaleListener(IStaleListener listener) {
if (staleListenerList != null) {
removeListener(staleListenerList, listener);
}
}
/**
* @param listener
* @since 1.2
*/
public synchronized void addDisposeListener(IDisposeListener listener) {
getDisposeListenerList().add(listener);
}
/**
* @param listener
* @since 1.2
*/
public synchronized void removeDisposeListener(IDisposeListener listener) {
if (disposeListenerList != null) {
disposeListenerList.remove(listener);
}
}
private ListenerList<IChangeListener> getGenericListenerList() {
if (genericListenerList == null) {
genericListenerList = new ListenerList<IChangeListener>();
}
return genericListenerList;
}
private ListenerList<IStaleListener> getStaleListenerList() {
if (staleListenerList == null) {
staleListenerList = new ListenerList<IStaleListener>();
}
return staleListenerList;
}
private ListenerList<IDisposeListener> getDisposeListenerList() {
if (disposeListenerList == null) {
disposeListenerList = new ListenerList<IDisposeListener>();
}
return disposeListenerList;
}
/**
* @param event
* @since 1.5
*/
protected void fireChange(ChangeEvent event) {
if (genericListenerList != null) {
genericListenerList.fireEvent(event);
}
}
/**
* @param event
* @since 1.5
*/
protected void fireStale(StaleEvent event) {
if (staleListenerList != null) {
staleListenerList.fireEvent(event);
}
}
/**
* @param disposeEvent
* @since 1.5
*/
public void fireDispose(DisposeEvent disposeEvent) {
if (disposeListenerList != null) {
disposeListenerList.fireEvent(disposeEvent);
}
}
/**
* @param listenerList
* @param listener
* @since 1.5
*/
protected <EV extends ObservableEvent<EV, L>, L extends IObservablesListener<L>> void addListener(
ListenerList<L> listenerList, L listener) {
boolean hadListeners = hasListeners();
listenerList.add(listener);
if (!hadListeners && hasListeners()) {
firstListenerAdded();
}
}
/**
* @param listenerList
* @param listener
* @since 1.5
*/
protected <EV extends ObservableEvent<EV, L>, L extends IObservablesListener<L>> void removeListener(
ListenerList<L> listenerList, L listener) {
boolean hadListeners = hasListeners();
listenerList.remove(listener);
if (hadListeners && !hasListeners()) {
this.lastListenerRemoved();
}
}
/**
* Note the 'dispose' listeners are not included. This is because this
* method is used to see if anyone still needs this observable. Listening
* for when an observable is disposed is not indicating use of the
* observable but merely a desire to clean things up.
*
* @return true if there are listeners, false if no listeners or only
* 'dispose' listeners
*/
protected boolean hasListeners() {
return ((genericListenerList != null && genericListenerList
.hasListeners()) || (staleListenerList != null && staleListenerList
.hasListeners()));
}
/**
*
*/
protected void firstListenerAdded() {
}
/**
*
*/
protected void lastListenerRemoved() {
}
/**
*
*/
protected void dispose() {
genericListenerList = null;
staleListenerList = null;
disposeListenerList = null;
}
/**
* Releases all listener references
*/
// protected void dispose() {
// genericChangeManager = null;
// staleChangeManager = null;
// disposeChangeManager = null;
// }
}