/* This file is part of RouteConverter. RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RouteConverter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.gui.actions; import slash.navigation.gui.Application; import javax.swing.*; import javax.swing.event.SwingPropertyChangeSupport; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import java.util.prefs.Preferences; import static java.lang.String.format; import static java.util.Collections.sort; import static javax.swing.Action.NAME; import static slash.common.helpers.PreferencesHelper.count; /** * Manages the {@link Action}s of an {@link Application}. * * @author Christian Pesch */ public class ActionManager { private static final Logger log = Logger.getLogger(ActionManager.class.getName()); private static final Preferences preferences = Preferences.userNodeForPackage(ActionManager.class); private static final String RUN_COUNT_PREFERENCE = "runCount"; private Map<String, Action> actionMap = new HashMap<>(); private Map<String, ProxyAction> proxyActionMap = new HashMap<>(); private String localName; public String getLocalName() { return localName; } public void setLocalName(String localName) { this.localName = localName; } public Action get(String actionName) { Action action = actionMap.get(actionName); if (action != null) return action; ProxyAction proxyAction = proxyActionMap.get(actionName); if (proxyAction == null) { proxyAction = new ProxyAction(); proxyActionMap.put(actionName, proxyAction); } return proxyAction; } public void register(String actionName, Action action) { Action found = actionMap.get(actionName); if (found != null) throw new IllegalArgumentException("Action '" + found + "' for '" + actionName + "' already registered"); actionMap.put(actionName, action); action.putValue(NAME, actionName); ProxyAction proxyAction = proxyActionMap.get(actionName); if (proxyAction != null) { proxyAction.setDelegate(action); } else { proxyActionMap.put(actionName, new ProxyAction(action)); } } public void registerLocal(String globalName, String localName, String actionName) { GlobalAction found = (GlobalAction) actionMap.get(globalName); if (found == null) throw new IllegalArgumentException("No action registered for '" + globalName + "'"); found.registerLocal(localName, actionName); } public void registerGlobal(String globalName) { register(globalName, new GlobalAction(globalName)); } public void run(String actionName) { run(actionName, new ActionEvent(this, -1, actionName)); } public void run(String actionName, ActionEvent actionEvent) { Action action = actionMap.get(actionName); if (action == null) throw new IllegalArgumentException("No action registered for '" + actionName + "'"); perform(action, actionEvent); } public void enable(String actionName, boolean enable) { Action action = actionMap.get(actionName); if (action == null) throw new IllegalArgumentException("No action registered for '" + actionName + "'"); action.setEnabled(enable); } public void enableLocal(String globalName, String localName, boolean enable) { GlobalAction found = (GlobalAction) actionMap.get(globalName); if (found == null) throw new IllegalArgumentException("No action registered for '" + globalName + "'"); if(localName.equals(getLocalName())) found.setEnabled(enable); } static void perform(Action action, ActionEvent event) { count(preferences, RUN_COUNT_PREFERENCE + action.getValue(NAME)); action.actionPerformed(event); } private List<String> getActionsSortedByName() { List<String> result = new ArrayList<>(actionMap.keySet()); sort(result); return result; } public void logUsage() { StringBuilder builder = new StringBuilder(); for (String actionName : getActionsSortedByName()) { int runs = preferences.getInt(RUN_COUNT_PREFERENCE + actionName, 0); if (runs > 0) builder.append(format("%n%s, runs: %d", actionName, runs)); } log.info("Action usage:" + builder.toString()); } private static class ProxyAction implements Action, PropertyChangeListener { private Action delegate = null; private SwingPropertyChangeSupport changeSupport = new SwingPropertyChangeSupport(this); private ProxyAction() { } private ProxyAction(Action delegate) { this.delegate = delegate; } public void setDelegate(Action delegate) { if (this.delegate != null) delegate.removePropertyChangeListener(this); this.delegate = delegate; delegate.addPropertyChangeListener(this); } public void propertyChange(PropertyChangeEvent evt) { changeSupport.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); } public Object getValue(String key) { return delegate != null ? delegate.getValue(key) : null; } public void putValue(String key, Object value) { if (delegate != null) delegate.putValue(key, value); } public boolean isEnabled() { return delegate == null || delegate.isEnabled(); } public void setEnabled(boolean enabled) { if (delegate != null) delegate.setEnabled(enabled); } public void addPropertyChangeListener(PropertyChangeListener listener) { changeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { changeSupport.removePropertyChangeListener(listener); } public void actionPerformed(ActionEvent e) { if(delegate != null) perform(delegate, e); } } }