package edu.cmu.cs.hcii.cogtool.util;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
public class Keypad extends WindowUtil.SimpleDialog
{
public static final int FULL_KEYPAD = 1;
public static final int NUMPAD_ONLY = 2;
public static final int FULL_WIDTH = 935;
public static final int NUMPAD_WIDTH = 150;
public static final String SHIFT_KEY =
L10N.get("KEYPAD.SHIFT", "SHIFT");
public static final String CAPS_KEY =
L10N.get("KEYPAD.CAPS_LOCK", "CAPS");
public static final String SPACE_KEY =
L10N.get("KEYPAD.SPACE", "SPACE");
public static final String BS_KEY =
L10N.get("KEYPAD.BACKSPACE", "BACKSPACE");
public static final String ENTER_KEY =
L10N.get("KEYPAD.ENTER", "Enter");
public static final String CANCEL_KEY =
L10N.get("KEYPAD.CANCEL", "Cancel");
protected static Color disabledColor = null;
protected static Color defaultBGColor = null;
protected Color getDisabledColor()
{
if (disabledColor == null) {
disabledColor =
dialog.getDisplay().getSystemColor(SWT.COLOR_GRAY);
}
return disabledColor;
}
protected Color getDefaultBGColor()
{
if (defaultBGColor == null) {
defaultBGColor =
dialog.getDisplay().getSystemColor(SWT.COLOR_WHITE);
}
return defaultBGColor;
}
protected class ButtonHitDetection implements SelectionListener
{
public void widgetSelected(SelectionEvent event)
{
if (shift) {
shift = ! shift;
}
String buttonLabel = ((Button) event.getSource()).getText();
if (buttonLabel.equals(SHIFT_KEY)) {
shift = ! shift;
// redisplayKeys();
}
else if (buttonLabel.equals(CAPS_KEY)) {
capsLock = ! capsLock;
// redisplayKeys();
}
else if (buttonLabel.equals(SPACE_KEY)) {
enteredText.append(" ");
}
else if (buttonLabel.equals(BS_KEY)) {
String text = enteredText.getText();
int currentLen = text.length();
if (enteredText.getSelectionCount() == 0) {
enteredText.setText(text.substring(0, currentLen - 1));
enteredText.setSelection(currentLen - 1);
}
else {
Point sel = enteredText.getSelection();
String tail = (currentLen == sel.y)
? ""
: text.substring(sel.y, currentLen - 1);
enteredText.setText(text.substring(0, sel.x).concat(tail));
enteredText.setSelection(sel.x);
}
}
else if (buttonLabel.equals("&&")) {
enteredText.append("&");
}
else {
enteredText.append(buttonLabel);
}
if (keypadType == FULL_KEYPAD) {
redisplayKeys();
}
}
public void widgetDefaultSelected(SelectionEvent evt)
{
widgetSelected(evt);
}
}
protected SelectionListener hitDetection = new ButtonHitDetection();
protected static final String keysRow1[] =
{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=" };
protected static final String keysRow2[] =
{ "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\" };
protected static final String keysRow3[] =
{ "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'" };
protected static final String keysRow4[] =
{ "z", "x", "c", "v", "b", "n", "m", ",", ".", "/" };
protected static final String keysRow1_shift[] =
{ "!", "@", "#", "$", "%", "^", "&&", "*", "(", ")", "_", "+" };
protected static final String keysRow2_shift[] =
{ "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "{", "}", "|" };
protected static final String keysRow3_shift[] =
{ "A", "S", "D", "F", "G", "H", "J", "K", "L", ":", "\"" };
protected static final String keysRow4_shift[] =
{ "Z", "X", "C", "V", "B", "N", "M", "<", ">", "?" };
protected static final String numberKeys[] =
{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "0", ".", BS_KEY };
protected Button letterButtons[] =
new Button[keysRow1.length + keysRow2.length
+ keysRow3.length
+ keysRow4.length];
protected boolean shift = false;
protected boolean capsLock = false;
protected int keypadType;
protected Text enteredText;
public Keypad(String title, int mode, int type)
{
super(title, mode);
keypadType = type;
}
protected Button makeButton(Composite parent,
String buttonLabel,
GridData gridKeysOption)
{
return makeButton(parent,
buttonLabel,
gridKeysOption,
hitDetection);
}
protected Button makeButton(Composite parent,
String buttonLabel,
GridData gridKeysOption,
SelectionListener listener)
{
Button keypadButton = new Button(parent, SWT.PUSH);
keypadButton.setText(buttonLabel);
keypadButton.setFont(FontUtils.DEFAULT_FONT);
keypadButton.setLayoutData(gridKeysOption);
keypadButton.addSelectionListener(listener);
return keypadButton;
}
/**
* Creates and lays out the buttons for the keypad's letter keys.
*
* @author Paul Rubritz (ptr@andrew.cmu.edu)
*/
protected void makeLetters()
{
Composite letters = new Composite(dialog, SWT.NONE);
GridLayout grid = new GridLayout();
grid.numColumns = 13;
letters.setLayout(grid);
GridData gridKeysOption;
int row = 1;
int rowLength = keysRow1.length;
int buttonCount = 0;
for (int i = 0; i < rowLength; i++) {
String buttonLabel = "";
gridKeysOption = new GridData();
gridKeysOption.widthHint = 50;
gridKeysOption.heightHint = 50;
switch (row) {
case 1: {
buttonLabel = keysRow1[i];
break;
}
case 2: {
buttonLabel = keysRow2[i];
break;
}
case 3: {
buttonLabel = keysRow3[i];
break;
}
case 4: {
buttonLabel = keysRow4[i];
break;
}
}
if (i == rowLength - 1) {
row++;
switch (row) {
case 2: {
rowLength = keysRow2.length;
i = -1;
gridKeysOption.horizontalSpan = 2;
break;
}
case 3: {
rowLength = keysRow3.length;
i = -1;
break;
}
case 4: {
rowLength = keysRow4.length;
i = -1;
gridKeysOption.horizontalSpan = 3;
break;
}
case 5: {
gridKeysOption.horizontalSpan = 4;
break;
}
default: {
break;
}
}
}
letterButtons[buttonCount++] =
makeButton(letters, buttonLabel, gridKeysOption);
}
/* shift button */
gridKeysOption = new GridData();
gridKeysOption.horizontalSpan = 2;
gridKeysOption.widthHint = 105;
gridKeysOption.heightHint = 50;
makeButton(letters, SHIFT_KEY, gridKeysOption);
/* caps lock button */
gridKeysOption = new GridData();
gridKeysOption.horizontalSpan = 2;
gridKeysOption.widthHint = 105;
gridKeysOption.heightHint = 50;
makeButton(letters, CAPS_KEY, gridKeysOption);
/* space bar button */
gridKeysOption = new GridData();
gridKeysOption.horizontalSpan = 6;
gridKeysOption.widthHint = 325;
gridKeysOption.heightHint = 50;
makeButton(letters, SPACE_KEY, gridKeysOption);
/* backspace button */
gridKeysOption = new GridData();
gridKeysOption.horizontalSpan = 3;
gridKeysOption.widthHint = 160;
gridKeysOption.heightHint = 50;
makeButton(letters, BS_KEY, gridKeysOption);
}
/**
* Creates and lays out the buttons for the keypad's number pad.
*
* @author Paul Rubritz (ptr@andrew.cmu.edu)
*/
protected void makeNumbers()
{
GridLayout grid = new GridLayout();
grid.numColumns = 3;
GridData gridKeysOption = new GridData();
gridKeysOption.horizontalIndent =
(keypadType == FULL_KEYPAD) ? 60 : 0;
gridKeysOption.verticalAlignment = SWT.TOP;
Composite numbers = new Composite(dialog, SWT.NONE);
numbers.setLayoutData(gridKeysOption);
numbers.setLayout(grid);
Button keypadButton;
for (int i = 0; i < numberKeys.length; i++) {
gridKeysOption = new GridData();
if (i < numberKeys.length - 1) {
gridKeysOption.widthHint = 50;
}
else if (keypadType == NUMPAD_ONLY) {
gridKeysOption.widthHint = 160;
gridKeysOption.horizontalSpan = 3;
}
else {
break;
}
gridKeysOption.heightHint = 50;
keypadButton = makeButton(numbers, numberKeys[i], gridKeysOption);
// TODO: This must be dependent upon the invocation context
// (see IntegerEntry)
if ((keypadType == NUMPAD_ONLY) &&
numberKeys[i].equals("-"))
{
keypadButton.setBackground(getDisabledColor());
keypadButton.setEnabled(false);
}
}
}
/**
* Creates and lays out the elements for the keypad's enter/cancel box.
*
* @author Paul Rubritz (ptr@andrew.cmu.edu)
*/
protected void makeEntry()
{
GridLayout grid = new GridLayout();
grid.numColumns = 3;
GridData gridKeysOption = new GridData();
gridKeysOption.horizontalSpan = 2;
Composite entry = new Composite(dialog, SWT.NONE);
entry.setLayoutData(gridKeysOption);
entry.setLayout(grid);
int width =
(keypadType == FULL_KEYPAD) ? FULL_WIDTH : NUMPAD_WIDTH;
/* text input box */
enteredText = new Text(entry, SWT.NONE);
enteredText.setFont(FontUtils.DEFAULT_FONT);
gridKeysOption = new GridData();
gridKeysOption.horizontalSpan = 3;
gridKeysOption.widthHint = width;
gridKeysOption.heightHint = 100;
enteredText.setLayoutData(gridKeysOption);
enteredText.setBackground(getDefaultBGColor());
enteredText.addKeyListener(new KeyAdapter()
{
@Override
public void keyPressed(KeyEvent evt)
{
if (evt.keyCode == SWT.ESC) {
userResponse = null;
dialog.close();
}
}
});
/* enter button */
gridKeysOption = new GridData();
gridKeysOption.verticalIndent = 10;
gridKeysOption.horizontalSpan = 2;
gridKeysOption.widthHint = width / 2;
gridKeysOption.heightHint = 75;
gridKeysOption.horizontalAlignment = SWT.RIGHT;
SelectionListener listener =
new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent event)
{
userResponse = enteredText.getText();
dialog.close();
}
};
makeButton(entry, ENTER_KEY, gridKeysOption, listener);
/* cancel button */
gridKeysOption = new GridData();
gridKeysOption.verticalIndent = 10;
gridKeysOption.horizontalSpan = 1;
gridKeysOption.widthHint = width / 2;
gridKeysOption.heightHint = 75;
gridKeysOption.horizontalAlignment = SWT.RIGHT;
listener =
new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent event)
{
userResponse = null;
dialog.close();
}
};
makeButton(entry, CANCEL_KEY, gridKeysOption, listener);
}
/**
* Displays appropriate changes to keys when shift or caps lock is pressed.
*
* @author Paul Rubritz (ptr@andrew.cmu.edu)
*/
public void redisplayKeys()
{
int btnIndex = 0;
int row = 1;
int rowLength = keysRow1.length;
for (int i = 0; i < rowLength; i++) {
Button keypadButton = letterButtons[btnIndex++];
if ((! shift && ! capsLock) ||
(capsLock && shift))
{
switch (row) {
case 1: {
keypadButton.setText(keysRow1[i]);
break;
}
case 2: {
keypadButton.setText(keysRow2[i]);
break;
}
case 3: {
keypadButton.setText(keysRow3[i]);
break;
}
case 4: {
keypadButton.setText(keysRow4[i]);
break;
}
}
}
else {
switch (row) {
case 1: {
keypadButton.setText(keysRow1_shift[i]);
break;
}
case 2: {
keypadButton.setText(keysRow2_shift[i]);
break;
}
case 3: {
keypadButton.setText(keysRow3_shift[i]);
break;
}
case 4: {
keypadButton.setText(keysRow4_shift[i]);
break;
}
}
}
if (i == rowLength - 1) {
row++;
switch (row) {
case 2: {
rowLength = keysRow2.length;
i = -1;
break;
}
case 3: {
rowLength = keysRow3.length;
i = -1;
break;
}
case 4: {
rowLength = keysRow4.length;
i = -1;
break;
}
default: {
break;
}
}
}
}
}
@Override
protected void buildDialog()
{
GridLayout grid = new GridLayout();
switch (keypadType) {
case FULL_KEYPAD: {
grid.numColumns = 2;
makeLetters();
makeNumbers();
makeEntry();
break;
}
case NUMPAD_ONLY: {
grid.numColumns = 1;
makeNumbers();
makeEntry();
break;
}
}
dialog.setLayout(grid);
}
}