001 /*
002 * Created on Mar 26, 2008
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005 * the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011 * specific language governing permissions and limitations under the License.
012 *
013 * Copyright @2008-2010 the original author or authors.
014 */
015 package org.fest.swing.keystroke;
016
017 import static java.awt.event.InputEvent.SHIFT_MASK;
018 import static java.awt.event.KeyEvent.CHAR_UNDEFINED;
019 import static org.fest.swing.util.Platform.osFamily;
020
021 import java.util.Locale;
022
023 import javax.swing.KeyStroke;
024
025 import org.fest.util.VisibleForTesting;
026
027 /**
028 * Understands a collection of <code>{@link KeyStrokeMapping}</code>.
029 *
030 * @author Yvonne Wang
031 * @author Alex Ruiz
032 */
033 public class KeyStrokeMap {
034
035 private static KeyStrokeMapCollection maps = new KeyStrokeMapCollection();
036
037 static {
038 reloadFromSystemSettings();
039 }
040
041 /**
042 * Reloads the key stroke mappings for the language from the default locale.
043 * @deprecated use <code>{@link #reloadFromSystemSettings()}</code> instead.
044 */
045 @Deprecated
046 public static void reloadFromLocale() {
047 reloadFromSystemSettings();
048 }
049
050 /**
051 * Reloads the key stroke mappings for the language using the current system settings.
052 * @since 1.2
053 */
054 public static void reloadFromSystemSettings() {
055 KeyStrokeMappingProviderPicker picker = new KeyStrokeMappingProviderPicker();
056 maps.clear();
057 addKeyStrokesFrom(picker.providerFor(osFamily(), Locale.getDefault()));
058 }
059
060 @VisibleForTesting
061 static void updateKeyStrokeMapCollection(KeyStrokeMapCollection c) {
062 maps = c;
063 }
064
065 /**
066 * Adds the collection of <code>{@link KeyStrokeMapping}</code>s from the given
067 * <code>{@link KeyStrokeMappingProvider}</code> to this map.
068 * @param provider the given <code>KeyStrokeMappingProvider</code>.
069 */
070 public static void addKeyStrokesFrom(KeyStrokeMappingProvider provider) {
071 for (KeyStrokeMapping entry : provider.keyStrokeMappings())
072 add(entry.character(), entry.keyStroke());
073 }
074
075 private static void add(Character character, KeyStroke keyStroke) {
076 maps.add(character, keyStroke);
077 }
078
079 /**
080 * Removes all the character-<code>{@link KeyStroke}</code> mappings.
081 */
082 public static void clearKeyStrokes() {
083 maps.clear();
084 }
085
086 /**
087 * Indicates whether <code>{@link KeyStrokeMap}</code> has mappings or not.
088 * @return <code>true</code> if it has mappings, <code>false</code> otherwise.
089 */
090 public static boolean hasKeyStrokes() {
091 return !maps.isEmpty();
092 }
093
094 /**
095 * Returns the <code>{@link KeyStroke}</code> corresponding to the given character, as best we can guess it, or
096 * <code>null</code> if we don't know how to generate it.
097 * @param character the given character.
098 * @return the key code-based <code>KeyStroke</code> corresponding to the given character, or <code>null</code> if
099 * we cannot generate it.
100 */
101 public static KeyStroke keyStrokeFor(char character) {
102 return maps.keyStrokeFor(character);
103 }
104
105 /**
106 * Given a <code>{@link KeyStroke}</code>, returns the equivalent character. Key strokes are defined properly for
107 * US keyboards only. To contribute your own, please add them using the method
108 * <code>{@link #addKeyStrokesFrom(KeyStrokeMappingProvider)}</code>.
109 * @param keyStroke the given <code>KeyStroke</code>.
110 * @return KeyEvent.VK_UNDEFINED if the result is unknown.
111 */
112 public static char charFor(KeyStroke keyStroke) {
113 Character character = maps.charFor(keyStroke);
114 // Try again, but strip all modifiers but shift
115 if (character == null) character = charWithoutModifiersButShift(keyStroke);
116 if (character == null) return CHAR_UNDEFINED;
117 return character.charValue();
118 }
119
120 private static Character charWithoutModifiersButShift(KeyStroke keyStroke) {
121 int mask = keyStroke.getModifiers() & ~SHIFT_MASK;
122 return maps.charFor(KeyStroke.getKeyStroke(keyStroke.getKeyCode(), mask));
123 }
124
125 private KeyStrokeMap() {}
126 }