source: josm/trunk/src/org/openstreetmap/josm/data/osm/DataSelectionListener.java@ 15586

Last change on this file since 15586 was 15586, checked in by Don-vip, 4 years ago

code cleanup

File size: 10.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
4import java.util.Collections;
5import java.util.HashSet;
6import java.util.LinkedHashSet;
7import java.util.Set;
8import java.util.stream.Collectors;
9import java.util.stream.Stream;
10
11import org.openstreetmap.josm.tools.CheckParameterUtil;
12
13/**
14 * This is a listener that listens to selection change events in the data set.
15 * @author Michael Zangl
16 * @since 12048
17 */
18@FunctionalInterface
19public interface DataSelectionListener {
20
21 /**
22 * Called whenever the selection is changed.
23 *
24 * You get notified about the new selection, the elements that were added and removed and the layer that triggered the event.
25 * @param event The selection change event.
26 * @see SelectionChangeEvent
27 */
28 void selectionChanged(SelectionChangeEvent event);
29
30 /**
31 * The event that is fired when the selection changed.
32 * @author Michael Zangl
33 * @since 12048
34 */
35 interface SelectionChangeEvent {
36 /**
37 * Gets the previous selection
38 * <p>
39 * This collection cannot be modified and will not change.
40 * @return The old selection
41 */
42 Set<OsmPrimitive> getOldSelection();
43
44 /**
45 * Gets the new selection. New elements are added to the end of the collection.
46 * <p>
47 * This collection cannot be modified and will not change.
48 * @return The new selection
49 */
50 Set<OsmPrimitive> getSelection();
51
52 /**
53 * Gets the primitives that have been removed from the selection.
54 * <p>
55 * Those are the primitives contained in {@link #getOldSelection()} but not in {@link #getSelection()}
56 * <p>
57 * This collection cannot be modified and will not change.
58 * @return The primitives that were removed
59 */
60 Set<OsmPrimitive> getRemoved();
61
62 /**
63 * Gets the primitives that have been added to the selection.
64 * <p>
65 * Those are the primitives contained in {@link #getSelection()} but not in {@link #getOldSelection()}
66 * <p>
67 * This collection cannot be modified and will not change.
68 * @return The primitives that were added
69 */
70 Set<OsmPrimitive> getAdded();
71
72 /**
73 * Gets the data set that triggered this selection event.
74 * @return The data set.
75 */
76 DataSet getSource();
77
78 /**
79 * Test if this event did not change anything.
80 * <p>
81 * This will return <code>false</code> for all events that are sent to listeners, so you don't need to test it.
82 * @return <code>true</code> if this did not change the selection.
83 */
84 default boolean isNop() {
85 return getAdded().isEmpty() && getRemoved().isEmpty();
86 }
87 }
88
89 /**
90 * The base class for selection events
91 * @author Michael Zangl
92 * @since 12048
93 */
94 abstract class AbstractSelectionEvent implements SelectionChangeEvent {
95 private final DataSet source;
96 private final Set<OsmPrimitive> old;
97
98 public AbstractSelectionEvent(DataSet source, Set<OsmPrimitive> old) {
99 CheckParameterUtil.ensureParameterNotNull(source, "source");
100 CheckParameterUtil.ensureParameterNotNull(old, "old");
101 this.source = source;
102 this.old = Collections.unmodifiableSet(old);
103 }
104
105 @Override
106 public Set<OsmPrimitive> getOldSelection() {
107 return old;
108 }
109
110 @Override
111 public DataSet getSource() {
112 return source;
113 }
114 }
115
116 /**
117 * The selection is replaced by a new selection
118 * @author Michael Zangl
119 * @since 12048
120 */
121 class SelectionReplaceEvent extends AbstractSelectionEvent {
122 private final Set<OsmPrimitive> current;
123 private Set<OsmPrimitive> removed;
124 private Set<OsmPrimitive> added;
125
126 /**
127 * Create a {@link SelectionReplaceEvent}
128 * @param source The source dataset
129 * @param old The old primitves that were previously selected. The caller needs to ensure that this set is not modifed.
130 * @param newSelection The primitives of the new selection.
131 */
132 public SelectionReplaceEvent(DataSet source, Set<OsmPrimitive> old, Stream<OsmPrimitive> newSelection) {
133 super(source, old);
134 this.current = newSelection.collect(Collectors.toCollection(LinkedHashSet::new));
135 }
136
137 @Override
138 public Set<OsmPrimitive> getSelection() {
139 return current;
140 }
141
142 @Override
143 public synchronized Set<OsmPrimitive> getRemoved() {
144 if (removed == null) {
145 removed = getOldSelection().stream()
146 .filter(p -> !current.contains(p))
147 .collect(Collectors.toCollection(LinkedHashSet::new));
148 }
149 return removed;
150 }
151
152 @Override
153 public synchronized Set<OsmPrimitive> getAdded() {
154 if (added == null) {
155 added = current.stream()
156 .filter(p -> !getOldSelection().contains(p)).collect(Collectors.toCollection(LinkedHashSet::new));
157 }
158 return added;
159 }
160
161 @Override
162 public String toString() {
163 return "SelectionReplaceEvent [current=" + current + ", removed=" + removed + ", added=" + added + ']';
164 }
165 }
166
167 /**
168 * Primitives are added to the selection
169 * @author Michael Zangl
170 * @since 12048
171 */
172 class SelectionAddEvent extends AbstractSelectionEvent {
173 private final Set<OsmPrimitive> add;
174 private final Set<OsmPrimitive> current;
175
176 /**
177 * Create a {@link SelectionAddEvent}
178 * @param source The source dataset
179 * @param old The old primitves that were previously selected. The caller needs to ensure that this set is not modifed.
180 * @param toAdd The primitives to add.
181 */
182 public SelectionAddEvent(DataSet source, Set<OsmPrimitive> old, Stream<OsmPrimitive> toAdd) {
183 super(source, old);
184 this.add = toAdd
185 .filter(p -> !old.contains(p))
186 .collect(Collectors.toCollection(LinkedHashSet::new));
187 if (this.add.isEmpty()) {
188 this.current = this.getOldSelection();
189 } else {
190 this.current = new LinkedHashSet<>(old);
191 this.current.addAll(add);
192 }
193 }
194
195 @Override
196 public Set<OsmPrimitive> getSelection() {
197 return Collections.unmodifiableSet(current);
198 }
199
200 @Override
201 public Set<OsmPrimitive> getRemoved() {
202 return Collections.emptySet();
203 }
204
205 @Override
206 public Set<OsmPrimitive> getAdded() {
207 return Collections.unmodifiableSet(add);
208 }
209
210 @Override
211 public String toString() {
212 return "SelectionAddEvent [add=" + add + ", current=" + current + ']';
213 }
214 }
215
216 /**
217 * Primitives are removed from the selection
218 * @author Michael Zangl
219 * @since 12048
220 */
221 class SelectionRemoveEvent extends AbstractSelectionEvent {
222 private final Set<OsmPrimitive> remove;
223 private final Set<OsmPrimitive> current;
224
225 /**
226 * Create a {@link SelectionRemoveEvent}
227 * @param source The source dataset
228 * @param old The old primitves that were previously selected. The caller needs to ensure that this set is not modifed.
229 * @param toRemove The primitives to remove.
230 */
231 public SelectionRemoveEvent(DataSet source, Set<OsmPrimitive> old, Stream<OsmPrimitive> toRemove) {
232 super(source, old);
233 this.remove = toRemove
234 .filter(old::contains)
235 .collect(Collectors.toCollection(LinkedHashSet::new));
236 if (this.remove.isEmpty()) {
237 this.current = this.getOldSelection();
238 } else {
239 HashSet<OsmPrimitive> currentSet = new LinkedHashSet<>(old);
240 currentSet.removeAll(remove);
241 current = currentSet;
242 }
243 }
244
245 @Override
246 public Set<OsmPrimitive> getSelection() {
247 return Collections.unmodifiableSet(current);
248 }
249
250 @Override
251 public Set<OsmPrimitive> getRemoved() {
252 return Collections.unmodifiableSet(remove);
253 }
254
255 @Override
256 public Set<OsmPrimitive> getAdded() {
257 return Collections.emptySet();
258 }
259
260 @Override
261 public String toString() {
262 return "SelectionRemoveEvent [remove=" + remove + ", current=" + current + ']';
263 }
264 }
265
266 /**
267 * Toggle the selected state of a primitive
268 * @author Michael Zangl
269 * @since 12048
270 */
271 class SelectionToggleEvent extends AbstractSelectionEvent {
272 private final Set<OsmPrimitive> current;
273 private final Set<OsmPrimitive> remove;
274 private final Set<OsmPrimitive> add;
275
276 /**
277 * Create a {@link SelectionToggleEvent}
278 * @param source The source dataset
279 * @param old The old primitves that were previously selected. The caller needs to ensure that this set is not modifed.
280 * @param toToggle The primitives to toggle.
281 */
282 public SelectionToggleEvent(DataSet source, Set<OsmPrimitive> old, Stream<OsmPrimitive> toToggle) {
283 super(source, old);
284 HashSet<OsmPrimitive> currentSet = new LinkedHashSet<>(old);
285 HashSet<OsmPrimitive> removeSet = new LinkedHashSet<>();
286 HashSet<OsmPrimitive> addSet = new LinkedHashSet<>();
287 toToggle.forEach(p -> {
288 if (currentSet.remove(p)) {
289 removeSet.add(p);
290 } else {
291 addSet.add(p);
292 currentSet.add(p);
293 }
294 });
295 this.current = Collections.unmodifiableSet(currentSet);
296 this.remove = Collections.unmodifiableSet(removeSet);
297 this.add = Collections.unmodifiableSet(addSet);
298 }
299
300 @Override
301 public Set<OsmPrimitive> getSelection() {
302 return Collections.unmodifiableSet(current);
303 }
304
305 @Override
306 public Set<OsmPrimitive> getRemoved() {
307 return Collections.unmodifiableSet(remove);
308 }
309
310 @Override
311 public Set<OsmPrimitive> getAdded() {
312 return Collections.unmodifiableSet(add);
313 }
314
315 @Override
316 public String toString() {
317 return "SelectionToggleEvent [current=" + current + ", remove=" + remove + ", add=" + add + ']';
318 }
319 }
320}
Note: See TracBrowser for help on using the repository browser.