/** * 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. * * Copyright 2012-2015 the original author or authors. */ package org.assertj.swing.keystroke; import static java.awt.event.InputEvent.SHIFT_MASK; import static java.awt.event.KeyEvent.CHAR_UNDEFINED; import static org.assertj.swing.util.Platform.osFamily; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.swing.KeyStroke; import org.assertj.core.util.VisibleForTesting; /** * A collection of {@link KeyStrokeMapping}. * * @author Yvonne Wang * @author Alex Ruiz */ public class KeyStrokeMap { private static KeyStrokeMapCollection maps = new KeyStrokeMapCollection(); static { reloadFromSystemSettings(); } /** * Reloads the key stroke mappings for the language using the current system settings. */ public static void reloadFromSystemSettings() { KeyStrokeMappingProviderPicker picker = new KeyStrokeMappingProviderPicker(); maps.clear(); addKeyStrokesFrom(picker.providerFor(osFamily(), KeyStrokeLocale.get())); } @VisibleForTesting static void updateKeyStrokeMapCollection(@Nonnull KeyStrokeMapCollection c) { maps = c; } /** * Adds the collection of {@link KeyStrokeMapping}s from the given {@link KeyStrokeMappingProvider} to this map. * * @param provider the given {@code KeyStrokeMappingProvider}. */ public static void addKeyStrokesFrom(@Nonnull KeyStrokeMappingProvider provider) { for (KeyStrokeMapping entry : provider.keyStrokeMappings()) { add(entry.character(), entry.keyStroke()); } } private static void add(@Nonnull Character character, @Nonnull KeyStroke keyStroke) { maps.add(character, keyStroke); } /** * Removes all the character-{@code KeyStroke} mappings. */ public static void clearKeyStrokes() { maps.clear(); } /** * Indicates whether {@link KeyStrokeMap} has mappings. * * @return {@code true} if it has mappings, {@code false} otherwise. */ public static boolean hasKeyStrokes() { return !maps.isEmpty(); } /** * Returns the {@code KeyStroke} corresponding to the given character, as best we can guess it, or {@code null} if we * don't know how to generate it. * * @param character the given character. * @return the key code-based {@code KeyStroke} corresponding to the given character, or {@code null} if we cannot * generate it. */ public static @Nullable KeyStroke keyStrokeFor(char character) { return maps.keyStrokeFor(character); } /** * Given a {@link KeyStroke}, returns the equivalent character. Key strokes are defined properly for US keyboards * only. To contribute your own, please add them using the method {@link #addKeyStrokesFrom(KeyStrokeMappingProvider)} * . * * @param keyStroke the given {@code KeyStroke}. * @return {@code KeyEvent.VK_UNDEFINED} if the result is unknown. */ public static char charFor(@Nonnull KeyStroke keyStroke) { Character character = maps.charFor(keyStroke); // Try again, but strip all modifiers but shift if (character == null) { character = charWithoutModifiersButShift(keyStroke); } if (character == null) { return CHAR_UNDEFINED; } return character; } private static @Nullable Character charWithoutModifiersButShift(@Nonnull KeyStroke keyStroke) { int mask = keyStroke.getModifiers() & ~SHIFT_MASK; return maps.charFor(KeyStroke.getKeyStroke(keyStroke.getKeyCode(), mask)); } private KeyStrokeMap() { } }