/* * Copyright 2003-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.plugins.actions; import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; import gnu.trove.THashMap; import gnu.trove.THashSet; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public abstract class BaseKeymapChanges { private static final Logger LOG = LogManager.getLogger(BaseKeymapChanges.class); private static Map<Keymap, Set<String>> ourClearedActions = new THashMap<>(); private Map<String, Set<Shortcut>> myRemovedShortcuts = new THashMap<>(); private Map<String, Set<Shortcut>> myAddedComplexShortcuts = new THashMap<>(); private Map<String, Set<ShortcutWrapper>> mySimpleShortcuts = new THashMap<>(); private Map<String, Set<ComplexShortcut>> myComplexShortcuts = new THashMap<>(); private Keymap myKeymap; public abstract String getScheme(); //shortId is an id w/o parameter ids public void parameterizedActionCreated(String shortId, String longId, Object... params) { Keymap keymap = getKeymap(); if (keymap == null) { return; } Set<ComplexShortcut> complexShortcuts = myComplexShortcuts.get(shortId); if (complexShortcuts == null) { return; } for (ComplexShortcut cs : complexShortcuts) { for (Shortcut s : cs.getShortcutsFor(params)) { addShortcutToKeymap(longId, keymap, s); Set<Shortcut> added = myAddedComplexShortcuts.get(longId); if (added == null) { added = new THashSet<>(); myAddedComplexShortcuts.put(longId, added); } added.add(s); } } } public final void init() { Keymap keymap = getKeymap(); if (keymap == null) { return; } for (Entry<String, Set<ShortcutWrapper>> e : mySimpleShortcuts.entrySet()) { String key = e.getKey(); for (ShortcutWrapper s : e.getValue()) { addShortcutToKeymap(key, keymap, s.myShortcut, s.myRemove, s.myReplaceAll); } } } public final void dispose() { Keymap keymap = getKeymap(); if (keymap == null) { return; } //complex for (Entry<String, Set<Shortcut>> e : myAddedComplexShortcuts.entrySet()) { String key = e.getKey(); for (Shortcut s : e.getValue()) { keymap.removeShortcut(key, s); } } myAddedComplexShortcuts.clear(); //simple for (Entry<String, Set<ShortcutWrapper>> e : mySimpleShortcuts.entrySet()) { String key = e.getKey(); for (ShortcutWrapper s : e.getValue()) { keymap.removeShortcut(key, s.myShortcut); } } mySimpleShortcuts.clear(); //register old for (Entry<String, Set<Shortcut>> e : myRemovedShortcuts.entrySet()) { String key = e.getKey(); for (Shortcut s : e.getValue()) { keymap.addShortcut(key, s); } } myRemovedShortcuts.clear(); ourClearedActions.clear(); } protected void addSimpleShortcut(String id, ShortcutWrapper... s) { Set<ShortcutWrapper> shortcuts = mySimpleShortcuts.get(id); if (shortcuts == null) { shortcuts = new THashSet<>(); mySimpleShortcuts.put(id, shortcuts); } shortcuts.addAll(Arrays.asList(s)); } protected void addSimpleShortcut(String id, Shortcut... s) { ShortcutWrapper[] sw = new ShortcutWrapper[s.length]; for (int i = 0; i < s.length; i++) { sw[i] = new ShortcutWrapper(s[i]); } addSimpleShortcut(id, sw); } protected void addComplexShortcut(String id, ComplexShortcut... s) { Set<ComplexShortcut> shortcuts = myComplexShortcuts.get(id); if (shortcuts == null) { shortcuts = new THashSet<>(); myComplexShortcuts.put(id, shortcuts); } shortcuts.addAll(Arrays.asList(s)); } private void addShortcutToKeymap(String longId, Keymap keymap, Shortcut s) { addShortcutToKeymap(longId, keymap, s, false, false); } private void addShortcutToKeymap(String longId, Keymap keymap, Shortcut s, boolean remove, boolean replaceAll) { Shortcut[] oldShortcuts = keymap.getShortcuts(longId); boolean isClear = oldShortcuts.length == 0; if (!isClear) { for (Set<String> set : ourClearedActions.values()) { if (set.contains(longId)) { isClear = true; break; } } } if (!isClear) { if (oldShortcuts.length != 0) { myRemovedShortcuts.put(longId, new THashSet<>(Arrays.asList(oldShortcuts))); keymap.removeAllActionShortcuts(longId); } } Set<String> actions = ourClearedActions.get(keymap); if (actions == null) { actions = new THashSet<>(); ourClearedActions.put(keymap, actions); } actions.add(longId); // Proceed as in class ActionManagerImpl in method processKeyboardShortcutNode if (remove) { keymap.removeShortcut(longId, s); } if (replaceAll) { keymap.removeAllActionShortcuts(longId); } if (!remove) { keymap.addShortcut(longId, s); } } private Keymap getKeymap() { if (myKeymap == null) { myKeymap = KeymapManager.getInstance().getKeymap(getScheme()); if (myKeymap == null) { LOG.error("keymap " + getScheme() + " is not found"); return null; } } return myKeymap; } protected static abstract class ComplexShortcut { public abstract List<Shortcut> getShortcutsFor(Object... params); public static class ParameterizedSimpleShortcut extends ComplexShortcut { private final List<Shortcut> myShortcut; public ParameterizedSimpleShortcut(Shortcut... shortcut) { myShortcut = Arrays.asList(shortcut); } @Override public List<Shortcut> getShortcutsFor(Object... params) { return myShortcut; } } } protected static class ShortcutWrapper { public final Shortcut myShortcut; public final boolean myRemove; public final boolean myReplaceAll; public ShortcutWrapper(Shortcut shortcut) { this(shortcut, false, false); } public ShortcutWrapper(Shortcut shortcut, boolean remove, boolean replaceAll) { myShortcut = shortcut; myRemove = remove; myReplaceAll = replaceAll; } } }