package org.esa.snap.rcp.util.internal; import org.esa.snap.rcp.util.SelectionSupport; import org.openide.util.Lookup; import org.openide.util.LookupListener; import org.openide.util.Utilities; import org.openide.util.WeakListeners; import java.lang.reflect.Array; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.function.Predicate; import java.util.stream.Stream; public class DefaultSelectionSupport<T> implements SelectionSupport<T> { private final Class<T> type; private final Lookup.Result<T> itemResult; private final LinkedList<Handler<T>> handlerList; private final LookupListener lookupListener; private Collection<? extends T> currentlySelectedItems; private LookupListener theWeakListener; public DefaultSelectionSupport(Class<T> type) { this.type = type; currentlySelectedItems = Collections.emptyList(); itemResult = Utilities.actionsGlobalContext().lookupResult(type); handlerList = new LinkedList<>(); lookupListener = createLookupListener(); } @Override public void addHandler(Handler<T> handler) { if (handlerList.isEmpty() && theWeakListener == null) { // first listener added --> add LookupListener theWeakListener = WeakListeners.create(LookupListener.class, lookupListener, itemResult); itemResult.addLookupListener(theWeakListener); } handlerList.add(handler); } @Override public void removeHandler(Handler<T> handler) { handlerList.remove(handler); if (handlerList.isEmpty()) { // last listener removed --> remove LookupListener itemResult.removeLookupListener(theWeakListener); theWeakListener = null; } } private LookupListener createLookupListener() { return ev -> { Collection<? extends T> allItems = itemResult.allInstances(); Stream<? extends T> deselectedStream = currentlySelectedItems.stream().filter((Predicate<T>) (o) -> !allItems.contains(o)); T[] allDeselected = deselectedStream.toArray(value -> (T[]) Array.newInstance(type, value)); T firstDeselected = null; if (allDeselected.length > 0) { firstDeselected = allDeselected[0]; } Stream<? extends T> newlySelectedStream = allItems.stream().filter((Predicate<T>) (o) -> !currentlySelectedItems.contains(o)); T[] allNewlySelected = newlySelectedStream.toArray(value -> (T[]) Array.newInstance(type, value)); T firstSelected = null; if (allNewlySelected.length > 0) { firstSelected = allNewlySelected[0]; } currentlySelectedItems = allItems; // todo check if implementation is correct - ASAP! for (Handler<T> handler : handlerList) { handler.selectionChange(firstDeselected, firstSelected); } }; } }