Here you can find the source of stringToKeys(String s)
Parameter | Description |
---|---|
s | the string with keys |
null
if the string description is not valid
public static KeyStroke[] stringToKeys(String s)
//package com.java2s; /*//from w w w . j a v a 2 s .co m * #%L * The AIBench Plugin Manager Plugin * %% * Copyright (C) 2006 - 2016 Daniel Glez-Pe?a and Florentino Fdez-Riverola * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Lesser Public License for more details. * * You should have received a copy of the GNU General Lesser Public * License along with this program. If not, see * <http://www.gnu.org/licenses/lgpl-3.0.html>. * #L% */ import java.awt.GraphicsEnvironment; import java.awt.Toolkit; import java.awt.event.KeyEvent; import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.NoSuchElementException; import java.util.StringTokenizer; import javax.swing.KeyStroke; public class Main { private static final int CTRL_WILDCARD_MASK = 32768; private static final int ALT_WILDCARD_MASK = CTRL_WILDCARD_MASK * 2; /** Operating system is Windows NT. */ public static final int OS_WINNT = 1 << 0; /** Operating system is Windows 95. */ public static final int OS_WIN95 = OS_WINNT << 1; /** Operating system is Windows 98. */ public static final int OS_WIN98 = OS_WIN95 << 1; /** Operating system is Solaris. */ public static final int OS_SOLARIS = OS_WIN98 << 1; /** Operating system is Linux. */ public static final int OS_LINUX = OS_SOLARIS << 1; /** Operating system is HP-UX. */ public static final int OS_HP = OS_LINUX << 1; /** Operating system is IBM AIX. */ public static final int OS_AIX = OS_HP << 1; /** Operating system is SGI IRIX. */ public static final int OS_IRIX = OS_AIX << 1; /** Operating system is Sun OS. */ public static final int OS_SUNOS = OS_IRIX << 1; /** Operating system is Compaq TRU64 Unix */ public static final int OS_TRU64 = OS_SUNOS << 1; /** Operating system is OS/2. */ public static final int OS_OS2 = OS_TRU64 << 2; /** Operating system is Mac. */ public static final int OS_MAC = OS_OS2 << 1; /** Operating system is Windows 2000. */ public static final int OS_WIN2000 = OS_MAC << 1; /** Operating system is Compaq OpenVMS */ public static final int OS_VMS = OS_WIN2000 << 1; /** *Operating system is one of the Windows variants but we don't know which *one it is */ public static final int OS_WIN_OTHER = OS_VMS << 1; /** Operating system is unknown. */ public static final int OS_OTHER = OS_WIN_OTHER << 1; /** Operating system is FreeBSD * @since 4.50 */ public static final int OS_FREEBSD = OS_OTHER << 1; private static int operatingSystem = -1; /** reference to map that maps allowed key names to their values (String, Integer) and reference to map for mapping of values to their names */ private static Reference<Object> namesAndValues; /** Convert a space-separated list of Emacs-like key binding names to a list of Swing key strokes. * @param s the string with keys * @return array of key strokes, or <code>null</code> if the string description is not valid * @see #stringToKey */ public static KeyStroke[] stringToKeys(String s) { StringTokenizer st = new StringTokenizer( s.toUpperCase(Locale.ENGLISH), " "); // NOI18N ArrayList<KeyStroke> arr = new ArrayList<KeyStroke>(); while (st.hasMoreElements()) { s = st.nextToken(); KeyStroke k = stringToKey(s); if (k == null) { return null; } arr.add(k); } return arr.toArray(new KeyStroke[arr.size()]); } /** Construct a new key description from a given universal string * description. * Provides mapping between Emacs-like textual key descriptions and the * <code>KeyStroke</code> object used in Swing. * <P> * This format has following form: * <P><code>[C][A][S][M]-<em>identifier</em></code> * <p>Where: * <UL> * <LI> <code>C</code> stands for the Control key * <LI> <code>A</code> stands for the Alt key * <LI> <code>S</code> stands for the Shift key * <LI> <code>M</code> stands for the Meta key * </UL> * The format also supports two wildcard codes, to support differences in * platforms. These are the preferred choices for registering keystrokes, * since platform conflicts will automatically be handled: * <UL> * <LI> <code>D</code> stands for the default menu accelerator - the Control * key on most platforms, the Command (meta) key on Macintosh</LI> * <LI> <code>O</code> stands for the alternate accelerator - the Alt key on * most platforms, the Ctrl key on Macintosh (Macintosh uses Alt as a * secondary shift key for composing international characters - if you bind * Alt-8 to an action, a mac user with a French keyboard will not be able * to type the <code>[</code> character, which is a significant handicap</LI> * </UL> * If you use the wildcard characters, and specify a key which will conflict * with keys the operating system consumes, it will be mapped to whichever * choice can work - for example, on Macintosh, Command-Q is always consumed * by the operating system, so <code>D-Q</code> will always map to Control-Q. * <p> * Every modifier before the hyphen must be pressed. * <em>identifier</EM> can be any text constant from {@link KeyEvent} but * without the leading <code>VK_</code> characters. So {@link KeyEvent#VK_ENTER} is described as * <code>ENTER</code>. * * @param s the string with the description of the key * @return key description object, or <code>null</code> if the string does not represent any valid key */ public static KeyStroke stringToKey(String s) { StringTokenizer st = new StringTokenizer( s.toUpperCase(Locale.ENGLISH), "-", true); // NOI18N int needed = 0; HashMap names = initNameAndValues()[0]; int lastModif = -1; try { for (;;) { String el = st.nextToken(); // required key if (el.equals("-")) { // NOI18N if (lastModif != -1) { needed |= lastModif; lastModif = -1; } continue; } // if there is more elements if (st.hasMoreElements()) { // the text should describe modifiers lastModif = readModifiers(el); } else { // last text must be the key code Integer i = (Integer) names.get(el); boolean wildcard = (needed & CTRL_WILDCARD_MASK) != 0; //Strip out the explicit mask - KeyStroke won't know //what to do with it needed = needed & ~CTRL_WILDCARD_MASK; boolean macAlt = (needed & ALT_WILDCARD_MASK) != 0; needed = needed & ~ALT_WILDCARD_MASK; if (i != null) { //#26854 - Default accelerator should be Command on mac if (wildcard) { needed |= getMenuShortCutKeyMask(); if ((getOperatingSystem() & OS_MAC) != 0) { if (!usableKeyOnMac(i.intValue(), needed)) { needed &= ~getMenuShortCutKeyMask(); needed |= KeyEvent.CTRL_MASK; } } } if (macAlt) { if (getOperatingSystem() == OS_MAC) { needed |= KeyEvent.CTRL_MASK; } else { needed |= KeyEvent.ALT_MASK; } } return KeyStroke.getKeyStroke(i.intValue(), needed); } else { return null; } } } } catch (NoSuchElementException ex) { return null; } } /** Initialization of the names and values * @return array of two hashmaps first maps * allowed key names to their values (String, Integer) * and second * hashtable for mapping of values to their names (Integer, String) */ private static synchronized HashMap[] initNameAndValues() { if (namesAndValues != null) { HashMap[] arr = (HashMap[]) namesAndValues.get(); if (arr != null) { return arr; } } Field[] fields; // JW - fix Issue #353-swingx: play nicer inside sandbox. try { fields = KeyEvent.class.getDeclaredFields(); // fields = KeyEvent.class.getFields(); } catch (SecurityException e) { // JW: need to do better? What are the use-cases where we don't have // any access to the fields? fields = new Field[0]; } HashMap<String, Integer> names = new HashMap<String, Integer>( ((fields.length * 4) / 3) + 5, 0.75f); HashMap<Integer, String> values = new HashMap<Integer, String>( ((fields.length * 4) / 3) + 5, 0.75f); for (int i = 0; i < fields.length; i++) { if (Modifier.isStatic(fields[i].getModifiers())) { String name = fields[i].getName(); if (name.startsWith("VK_")) { // NOI18N // exclude VK name = name.substring(3); try { int numb = fields[i].getInt(null); Integer value = new Integer(numb); names.put(name, value); values.put(value, name); } catch (IllegalArgumentException ex) { } catch (IllegalAccessException ex) { } } } } if (names.get("CONTEXT_MENU") == null) { // NOI18N Integer n = new Integer(0x20C); names.put("CONTEXT_MENU", n); // NOI18N values.put(n, "CONTEXT_MENU"); // NOI18N n = new Integer(0x20D); names.put("WINDOWS", n); // NOI18N values.put(n, "WINDOWS"); // NOI18N } HashMap[] arr = { names, values }; namesAndValues = new SoftReference<Object>(arr); return arr; } /** Reads for modifiers and creates integer with required mask. * @param s string with modifiers * @return integer with mask * @exception NoSuchElementException if some letter is not modifier */ private static int readModifiers(String s) throws NoSuchElementException { int m = 0; for (int i = 0; i < s.length(); i++) { switch (s.charAt(i)) { case 'C': m |= KeyEvent.CTRL_MASK; break; case 'A': m |= KeyEvent.ALT_MASK; break; case 'M': m |= KeyEvent.META_MASK; break; case 'S': m |= KeyEvent.SHIFT_MASK; break; case 'D': m |= CTRL_WILDCARD_MASK; break; case 'O': m |= ALT_WILDCARD_MASK; break; default: throw new NoSuchElementException(s); } } return m; } /** * need to guard against headlessExceptions when testing. * @return the acceletor mask for shortcuts. */ private static int getMenuShortCutKeyMask() { if (GraphicsEnvironment.isHeadless()) { return ((getOperatingSystem() & OS_MAC) != 0) ? KeyEvent.META_MASK : KeyEvent.CTRL_MASK; } return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); } /** Get the operating system on which NetBeans is running. * @return one of the <code>OS_*</code> constants (such as {@link #OS_WINNT}) */ public static int getOperatingSystem() { if (operatingSystem == -1) { String osName = System.getProperty("os.name"); if ("Windows NT".equals(osName)) { // NOI18N operatingSystem = OS_WINNT; } else if ("Windows 95".equals(osName)) { // NOI18N operatingSystem = OS_WIN95; } else if ("Windows 98".equals(osName)) { // NOI18N operatingSystem = OS_WIN98; } else if ("Windows 2000".equals(osName)) { // NOI18N operatingSystem = OS_WIN2000; } else if (osName.startsWith("Windows ")) { // NOI18N operatingSystem = OS_WIN_OTHER; } else if ("Solaris".equals(osName)) { // NOI18N operatingSystem = OS_SOLARIS; } else if (osName.startsWith("SunOS")) { // NOI18N operatingSystem = OS_SOLARIS; } // JDK 1.4 b2 defines os.name for me as "Redhat Linux" -jglick else if (osName.endsWith("Linux")) { // NOI18N operatingSystem = OS_LINUX; } else if ("HP-UX".equals(osName)) { // NOI18N operatingSystem = OS_HP; } else if ("AIX".equals(osName)) { // NOI18N operatingSystem = OS_AIX; } else if ("Irix".equals(osName)) { // NOI18N operatingSystem = OS_IRIX; } else if ("SunOS".equals(osName)) { // NOI18N operatingSystem = OS_SUNOS; } else if ("Digital UNIX".equals(osName)) { // NOI18N operatingSystem = OS_TRU64; } else if ("OS/2".equals(osName)) { // NOI18N operatingSystem = OS_OS2; } else if ("OpenVMS".equals(osName)) { // NOI18N operatingSystem = OS_VMS; } else if (osName.equals("Mac OS X")) { // NOI18N operatingSystem = OS_MAC; } else if (osName.startsWith("Darwin")) { // NOI18N operatingSystem = OS_MAC; } else if (osName.toLowerCase(Locale.US).startsWith("freebsd")) { // NOI18N operatingSystem = OS_FREEBSD; } else { operatingSystem = OS_OTHER; } } return operatingSystem; } private static boolean usableKeyOnMac(int key, int mask) { //All permutations fail for Q except ctrl if (key == KeyEvent.VK_Q) { return false; } boolean isMeta = ((mask & KeyEvent.META_MASK) != 0) || ((mask & KeyEvent.CTRL_DOWN_MASK) != 0); boolean isAlt = ((mask & KeyEvent.ALT_MASK) != 0) || ((mask & KeyEvent.ALT_DOWN_MASK) != 0); boolean isOnlyMeta = isMeta && ((mask & ~(KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK)) == 0); //Mac OS consumes keys Command+ these keys - the app will never see //them, so CTRL should not be remapped for these if (isOnlyMeta) { return (key != KeyEvent.VK_H) && (key != KeyEvent.VK_SPACE) && (key != KeyEvent.VK_TAB); } else return !((key == KeyEvent.VK_D) && isMeta && isAlt); } }