// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui.util; import java.awt.Component; import java.awt.Cursor; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; /** * This class manages multiple cursors for multiple components. * All components share the same cursor that was last set using {@link #setNewCursor(Cursor, Object)} * * @author Michael Zangl */ public class CursorManager { private final LinkedHashMap<Object, Cursor> cursors = new LinkedHashMap<>(); private final CopyOnWriteArrayList<Component> components = new CopyOnWriteArrayList<>(); /** * Creates a new NavigationCursorManager * @param forComponent The initial component the cursor should be managed for. */ public CursorManager(Component forComponent) { addComponent(forComponent); } /** * Adds a component that this manager should send cursor changes to. * @param forComponent The component. */ public synchronized void addComponent(Component forComponent) { components.addIfAbsent(forComponent); forComponent.setCursor(getCurrentCursor()); } /** * Removes a component that this manager should send cursor changes to. The current cursor is not reset. * @param forComponent The component. */ public synchronized void removeComponent(Component forComponent) { components.remove(forComponent); } /** * Set new cursor. * @param cursor The new cursor to use. * @param reference A reference object that can be passed to the next set/reset calls to identify the caller. */ public synchronized void setNewCursor(Cursor cursor, Object reference) { Objects.requireNonNull(reference, "Cannot register a cursor that can never be removed."); // re-insert to allow overriding. cursors.remove(reference); cursors.put(reference, cursor); updateCursor(); } /** * Remove the new cursor that was set with the given reference object. and reset to previous * @param reference A reference object that can be passed to the next set/reset calls to identify the caller. */ public synchronized void resetCursor(Object reference) { if (reference == null) { return; } cursors.remove(reference); updateCursor(); } private void updateCursor() { Cursor cursor = getCurrentCursor(); for (Component c : components) { c.setCursor(cursor); } } private Cursor getCurrentCursor() { Iterator<Cursor> it = cursors.values().iterator(); Cursor cursor = null; while (it.hasNext()) { cursor = it.next(); } return cursor; } }