// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.data.osm.event;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.openstreetmap.josm.data.SelectionChangedListener;
import org.openstreetmap.josm.data.osm.DataSet;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
/**
* GWT
*
* changelog
* SwingUtilities.invokeLater(edtRunnable) -> edtRunnable.run()
*/
/**
* Similar like {@link DatasetEventManager}, just for selection events. Because currently selection changed
* event are global, only FIRE_IN_EDT and FIRE_EDT_CONSOLIDATED modes are really useful
*
*/
public class SelectionEventManager implements SelectionChangedListener {
private static final SelectionEventManager instance = new SelectionEventManager();
public static SelectionEventManager getInstance() {
return instance;
}
private static class ListenerInfo {
final SelectionChangedListener listener;
public ListenerInfo(SelectionChangedListener listener, boolean consolidate) {
this.listener = listener;
}
@Override
public int hashCode() {
return listener.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof ListenerInfo && ((ListenerInfo)o).listener == listener;
}
}
private Collection<? extends OsmPrimitive> selection;
private final CopyOnWriteArrayList<ListenerInfo> inEDTListeners = new CopyOnWriteArrayList<ListenerInfo>();
private final CopyOnWriteArrayList<ListenerInfo> normalListeners = new CopyOnWriteArrayList<ListenerInfo>();
public SelectionEventManager() {
DataSet.addSelectionListener(this);
}
public void addSelectionListener(SelectionChangedListener listener, FireMode fireMode) {
if (fireMode == FireMode.IN_EDT)
throw new UnsupportedOperationException("IN_EDT mode not supported, you probably want to use IN_EDT_CONSOLIDATED.");
if (fireMode == FireMode.IN_EDT || fireMode == FireMode.IN_EDT_CONSOLIDATED) {
inEDTListeners.addIfAbsent(new ListenerInfo(listener, fireMode == FireMode.IN_EDT_CONSOLIDATED));
} else {
normalListeners.addIfAbsent(new ListenerInfo(listener, false));
}
}
public void removeSelectionListener(SelectionChangedListener listener) {
ListenerInfo searchListener = new ListenerInfo(listener, false);
inEDTListeners.remove(searchListener);
normalListeners.remove(searchListener);
}
public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
fireEvents(normalListeners, newSelection);
selection = newSelection;
edtRunnable.run();
}
private void fireEvents(List<ListenerInfo> listeners, Collection<? extends OsmPrimitive> newSelection) {
for (ListenerInfo listener: listeners) {
listener.listener.selectionChanged(newSelection);
}
}
private final Runnable edtRunnable = new Runnable() {
public void run() {
if (selection != null) {
fireEvents(inEDTListeners, selection);
}
}
};
}