package org.codefx.libfx.listener.handle; import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ArrayChangeListener; import javafx.collections.ListChangeListener; import javafx.collections.MapChangeListener; import javafx.collections.ObservableArray; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; import javafx.collections.ObservableSet; import javafx.collections.SetChangeListener; /** * Factory class for functionality surrounding {@link ListenerHandle}s. */ public class ListenerHandles { /** * Private constructor so utility class is not instantiated. */ private ListenerHandles() { // nothing to do } /** * Creates a {@link ListenerHandleBuilder builder} for a generic {@link ListenerHandle}. * * @param <O> * the type of the observable instance (e.g {@link javafx.beans.value.ObservableValue ObservableValue} or * {@link javafx.collections.ObservableMap ObservableMap}) to which the listener will be added * @param <L> * the type of the listener which will be added to the observable * @param observable * the observable instance to which the {@code listener} will be added * @param listener * the listener which will be added to the {@code observable} * @return a {@link ListenerHandleBuilder} for a {@code ListenerHandle}. * @see ListenerHandleBuilder */ public static <O, L> ListenerHandleBuilder<O, L> createFor(O observable, L listener) { return ListenerHandleBuilder.from(observable, listener); } // Observable + InvalidationListener /** * Adds the specified listener to the specified observable and returns a handle for the combination. * * @param observable * the {@link Observable} to which the {@code invalidationListener} will be added * @param invalidationListener * the {@link InvalidationListener} which will be added to the {@code observable} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially attached */ public static ListenerHandle createAttached(Observable observable, InvalidationListener invalidationListener) { ListenerHandle handle = createDetached(observable, invalidationListener); handle.attach(); return handle; } /** * Creates a listener handle for the specified observable and listener. The listener is not yet attached! * * @param observable * the {@link Observable} to which the {@code invalidationListener} will be added * @param invalidationListener * the {@link InvalidationListener} which will be added to the {@code observableValue} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially detached */ public static ListenerHandle createDetached(Observable observable, InvalidationListener invalidationListener) { return ListenerHandleBuilder .from(observable, invalidationListener) .onAttach(Observable::addListener) .onDetach(Observable::removeListener) .buildDetached(); } // ObservableValue + ChangeListener /** * Adds the specified listener to the specified observable value and returns a handle for the combination. * * @param <T> * the type of the value wrapped by the observable * @param observableValue * the {@link ObservableValue} to which the {@code changeListener} will be added * @param changeListener * the {@link ChangeListener} which will be added to the {@code observableValue} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially attached */ public static <T> ListenerHandle createAttached( ObservableValue<T> observableValue, ChangeListener<? super T> changeListener) { ListenerHandle handle = createDetached(observableValue, changeListener); handle.attach(); return handle; } /** * Creates a listener handle for the specified observable value and listener. The listener is not yet attached! * * @param <T> * the type of the value wrapped by the observable * @param observableValue * the {@link ObservableValue} to which the {@code changeListener} will be added * @param changeListener * the {@link ChangeListener} which will be added to the {@code observableValue} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially detached */ public static <T> ListenerHandle createDetached( ObservableValue<T> observableValue, ChangeListener<? super T> changeListener) { return ListenerHandleBuilder .from(observableValue, changeListener) .onAttach(ObservableValue::addListener) .onDetach(ObservableValue::removeListener) .buildDetached(); } // ObservableArray + ArrayChangeListener /** * Adds the specified listener to the specified observable array and returns a handle for the combination. * * @param <T> * the type of the array wrapped by the observable * @param observableArray * the {@link ObservableArray} to which the {@code changeListener} will be added * @param changeListener * the {@link ArrayChangeListener} which will be added to the {@code observableArray} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially attached */ public static <T extends ObservableArray<T>> ListenerHandle createAttached( ObservableArray<T> observableArray, ArrayChangeListener<T> changeListener) { ListenerHandle handle = createDetached(observableArray, changeListener); handle.attach(); return handle; } /** * Creates a listener handle for the specified observable array and listener. The listener is not yet attached! * * @param <T> * the type of the array wrapped by the observable * @param observableArray * the {@link ObservableArray} to which the {@code changeListener} will be added * @param changeListener * the {@link ArrayChangeListener} which will be added to the {@code observableArray} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially detached */ public static <T extends ObservableArray<T>> ListenerHandle createDetached( ObservableArray<T> observableArray, ArrayChangeListener<T> changeListener) { return ListenerHandleBuilder .from(observableArray, changeListener) .onAttach(ObservableArray::addListener) .onDetach(ObservableArray::removeListener) .buildDetached(); } // ObservableList + ListChangeListener /** * Adds the specified listener to the specified observable list and returns a handle for the combination. * * @param <E> * the list element type * @param observableList * the {@link ObservableList} to which the {@code changeListener} will be added * @param changeListener * the {@link ListChangeListener} which will be added to the {@code observableList} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially attached */ public static <E> ListenerHandle createAttached( ObservableList<E> observableList, ListChangeListener<? super E> changeListener) { ListenerHandle handle = createDetached(observableList, changeListener); handle.attach(); return handle; } /** * Creates a listener handle for the specified observable list and listener. The listener is not yet attached! * * @param <E> * the list element type * @param observableList * the {@link ObservableList} to which the {@code changeListener} will be added * @param changeListener * the {@link ListChangeListener} which will be added to the {@code observableList} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially detached */ public static <E> ListenerHandle createDetached( ObservableList<E> observableList, ListChangeListener<? super E> changeListener) { return ListenerHandleBuilder .from(observableList, changeListener) .onAttach(ObservableList::addListener) .onDetach(ObservableList::removeListener) .buildDetached(); } // ObservableSet + SetChangeListener /** * Adds the specified listener to the specified observable set and returns a handle for the combination. * * @param <E> * the set element type * @param observableSet * the {@link ObservableSet} to which the {@code changeListener} will be added * @param changeListener * the {@link SetChangeListener} which will be added to the {@code observableSet} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially attached */ public static <E> ListenerHandle createAttached( ObservableSet<E> observableSet, SetChangeListener<? super E> changeListener) { ListenerHandle handle = createDetached(observableSet, changeListener); handle.attach(); return handle; } /** * Creates a listener handle for the specified observable set and listener. The listener is not yet attached! * * @param <E> * the set element type * @param observableSet * the {@link ObservableSet} to which the {@code changeListener} will be added * @param changeListener * the {@link SetChangeListener} which will be added to the {@code observableSet} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially detached */ public static <E> ListenerHandle createDetached( ObservableSet<E> observableSet, SetChangeListener<? super E> changeListener) { return ListenerHandleBuilder .from(observableSet, changeListener) .onAttach(ObservableSet::addListener) .onDetach(ObservableSet::removeListener) .buildDetached(); } // ObservableMap + MapChangeListener /** * Adds the specified listener to the specified observable map and returns a handle for the combination. * * @param <K> * the map key element type * @param <V> * the map value element type * @param observableMap * the {@link ObservableMap} to which the {@code changeListener} will be added * @param changeListener * the {@link MapChangeListener} which will be added to the {@code observableMap} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially attached */ public static <K, V> ListenerHandle createAttached( ObservableMap<K, V> observableMap, MapChangeListener<? super K, ? super V> changeListener) { ListenerHandle handle = createDetached(observableMap, changeListener); handle.attach(); return handle; } /** * Creates a listener handle for the specified observable map and listener. The listener is not yet attached! * * @param <K> * the map key element type * @param <V> * the map value element type * @param observableMap * the {@link ObservableMap} to which the {@code changeListener} will be added * @param changeListener * the {@link MapChangeListener} which will be added to the {@code observableMap} * @return a {@link ListenerHandle} for the specified arguments; the listener is initially detached */ public static <K, V> ListenerHandle createDetached( ObservableMap<K, V> observableMap, MapChangeListener<? super K, ? super V> changeListener) { return ListenerHandleBuilder .from(observableMap, changeListener) .onAttach(ObservableMap::addListener) .onDetach(ObservableMap::removeListener) .buildDetached(); } }