// This file is part of Penn TotalRecall <http://memory.psych.upenn.edu/TotalRecall>.
//
// TotalRecall 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, version 3 only.
//
// TotalRecall 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 TotalRecall. If not, see <http://www.gnu.org/licenses/>.
package control;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.KeyStroke;
import scala.Option;
import behaviors.UpdatingAction;
import edu.upenn.psych.memory.shortcutmanager.Shortcut;
import edu.upenn.psych.memory.shortcutmanager.XAction;
import edu.upenn.psych.memory.shortcutmanager.XActionListener;
/**
* Storage class that associates <code>Objects</code> with {@link util.ActionIdentification} and <code>KeyStroke</code> objects.
*
* Used by <code>IdentifiedMultiActions</code> and <code>IdentifiedSingleActions</code> to automatically associate
* themselves with names, tooltips, and shortcuts.
*
* @author Yuvi Masory
*/
public class XActionManager {
public static class Pair<T, U> {
final T t;
final U u;
public Pair(T t, U u) {
this.t = t;
this.u = u;
}
}
private XActionManager() {}
private static HashMap<String, Set<UpdatingAction>> listenersMap = new HashMap<String, Set<UpdatingAction>>();
private static HashMap<String, XAction> xactionsMap = new HashMap<String, XAction>();
private static HashMap<String, ArrayList<Pair<Object, InputMap>>> inputMapMap = new HashMap<String, ArrayList<Pair<Object, InputMap>>>();
public static XActionListener listener = new XActionListener() {
@Override
public void xActionUpdated(XAction xact, Option<Shortcut> old) {
String id = xact.id();
xactionsMap.put(id, xact);
update(xact.id(), old);
}
};
public static KeyStroke lookup(UpdatingAction action, Enum<?> e) {
String id = makeId(action, e);
return lookup(id);
}
public static KeyStroke lookup(String id) {
XAction xact = xactionsMap.get(id);
if(xact != null) {
Shortcut shorty = xact.javaShortcut();
if(shorty != null) {
return shorty.stroke();
}
}
return null;
}
private static String makeId(UpdatingAction action, Enum<?> e) {
String id = action.getClass().getName();
if(e != null) {
String eName = e.name();
String[] parts = e.getClass().toString().split("\\$");
String eClass = parts[parts.length - 1];
id += "-" + eClass + "." + eName;
}
return id;
}
public static void registerInputMap(UpdatingAction action, Enum<?> e, String mapKey, InputMap map) {
String id = makeId(action, e);
if(inputMapMap.get(id) == null) {
inputMapMap.put(id, new ArrayList<Pair<Object, InputMap>>());
}
ArrayList<Pair<Object, InputMap>> pairs = inputMapMap.get(id);
pairs.add(new Pair<Object, InputMap>(mapKey, map));
}
public static void registerAction(UpdatingAction action, Enum<?> e) {
String id = makeId(action, e);
if(listenersMap.get(id) == null) {
listenersMap.put(id, new HashSet<UpdatingAction>());
}
listenersMap.get(id).add(action);
update(id, null);
}
private static void update(String id, Option<Shortcut> old) {
Set<UpdatingAction> actions = listenersMap.get(id);
XAction xact = xactionsMap.get(id);
if(xact != null) {
Shortcut shorty = xact.javaShortcut();
KeyStroke stroke = shorty == null ? null : shorty.stroke();
if (actions != null) {
for(UpdatingAction action: actions) {
action.putValue(Action.NAME, xact.name());
String tooltip = xact.javaTooltip();
action.putValue(Action.SHORT_DESCRIPTION, tooltip);
action.putValue(Action.ACCELERATOR_KEY, stroke);
}
}
ArrayList<Pair<Object, InputMap>> inputMapPairs = inputMapMap.get(id);
if(inputMapPairs != null) {
for(Pair<Object, InputMap> pair: inputMapPairs) {
InputMap inputMap = pair.u;
Shortcut oldShortcut;
if(old == null) {
oldShortcut = null;
}
else {
oldShortcut = old.isDefined() ? old.get() : null;
}
KeyStroke oldStroke = oldShortcut == null ? null : oldShortcut.stroke();
Object inputMapKey = pair.t;
if(oldStroke != null) {
inputMap.remove(oldStroke);
}
inputMap.put(stroke, inputMapKey);
}
}
}
}
}