Ignore:
Timestamp:
2016-11-08T23:29:31+01:00 (3 years ago)
Author:
michael2402
Message:

Simplify ExpertToggleAction

Make ExpertToggleAction use the listener list to track weak listeners and add a method to set expert mode explicitly. Use it in OsmDataLayerTest to make tracing expert mode problems easier.

Add test case for ExpertToggleAction.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/ExpertToggleAction.java

    r10600 r11224  
    66import java.awt.Component;
    77import 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;
    128
    139import org.openstreetmap.josm.Main;
     10import org.openstreetmap.josm.data.preferences.BooleanProperty;
     11import org.openstreetmap.josm.tools.ListenerList;
    1412
    1513/**
     
    1917public class ExpertToggleAction extends ToggleAction {
    2018
     19    /**
     20     * This listener is notified whenever the expert mode setting changed.
     21     */
    2122    @FunctionalInterface
    2223    public interface ExpertModeChangeListener {
     24        /**
     25         * The expert mode changed.
     26         * @param isExpert <code>true</code> if expert mode was enabled, false otherwise.
     27         */
    2328        void expertChanged(boolean isExpert);
    2429    }
    2530
    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);
    2836
    2937    private static final ExpertToggleAction INSTANCE = new ExpertToggleAction();
    3038
    3139    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));
    5242    }
    5343
     
    6353    public static synchronized void addExpertModeChangeListener(ExpertModeChangeListener listener, boolean fireWhenAdding) {
    6454        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);
    7056        if (fireWhenAdding) {
    7157            listener.expertChanged(isExpert());
     
    8066    public static synchronized void removeExpertModeChangeListener(ExpertModeChangeListener listener) {
    8167        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);
    9169    }
    9270
     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     */
    9375    public static synchronized void addVisibilitySwitcher(Component c) {
    9476        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);
    10078        c.setVisible(isExpert());
    10179    }
    10280
     81    /**
     82     * Stops tracking visibility changes for the given component.
     83     * @param c The component.
     84     * @see #addVisibilitySwitcher(Component)
     85     */
    10386    public static synchronized void removeVisibilitySwitcher(Component c) {
    10487        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);
    11489    }
    11590
     
    128103            Main.toolbar.register(this);
    129104        }
    130         setSelected(Main.pref.getBoolean("expert", false));
     105        setSelected(PREF_EXPERT.get());
    131106        notifySelectedState();
    132107    }
     
    135110    protected final void notifySelectedState() {
    136111        super.notifySelectedState();
     112        PREF_EXPERT.put(isSelected());
    137113        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        }
    138126    }
    139127
     
    141129    public void actionPerformed(ActionEvent e) {
    142130        toggleSelectedState(e);
    143         Main.pref.put("expert", isSelected());
    144131        notifySelectedState();
    145132    }
Note: See TracChangeset for help on using the changeset viewer.