source: josm/trunk/src/org/openstreetmap/josm/data/osm/event/SelectionEventManager.java @ 11928

Last change on this file since 11928 was 11928, checked in by Don-vip, 20 months ago

improve unit tests, javadoc

  • Property svn:eol-style set to native
File size: 3.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.event;
3
4import java.util.Collection;
5import java.util.List;
6import java.util.Objects;
7import java.util.concurrent.CopyOnWriteArrayList;
8
9import javax.swing.SwingUtilities;
10
11import org.openstreetmap.josm.data.SelectionChangedListener;
12import org.openstreetmap.josm.data.osm.DataSet;
13import org.openstreetmap.josm.data.osm.OsmPrimitive;
14import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
15
16/**
17 * Similar like {@link DatasetEventManager}, just for selection events. Because currently selection changed
18 * event are global, only FIRE_IN_EDT and FIRE_EDT_CONSOLIDATED modes are really useful
19 * @since 2912
20 */
21public class SelectionEventManager implements SelectionChangedListener {
22
23    private static final SelectionEventManager instance = new SelectionEventManager();
24
25    /**
26     * Returns the unique instance.
27     * @return the unique instance
28     */
29    public static SelectionEventManager getInstance() {
30        return instance;
31    }
32
33    private static class ListenerInfo {
34        private final SelectionChangedListener listener;
35
36        ListenerInfo(SelectionChangedListener listener) {
37            this.listener = listener;
38        }
39
40        @Override
41        public int hashCode() {
42            return Objects.hash(listener);
43        }
44
45        @Override
46        public boolean equals(Object o) {
47            if (this == o) return true;
48            if (o == null || getClass() != o.getClass()) return false;
49            ListenerInfo that = (ListenerInfo) o;
50            return Objects.equals(listener, that.listener);
51        }
52    }
53
54    private Collection<? extends OsmPrimitive> selection;
55    private final CopyOnWriteArrayList<ListenerInfo> inEDTListeners = new CopyOnWriteArrayList<>();
56    private final CopyOnWriteArrayList<ListenerInfo> normalListeners = new CopyOnWriteArrayList<>();
57
58    /**
59     * Constructs a new {@code SelectionEventManager}.
60     */
61    public SelectionEventManager() {
62        DataSet.addSelectionListener(this);
63    }
64
65    /**
66     * Registers a new {@code SelectionChangedListener}.
67     * @param listener listener to add
68     * @param fireMode EDT firing mode
69     */
70    public void addSelectionListener(SelectionChangedListener listener, FireMode fireMode) {
71        if (fireMode == FireMode.IN_EDT)
72            throw new UnsupportedOperationException("IN_EDT mode not supported, you probably want to use IN_EDT_CONSOLIDATED.");
73        if (fireMode == FireMode.IN_EDT || fireMode == FireMode.IN_EDT_CONSOLIDATED) {
74            inEDTListeners.addIfAbsent(new ListenerInfo(listener));
75        } else {
76            normalListeners.addIfAbsent(new ListenerInfo(listener));
77        }
78    }
79
80    /**
81     * Unregisters a {@code SelectionChangedListener}.
82     * @param listener listener to remove
83     */
84    public void removeSelectionListener(SelectionChangedListener listener) {
85        ListenerInfo searchListener = new ListenerInfo(listener);
86        inEDTListeners.remove(searchListener);
87        normalListeners.remove(searchListener);
88    }
89
90    @Override
91    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
92        fireEvents(normalListeners, newSelection);
93        selection = newSelection;
94        SwingUtilities.invokeLater(edtRunnable);
95    }
96
97    private static void fireEvents(List<ListenerInfo> listeners, Collection<? extends OsmPrimitive> newSelection) {
98        for (ListenerInfo listener: listeners) {
99            listener.listener.selectionChanged(newSelection);
100        }
101    }
102
103    private final Runnable edtRunnable = () -> {
104        if (selection != null) {
105            fireEvents(inEDTListeners, selection);
106        }
107    };
108}
Note: See TracBrowser for help on using the repository browser.