001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.awt.event.ActionEvent; 008import java.lang.ref.WeakReference; 009import java.util.ArrayList; 010import java.util.Iterator; 011import java.util.List; 012 013import org.openstreetmap.josm.Main; 014 015/** 016 * This action toggles the Expert mode. 017 * @since 4840 018 */ 019public class ExpertToggleAction extends ToggleAction { 020 021 public interface ExpertModeChangeListener { 022 void expertChanged(boolean isExpert); 023 } 024 025 private static final List<WeakReference<ExpertModeChangeListener>> listeners = new ArrayList<WeakReference<ExpertModeChangeListener>>(); 026 private static final List<WeakReference<Component>> visibilityToggleListeners = new ArrayList<WeakReference<Component>>(); 027 028 private static ExpertToggleAction INSTANCE = new ExpertToggleAction(); 029 030 private synchronized static void fireExpertModeChanged(boolean isExpert) { 031 { 032 Iterator<WeakReference<ExpertModeChangeListener>> it = listeners.iterator(); 033 while (it.hasNext()) { 034 WeakReference<ExpertModeChangeListener> wr = it.next(); 035 ExpertModeChangeListener listener = wr.get(); 036 if (listener == null) { 037 it.remove(); 038 continue; 039 } 040 listener.expertChanged(isExpert); 041 } 042 } 043 { 044 Iterator<WeakReference<Component>> it = visibilityToggleListeners.iterator(); 045 while (it.hasNext()) { 046 WeakReference<Component> wr = it.next(); 047 Component c = wr.get(); 048 if (c == null) { 049 it.remove(); 050 continue; 051 } 052 c.setVisible(isExpert); 053 } 054 } 055 } 056 057 /** 058 * Register a expert mode change listener 059 * 060 * @param listener the listener. Ignored if null. 061 */ 062 public static void addExpertModeChangeListener(ExpertModeChangeListener listener) { 063 addExpertModeChangeListener(listener, false); 064 } 065 066 public synchronized static void addExpertModeChangeListener(ExpertModeChangeListener listener, boolean fireWhenAdding) { 067 if (listener == null) return; 068 for (WeakReference<ExpertModeChangeListener> wr : listeners) { 069 // already registered ? => abort 070 if (wr.get() == listener) return; 071 } 072 listeners.add(new WeakReference<ExpertModeChangeListener>(listener)); 073 if (fireWhenAdding) { 074 listener.expertChanged(isExpert()); 075 } 076 } 077 078 /** 079 * Removes a expert mode change listener 080 * 081 * @param listener the listener. Ignored if null. 082 */ 083 public synchronized static void removeExpertModeChangeListener(ExpertModeChangeListener listener) { 084 if (listener == null) return; 085 Iterator<WeakReference<ExpertModeChangeListener>> it = listeners.iterator(); 086 while (it.hasNext()) { 087 WeakReference<ExpertModeChangeListener> wr = it.next(); 088 // remove the listener - and any other listener which god garbage 089 // collected in the meantime 090 if (wr.get() == null || wr.get() == listener) { 091 it.remove(); 092 } 093 } 094 } 095 096 public synchronized static void addVisibilitySwitcher(Component c) { 097 if (c == null) return; 098 for (WeakReference<Component> wr : visibilityToggleListeners) { 099 // already registered ? => abort 100 if (wr.get() == c) return; 101 } 102 visibilityToggleListeners.add(new WeakReference<Component>(c)); 103 c.setVisible(isExpert()); 104 } 105 106 public synchronized static void removeVisibilitySwitcher(Component c) { 107 if (c == null) return; 108 Iterator<WeakReference<Component>> it = visibilityToggleListeners.iterator(); 109 while (it.hasNext()) { 110 WeakReference<Component> wr = it.next(); 111 // remove the listener - and any other listener which god garbage 112 // collected in the meantime 113 if (wr.get() == null || wr.get() == c) { 114 it.remove(); 115 } 116 } 117 } 118 119 /** 120 * Constructs a new {@code ExpertToggleAction}. 121 */ 122 public ExpertToggleAction() { 123 super(tr("Expert Mode"), 124 "expert", 125 tr("Enable/disable expert mode"), 126 null, 127 false /* register toolbar */ 128 ); 129 putValue("toolbar", "expertmode"); 130 Main.toolbar.register(this); 131 setSelected(Main.pref.getBoolean("expert", false)); 132 notifySelectedState(); 133 } 134 135 protected void notifySelectedState() { 136 super.notifySelectedState(); 137 fireExpertModeChanged(isSelected()); 138 } 139 140 @Override 141 public void actionPerformed(ActionEvent e) { 142 toggleSelectedState(e); 143 Main.pref.put("expert", isSelected()); 144 notifySelectedState(); 145 } 146 147 /** 148 * Replies the unique instance of this action. 149 * @return The unique instance of this action 150 */ 151 public static ExpertToggleAction getInstance() { 152 return INSTANCE; 153 } 154 155 /** 156 * Determines if expert mode is enabled. 157 * @return {@code true} if expert mode is enabled, {@code false} otherwise. 158 */ 159 public static boolean isExpert() { 160 return INSTANCE.isSelected(); 161 } 162}