/*
* Copyright 2003-2013 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.editor.runtime.cells;
import jetbrains.mps.openapi.editor.cells.KeyMap;
import jetbrains.mps.openapi.editor.cells.KeyMapAction;
import jetbrains.mps.util.Pair;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* User: shatalin
* Date: 2/8/13
*/
public class KeyMapImpl implements KeyMap {
private boolean myApplicableToEveryModel = false;
private List<KeyMap> myChildKeyMaps;
private HashMap<ActionKey, KeyMapAction> myActionMap = new HashMap<ActionKey, KeyMapAction>();
private List<Pair<ActionKey, KeyMapAction>> myDuplicatedActionList;
@Override
public boolean isApplicableToEveryModel() {
return myApplicableToEveryModel;
}
public void setApplicableToEveryModel(boolean isApplicable) {
myApplicableToEveryModel = isApplicable;
}
@Override
public void addKeyMap(KeyMap keyMap) {
if (myChildKeyMaps == null) {
myChildKeyMaps = new LinkedList<KeyMap>();
}
myChildKeyMaps.add(keyMap);
}
@Override
public void putAction(String modifiers, String keyCode, KeyMapAction action) {
boolean keyTyped = keyCode.length() == 1;
ActionKey key = new ActionKey(modifiers, keyCode, keyTyped);
if (!myActionMap.containsKey(key)) {
myActionMap.put(key, action);
} else {
if (myDuplicatedActionList == null) {
myDuplicatedActionList = new LinkedList<Pair<ActionKey, KeyMapAction>>();
}
myDuplicatedActionList.add(new Pair<ActionKey, KeyMapAction>(key, action));
}
}
@Override
public Collection<KeyMapAction> getActions(Collection<ActionKey> keys) {
return getActions(keys, new ArrayList<KeyMapAction>());
}
private Collection<KeyMapAction> getActions(Collection<KeyMap.ActionKey> keys, Collection<KeyMapAction> result) {
for (ActionKey actionKey : keys) {
KeyMapAction action = myActionMap.get(actionKey);
if (action != null) {
result.add(action);
if (myDuplicatedActionList != null) {
for (Pair<ActionKey, KeyMapAction> pair : myDuplicatedActionList) {
if (pair.o1.equals(actionKey)) {
result.add(pair.o2);
}
}
}
}
}
if (myChildKeyMaps != null) {
for (KeyMap childKeyMap : myChildKeyMaps) {
if (childKeyMap instanceof KeyMapImpl) {
((KeyMapImpl) childKeyMap).getActions(keys, result);
} else {
result.addAll(childKeyMap.getActions(keys));
}
}
}
return result;
}
@Override
public Collection<KeyMapAction> getAllActions() {
return getAllActions(new ArrayList<KeyMapAction>());
}
private Collection<KeyMapAction> getAllActions(Collection<KeyMapAction> result) {
result.addAll(myActionMap.values());
if (myDuplicatedActionList != null) {
for (Pair<ActionKey, KeyMapAction> pair : myDuplicatedActionList) {
result.add(pair.o2);
}
}
if (myChildKeyMaps != null) {
for (KeyMap childKeyMap : myChildKeyMaps) {
if (childKeyMap instanceof KeyMapImpl) {
((KeyMapImpl) childKeyMap).getAllActions(result);
} else {
result.addAll(childKeyMap.getAllActions());
}
}
}
return result;
}
@Override
public Collection<ActionKey> getActionKeys() {
return getActionKeys(new HashSet<ActionKey>());
}
private Collection<ActionKey> getActionKeys(Set<ActionKey> result) {
result.addAll(myActionMap.keySet());
if (myChildKeyMaps != null) {
for (KeyMap childKeyMap : myChildKeyMaps) {
if (childKeyMap instanceof KeyMapImpl) {
((KeyMapImpl) childKeyMap).getActionKeys(result);
} else {
result.addAll(childKeyMap.getActionKeys());
}
}
}
return result;
}
}