1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.util;
|
---|
3 |
|
---|
4 | import java.awt.Component;
|
---|
5 | import java.awt.Cursor;
|
---|
6 | import java.util.Iterator;
|
---|
7 | import java.util.LinkedHashMap;
|
---|
8 | import java.util.Objects;
|
---|
9 | import java.util.concurrent.CopyOnWriteArrayList;
|
---|
10 |
|
---|
11 | /**
|
---|
12 | * This class manages multiple cursors for multiple components.
|
---|
13 | * All components share the same cursor that was last set using {@link #setNewCursor(Cursor, Object)}
|
---|
14 | *
|
---|
15 | * @author Michael Zangl
|
---|
16 | */
|
---|
17 | public class CursorManager {
|
---|
18 |
|
---|
19 | private final LinkedHashMap<Object, Cursor> cursors = new LinkedHashMap<>();
|
---|
20 | private final CopyOnWriteArrayList<Component> components = new CopyOnWriteArrayList<>();
|
---|
21 |
|
---|
22 | /**
|
---|
23 | * Creates a new NavigationCursorManager
|
---|
24 | * @param forComponent The initial component the cursor should be managed for.
|
---|
25 | */
|
---|
26 | public CursorManager(Component forComponent) {
|
---|
27 | addComponent(forComponent);
|
---|
28 | }
|
---|
29 |
|
---|
30 | /**
|
---|
31 | * Adds a component that this manager should send cursor changes to.
|
---|
32 | * @param forComponent The component.
|
---|
33 | */
|
---|
34 | public synchronized void addComponent(Component forComponent) {
|
---|
35 | components.addIfAbsent(forComponent);
|
---|
36 | forComponent.setCursor(getCurrentCursor());
|
---|
37 | }
|
---|
38 |
|
---|
39 | /**
|
---|
40 | * Removes a component that this manager should send cursor changes to. The current cursor is not reset.
|
---|
41 | * @param forComponent The component.
|
---|
42 | */
|
---|
43 | public synchronized void removeComponent(Component forComponent) {
|
---|
44 | components.remove(forComponent);
|
---|
45 | }
|
---|
46 |
|
---|
47 | /**
|
---|
48 | * Set new cursor.
|
---|
49 | * @param cursor The new cursor to use.
|
---|
50 | * @param reference A reference object that can be passed to the next set/reset calls to identify the caller.
|
---|
51 | */
|
---|
52 | public synchronized void setNewCursor(Cursor cursor, Object reference) {
|
---|
53 | Objects.requireNonNull(reference, "Cannot register a cursor that can never be removed.");
|
---|
54 | // re-insert to allow overriding.
|
---|
55 | cursors.remove(reference);
|
---|
56 | cursors.put(reference, cursor);
|
---|
57 | updateCursor();
|
---|
58 | }
|
---|
59 |
|
---|
60 | /**
|
---|
61 | * Remove the new cursor that was set with the given reference object. and reset to previous
|
---|
62 | * @param reference A reference object that can be passed to the next set/reset calls to identify the caller.
|
---|
63 | */
|
---|
64 | public synchronized void resetCursor(Object reference) {
|
---|
65 | if (reference == null) {
|
---|
66 | return;
|
---|
67 | }
|
---|
68 | cursors.remove(reference);
|
---|
69 | updateCursor();
|
---|
70 | }
|
---|
71 |
|
---|
72 | private void updateCursor() {
|
---|
73 | Cursor cursor = getCurrentCursor();
|
---|
74 | for (Component c : components) {
|
---|
75 | c.setCursor(cursor);
|
---|
76 | }
|
---|
77 | }
|
---|
78 |
|
---|
79 | private Cursor getCurrentCursor() {
|
---|
80 | Iterator<Cursor> it = cursors.values().iterator();
|
---|
81 | Cursor cursor = null;
|
---|
82 | while (it.hasNext()) {
|
---|
83 | cursor = it.next();
|
---|
84 | }
|
---|
85 | return cursor;
|
---|
86 | }
|
---|
87 |
|
---|
88 | }
|
---|