package bluej.utility.javafx;

import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import bluej.utility.Utility;


| A class that allows you to attach a listener to each item in a stream. | Each time the stream may have changed, you can call listenOnlyTo to attach | listeners to every item in the stream. The class keeps track of which items | it is already listening to, so it ensures that it will never attach multiple | listeners to any given item. Also, when an item leaves the stream, the listener | will be removed. | public class MultiListener<T>{ public static interface RemoveAndUpdate { public void removeListener(); public default void updateListener() { } } private static class BooleanAndRemoveAndUpdate { public boolean flaggedForRemoval = false; public final RemoveAndUpdate removeAndUpdate; BooleanAndRemoveAndUpdate(RemoveAndUpdate removeAndUpdate) { this.removeAndUpdate = removeAndUpdate; } } private final IdentityHashMap<T, BooleanAndRemoveAndUpdate> listening = new IdentityHashMap<>(); private final Function<T, RemoveAndUpdate> addListener;
| | @param addListener The function that attaches a listener to the given item, and | gives back functions for removing and updating the listener in future. | @param removeListener The function that removes a listener from the given item | @param updateListener The function that is called when an item remains in the stream from last time | public MultiListener(Function<T, RemoveAndUpdate> addListener) { this.addListener = addListener; } public void listenOnlyTo(Stream<T> items) { listening.forEach((k, v) -> v.flaggedForRemoval = true); for (T t : Utility.iterableStream(items)) { BooleanAndRemoveAndUpdate value = listening.get(t); if (value != null) { value.removeAndUpdate.updateListener(); value.flaggedForRemoval = false; } else { listening.put(t, new BooleanAndRemoveAndUpdate(addListener.apply(t))); } } List<Entry<T, BooleanAndRemoveAndUpdate>> stale = listening.entrySet().stream().filter(e -> e.getValue().flaggedForRemoval).collect(Collectors.toList()); stale.forEach(e -> {e.getValue().removeAndUpdate.removeListener(); listening.remove(e.getKey()); }); } public void stopListening() { listening.forEach((k, v) -> v.removeAndUpdate.removeListener()); listening.clear(); } }
top, use, map, interface RemoveAndUpdate

.   removeListener
.   updateListener

top, use, map, class BooleanAndRemoveAndUpdate

.   MultiListener
.   listenOnlyTo
.   stopListening




91 neLoCode + 10 LoComm