blob: 4036b6a55dcf1c29c40829de81d2176d96719c1c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 SWTBot Committers and others.
* 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:
* Ketan Padegaonkar - initial API and implementation
*******************************************************************************/
package org.eclipse.swtbot.swt.finder.keyboard;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferenceConstants;
import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
/**
* @author Ketan Padegaonkar <KetanPadegaonkar [at] gmail [dot] com>
* @version $Id$
*/
public class KeyboardLayoutGenerator {
private static Keyboard keyboard;
private static SWTBotText text;
private static FileWriter fileWriter;
private static CombinationGenerator<Integer> generator;
public static void main(String[] args) {
System.setProperty(SWTBotPreferenceConstants.KEY_KEYBOARD_LAYOUT, "org.eclipse.swtbot.swt.finder.keyboard.empty");
Display display = new Display();
keyboard = KeyboardFactory.getSWTKeyboard();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
final Text text = new Text(shell, SWT.MULTI | SWT.LEAD | SWT.BORDER);
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
createGenerator();
new Thread() {
@Override
public void run() {
SWTUtils.sleep(1000);
try {
typeKeystrokes(text);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
System.exit(0);
}
};
}.start();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static void typeKeystrokes(final Text text) throws IOException {
fileWriter = new FileWriter("keyboard.layout");
KeyboardLayoutGenerator.text = new SWTBotText(text);
for (char c : Keys.getInputs()) {
combination(c);
}
fileWriter.close();
}
private static void createGenerator() {
if (isMac()) {
generator = new CombinationGenerator<Integer>(4, SWT.ALT, SWT.SHIFT, SWT.CTRL, SWT.COMMAND);
} else {
generator = new CombinationGenerator<Integer>(3, SWT.ALT, SWT.SHIFT, SWT.CTRL);
}
}
private static void combination(char ch) {
Iterator<List<Integer>> iterator = generator.iterator();
while (iterator.hasNext()) {
List<Integer> combinationList = iterator.next();
Integer[] combination = combinationList.toArray(new Integer[combinationList.size()]);
int modificationKeys = or(combination);
KeyStroke[] keys;
try {
keys = Keystrokes.toKeys(modificationKeys, ch);
} catch (Exception e) {
// could not parse ch to a keystroke.
keys = new KeyStroke[] { KeyStroke.getInstance(0, ch) };
}
if (filter(keys))
continue;
text.setText("\n");
text.setFocus();
keyboard.pressShortcut(keys);
text.setFocus();
text.setText(text.getText().trim() + " " + KeyStroke.getInstance(modificationKeys, ch));
try {
fileWriter.write(text.getText());
fileWriter.write('\n');
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
private static boolean filter(KeyStroke[] keys) {
List<KeyStroke> list = Arrays.asList(keys);
return // quit
list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'Q')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'q')))
// logout
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND | SWT.ALT, 'Q')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND | SWT.ALT, 'q')))
// minimize
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'm')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'M')))
// screenshot
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND | SWT.SHIFT, '4')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND | SWT.CTRL | SWT.SHIFT, '4')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND | SWT.SHIFT, '3')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND | SWT.CTRL | SWT.SHIFT, '3')))
// hide
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'h')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'H')))
// paste
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'v')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'V')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.CTRL, 'v')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.CTRL, 'V')))
// cut
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'x')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.COMMAND, 'X')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.CTRL, 'x')))
|| list.equals(Arrays.asList(Keystrokes.toKeys(SWT.CTRL, 'X')))
//
;
}
private static boolean isMac() {
String swtPlatform = SWT.getPlatform();
return ("carbon".equals(swtPlatform) || "cocoa".equals(swtPlatform));
}
private static int or(Integer[] combination) {
int or = 0;
for (Integer integer : combination) {
or |= integer;
}
return or;
}
private static class CombinationGenerator<T> implements Iterable<List<T>> {
private final int r;
private final T[] values;
private ArrayList<List<T>> result;
/**
* @param r the number of elements in the combination
* @param values the values that should be combined.
*/
CombinationGenerator(int r, T... values) {
this.r = r;
this.values = values;
initialize();
}
private void initialize() {
result = new ArrayList<List<T>>();
for (int i = 1; i <= r; i++) {
FixedSizeCombinationGenerator<T> combinationGenerator = new FixedSizeCombinationGenerator<T>(i, values);
for (List<T> list : combinationGenerator) {
result.add(list);
}
}
}
public Iterator<List<T>> iterator() {
return result.iterator();
}
class FixedSizeCombinationGenerator<E> implements Iterator<List<E>>, Iterable<List<E>> {
private int[] a;
private int n;
private int r;
private BigInteger numLeft;
private BigInteger total;
private final E[] elements;
FixedSizeCombinationGenerator(int r, E... elements) {
this.elements = elements;
int n = elements.length;
if (r > n) {
throw new IllegalArgumentException();
}
if (n < 1) {
throw new IllegalArgumentException();
}
this.n = n;
this.r = r;
a = new int[r];
BigInteger nFact = getFactorial(n);
BigInteger rFact = getFactorial(r);
BigInteger nminusrFact = getFactorial(n - r);
total = nFact.divide(rFact.multiply(nminusrFact));
reset();
}
public void reset() {
for (int i = 0; i < a.length; i++) {
a[i] = i;
}
numLeft = new BigInteger(total.toString());
}
private BigInteger getFactorial(int n) {
BigInteger fact = BigInteger.ONE;
for (int i = n; i > 1; i--) {
fact = fact.multiply(new BigInteger(Integer.toString(i)));
}
return fact;
}
private int[] getIndices() {
if (numLeft.equals(total)) {
numLeft = numLeft.subtract(BigInteger.ONE);
return a;
}
int i = r - 1;
while (a[i] == n - r + i) {
i--;
}
a[i] = a[i] + 1;
for (int j = i + 1; j < r; j++) {
a[j] = a[i] + j - i;
}
numLeft = numLeft.subtract(BigInteger.ONE);
return a;
}
public boolean hasNext() {
return numLeft.compareTo(BigInteger.ZERO) == 1;
}
public List<E> next() {
ArrayList<E> arrayList = new ArrayList<E>();
int[] indices = getIndices();
for (int i = 0; i < indices.length; i++) {
arrayList.add(elements[indices[i]]);
}
return arrayList;
}
public void remove() {
throw new UnsupportedOperationException();
}
public Iterator<List<E>> iterator() {
return this;
}
}
}
}