/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.rc.swt.driver; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import org.eclipse.jubula.rc.common.exception.RobotException; import org.eclipse.jubula.rc.common.logger.AutServerLogger; import org.eclipse.swt.SWT; /** * @author BREDEX GmbH * @created 12.07.2007 */ public class KeyboardHelper { /** the logger */ private static AutServerLogger log = new AutServerLogger( KeyboardHelper.class); /** * The delimiter (+). */ private static final String DELIMITER = "+"; //$NON-NLS-1$ /** * shift */ private static final String SHIFT = "shift"; //$NON-NLS-1$ /** * ctrl */ private static final String CTRL = "ctrl"; //$NON-NLS-1$ /** * alt */ private static final String ALT = "alt"; //$NON-NLS-1$ /** * The keyboard mapping. * Key = character * Value = KeyStroke */ private Map<Character, KeyStroke> m_mapping = new HashMap<Character, KeyStroke>(); /** * Constructor * * @param layout The keyboard layout. */ public KeyboardHelper(Properties layout) { initKeyboardMapping(layout); } /** * Inits keyboard mapping * @param layout The keyboard layout. */ private void initKeyboardMapping(Properties layout) { final Iterator charsIter = layout.keySet().iterator(); while (charsIter.hasNext()) { final String origCharStr = (String)charsIter.next(); if (origCharStr.length() < 1) { final String msg = "Could not parse keyboard layout."; //$NON-NLS-1$ log.error(msg, new RobotException(new IOException(msg))); } final char origChar = origCharStr.charAt(0); final String mapping = ((String)layout.get(origCharStr)).toLowerCase(); final StringTokenizer tok = new StringTokenizer(mapping, DELIMITER); final char nativeChar = mapping.charAt(mapping.length() - 1); final KeyStroke keyStroke = new KeyStroke(nativeChar); while (tok.hasMoreTokens()) { final String modifier = tok.nextToken(); final int mod = getModifier(modifier); if (mod != 0) { keyStroke.addModifier(mod); } } m_mapping.put(new Character(origChar), keyStroke); } } /** * * @param modifier the modifier * @return the SWT constant of the given modifier or 0 if no SWT-modifier. */ private int getModifier(String modifier) { int mod = 0; if (CTRL.equals(modifier)) { mod = SWT.CTRL; } else if (SHIFT.equals(modifier)) { mod = SWT.SHIFT; } else if (ALT.equals(modifier)) { mod = SWT.ALT; } return mod; } /** * * @param character the charater * @return the KeyStroke for the given character. */ public KeyStroke getKeyStroke(char character) { KeyStroke keyStroke = null; if (Character.isUpperCase(character)) { final char lowChar = Character.toLowerCase(character); keyStroke = new KeyStroke(lowChar); keyStroke.addModifier(SWT.SHIFT); return keyStroke; } if (isSingleKey(character)) { return new KeyStroke(character); } keyStroke = m_mapping.get(new Character(character)); // if no KeyStroke was found, return a KeyStroke with the given // character and log in debug. // It is not necessarily an error, see method isSingleKey(char)! if (keyStroke == null && log.isDebugEnabled()) { log.debug("No keyboard-mapping found for character '" //$NON-NLS-1$ + String.valueOf(character) + "'!"); //$NON-NLS-1$ } return keyStroke != null ? keyStroke : new KeyStroke(character); } /** * @param character a char value * @return true if the given character can be entered via single keyboard * key (without modifiers), false otherwise. */ private boolean isSingleKey(char character) { // Some characters e.g. ,.-+# on de_DE-layout do not match here. // Is there a way to find it out? return Character.isLowerCase(character) || Character.isWhitespace(character) || (Character.isDigit(character)); } /** * KeyStroke * @author BREDEX GmbH * @created 13.07.2007 */ public static class KeyStroke { /** The character */ private char m_char = '0'; /** The List of modifiers */ private List<Integer> m_modifiers = new ArrayList<Integer>(3); /** * Constructor. * @param character the character without the modifiers. */ public KeyStroke(char character) { m_char = character; } /** * * @return the character without modifiers. */ public char getChar() { return m_char; } /** * * @return the modifier */ public Integer[] getModifiers() { return m_modifiers.toArray( new Integer[m_modifiers.size()]); } /** * Adds the given modifier to the KeyStroke. * @param modifier the modifier. */ public void addModifier(int modifier) { m_modifiers.add(new Integer(modifier)); } } }