- Timestamp:
- 2016-11-08T23:29:31+01:00 (8 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/ExpertToggleAction.java
r10600 r11224 6 6 import java.awt.Component; 7 7 import java.awt.event.ActionEvent; 8 import java.lang.ref.WeakReference;9 import java.util.ArrayList;10 import java.util.Iterator;11 import java.util.List;12 8 13 9 import org.openstreetmap.josm.Main; 10 import org.openstreetmap.josm.data.preferences.BooleanProperty; 11 import org.openstreetmap.josm.tools.ListenerList; 14 12 15 13 /** … … 19 17 public class ExpertToggleAction extends ToggleAction { 20 18 19 /** 20 * This listener is notified whenever the expert mode setting changed. 21 */ 21 22 @FunctionalInterface 22 23 public interface ExpertModeChangeListener { 24 /** 25 * The expert mode changed. 26 * @param isExpert <code>true</code> if expert mode was enabled, false otherwise. 27 */ 23 28 void expertChanged(boolean isExpert); 24 29 } 25 30 26 private static final List<WeakReference<ExpertModeChangeListener>> listeners = new ArrayList<>(); 27 private static final List<WeakReference<Component>> visibilityToggleListeners = new ArrayList<>(); 31 // TODO: Switch to checked list. We can do this as soon as we do not see any more warnings. 32 private static final ListenerList<ExpertModeChangeListener> listeners = ListenerList.createUnchecked(); 33 private static final ListenerList<Component> visibilityToggleListeners = ListenerList.createUnchecked(); 34 35 private static final BooleanProperty PREF_EXPERT = new BooleanProperty("expert", false); 28 36 29 37 private static final ExpertToggleAction INSTANCE = new ExpertToggleAction(); 30 38 31 39 private static synchronized void fireExpertModeChanged(boolean isExpert) { 32 Iterator<WeakReference<ExpertModeChangeListener>> it1 = listeners.iterator(); 33 while (it1.hasNext()) { 34 WeakReference<ExpertModeChangeListener> wr = it1.next(); 35 ExpertModeChangeListener listener = wr.get(); 36 if (listener == null) { 37 it1.remove(); 38 continue; 39 } 40 listener.expertChanged(isExpert); 41 } 42 Iterator<WeakReference<Component>> it2 = visibilityToggleListeners.iterator(); 43 while (it2.hasNext()) { 44 WeakReference<Component> wr = it2.next(); 45 Component c = wr.get(); 46 if (c == null) { 47 it2.remove(); 48 continue; 49 } 50 c.setVisible(isExpert); 51 } 40 listeners.fireEvent(listener -> listener.expertChanged(isExpert)); 41 visibilityToggleListeners.fireEvent(c -> c.setVisible(isExpert)); 52 42 } 53 43 … … 63 53 public static synchronized void addExpertModeChangeListener(ExpertModeChangeListener listener, boolean fireWhenAdding) { 64 54 if (listener == null) return; 65 for (WeakReference<ExpertModeChangeListener> wr : listeners) { 66 // already registered ? => abort 67 if (wr.get() == listener) return; 68 } 69 listeners.add(new WeakReference<>(listener)); 55 listeners.addWeakListener(listener); 70 56 if (fireWhenAdding) { 71 57 listener.expertChanged(isExpert()); … … 80 66 public static synchronized void removeExpertModeChangeListener(ExpertModeChangeListener listener) { 81 67 if (listener == null) return; 82 Iterator<WeakReference<ExpertModeChangeListener>> it = listeners.iterator(); 83 while (it.hasNext()) { 84 WeakReference<ExpertModeChangeListener> wr = it.next(); 85 // remove the listener - and any other listener which god garbage 86 // collected in the meantime 87 if (wr.get() == null || wr.get() == listener) { 88 it.remove(); 89 } 90 } 68 listeners.removeListener(listener); 91 69 } 92 70 71 /** 72 * Marks a component to be only visible when expert mode is enabled. The visibility of the component is changed automatically. 73 * @param c The component. 74 */ 93 75 public static synchronized void addVisibilitySwitcher(Component c) { 94 76 if (c == null) return; 95 for (WeakReference<Component> wr : visibilityToggleListeners) { 96 // already registered ? => abort 97 if (wr.get() == c) return; 98 } 99 visibilityToggleListeners.add(new WeakReference<>(c)); 77 visibilityToggleListeners.addWeakListener(c); 100 78 c.setVisible(isExpert()); 101 79 } 102 80 81 /** 82 * Stops tracking visibility changes for the given component. 83 * @param c The component. 84 * @see #addVisibilitySwitcher(Component) 85 */ 103 86 public static synchronized void removeVisibilitySwitcher(Component c) { 104 87 if (c == null) return; 105 Iterator<WeakReference<Component>> it = visibilityToggleListeners.iterator(); 106 while (it.hasNext()) { 107 WeakReference<Component> wr = it.next(); 108 // remove the listener - and any other listener which god garbage 109 // collected in the meantime 110 if (wr.get() == null || wr.get() == c) { 111 it.remove(); 112 } 113 } 88 visibilityToggleListeners.removeListener(c); 114 89 } 115 90 … … 128 103 Main.toolbar.register(this); 129 104 } 130 setSelected( Main.pref.getBoolean("expert", false));105 setSelected(PREF_EXPERT.get()); 131 106 notifySelectedState(); 132 107 } … … 135 110 protected final void notifySelectedState() { 136 111 super.notifySelectedState(); 112 PREF_EXPERT.put(isSelected()); 137 113 fireExpertModeChanged(isSelected()); 114 } 115 116 /** 117 * Forces the expert mode state to the given state. 118 * @param isExpert if expert mode should be used. 119 * @since 11224 120 */ 121 public void setExpert(boolean isExpert) { 122 if (isSelected() != isExpert) { 123 setSelected(isExpert); 124 notifySelectedState(); 125 } 138 126 } 139 127 … … 141 129 public void actionPerformed(ActionEvent e) { 142 130 toggleSelectedState(e); 143 Main.pref.put("expert", isSelected());144 131 notifySelectedState(); 145 132 } -
trunk/src/org/openstreetmap/josm/tools/ListenerList.java
r11018 r11224 80 80 */ 81 81 public synchronized void addWeakListener(T listener) { 82 ensureNotInList(listener); 83 // clean the weak listeners, just to be sure... 84 while (weakListeners.remove(new WeakListener<T>(null))) { 85 // continue 86 } 87 weakListeners.add(new WeakListener<>(listener)); 82 if (ensureNotInList(listener)) { 83 // clean the weak listeners, just to be sure... 84 while (weakListeners.remove(new WeakListener<T>(null))) { 85 // continue 86 } 87 weakListeners.add(new WeakListener<>(listener)); 88 } 88 89 } 89 90 … … 93 94 */ 94 95 public synchronized void addListener(T listener) { 95 ensureNotInList(listener); 96 listeners.add(listener); 97 } 98 99 private void ensureNotInList(T listener) { 96 if (ensureNotInList(listener)) { 97 listeners.add(listener); 98 } 99 } 100 101 private boolean ensureNotInList(T listener) { 100 102 CheckParameterUtil.ensureParameterNotNull(listener, "listener"); 101 103 if (containsListener(listener)) { 102 104 failAdd(listener); 105 return false; 106 } else { 107 return true; 103 108 } 104 109 } … … 217 222 } 218 223 224 private static class UncheckedListenerList<T> extends ListenerList<T> { 225 @Override 226 protected void failAdd(T listener) { 227 Logging.warn("Listener was alreaady added: {0}", listener); 228 // ignore 229 } 230 231 @Override 232 protected void failRemove(T listener) { 233 Logging.warn("Listener was removed twice or not added: {0}", listener); 234 // ignore 235 } 236 } 237 219 238 /** 220 239 * Create a new listener list … … 229 248 } 230 249 } 250 251 /** 252 * Creates a new listener list that does not fail if listeners are added ore removed twice. 253 * <p> 254 * Use of this list is discouraged. You should always use {@link #create()} in new implementations and check your listeners. 255 * @param <T> The listener type 256 * @return A new list. 257 * @since 11224 258 */ 259 public static <T> ListenerList<T> createUnchecked() { 260 return new UncheckedListenerList<>(); 261 } 231 262 }
Note:
See TracChangeset
for help on using the changeset viewer.