/* Keyboard class displays a settable keyboard provides information about keys, fingering, distances requires a specific keyboard image for display author: JAM (Jon A. Maxwell) email: jmaxwell@acm.vt.edu date: Mar 20 1998 */ import java.util.*; import java.awt.*; public class Keyboard extends Panel { // constants public static final int UPPERCASE = 1; public static final int LOWERCASE = 0; public static final int HOMEROW = 2; public static final int ROWS = 5; public static final int COLUMNS = 15; // defaults protected static final String defKeyFontName = "Courier"; protected static final int defKeyFontSize = 10; protected static final String defaultKeyboard[] = { // lowercase, uppercase "`1234567890-=\\", "~!@#$%^&*()_+|" , " qwertyuiop[]" , " QWERTYUIOP{}" , " asdfghjkl;'\n" , " ASDFGHJKL:\"\n", " zxcvbnm,./" , " ZXCVBNM<>?" , " " , "" }; protected static final String defaultFingering[] = { // left: 0123 right: 4567 thumb: 8 "00123344567777" , " 012334456777" , " 012334456777" , " 0123444567" , " 8" }; // data protected Image keyboardImage; protected Font keyFont; protected FontMetrics keyFontMetrics; protected Hashtable charToIndex; // convert from char to key index as Point(col,row) protected char key[][][] = new char[ROWS][COLUMNS][2 /*shift*/ ]; protected Rectangle keyArea[][] = new Rectangle[ROWS][COLUMNS]; // area of image protected Finger keyFinger[][] = new Finger[ROWS][COLUMNS]; // finger used for key protected Finger finger[]; // 0..3 left hand, 4..7 right hand, 8 thumb // constructor public Keyboard(Image image) { keyboardImage = image; keyFont = new Font(defKeyFontName, Font.PLAIN, defKeyFontSize); charToIndex = new Hashtable(200); setupKeys(); setupKeyAreas(); setupFingers(); } // public methods // lookup the finger used for a key public Finger closestFinger(int row, int col) { return keyFinger[row][col]; } // locate the key index (Point(col,row)) of a character public Point locate(char value) { return (Point) charToIndex.get( new Character(value) ); } // locate the key index (Point(col,row)) of a point on the keyboard image public Point locate(Point point) { // find letter at that point // .. use a better search if heavily used for (int row = 0; row rowEnd[row]) return false; return true; } // draw the keys protected void drawKeys(Graphics g) { // future: draw into offscreen image g.setColor(Color.black); g.setFont(keyFont); keyFontMetrics = g.getFontMetrics(); for (int row = 0; row < ROWS; row++) for (int col = 0; col < COLUMNS; col++) drawKey(g, row, col); } protected void drawKey(Graphics g, int row, int col) { Rectangle area = keyArea[row][col]; Point drawAt = new Point(0,0); char buf[] = new char[1]; if (key[row][col][0] == 0 && key[row][col][1] == 0) return; int topY = area.y + 2; int bottomY = area.y + keyHeight - 4; Point center = new Point(area.x + keyWidth/2 ,(topY + bottomY) / 2); if (Character.toUpperCase(key[row][col][0]) == key[row][col][1]) { // draw in middle buf[0] = key[row][col][1]; drawAt = new Point(center.x - keyFontMetrics.charWidth(buf[0])/2, center.y + keyFontMetrics.getHeight()/2 ); g.drawChars(buf,0,1,drawAt.x, drawAt.y); } else { // draw upper buf[0] = key[row][col][1]; drawAt = new Point(center.x - keyFontMetrics.charWidth(buf[0])/2, center.y - 1 ); g.drawChars(buf,0,1,drawAt.x, drawAt.y); // draw lower buf[0] = key[row][col][0]; drawAt = new Point(center.x - keyFontMetrics.charWidth(buf[0])/2, bottomY ); g.drawChars(buf,0,1,drawAt.x, drawAt.y); } } // setup // create fingers, assign keys a finger private void setupFingers() { int i; finger = new Finger[9]; for (i=0; i<4; i++) {finger[i] = new Finger(HOMEROW, i+1, Finger.LEFTHAND, i);} for (i=4; i<8; i++) {finger[i] = new Finger(HOMEROW, i+3, Finger.RIGHTHAND, i-4);} finger[8] = new Finger(HOMEROW+2, 1, Finger.RIGHTHAND, Finger.THUMB); //thumb on spacebar for (int row = 0; row < defaultFingering.length; row++) for (int col = 0; col < defaultFingering[row].length(); col++) { char c = defaultFingering[row].charAt(col); if (!Character.isDigit(c)) keyFinger[row][col] = null; else keyFinger[row][col] = finger[Character.digit(c,10)]; } } // assign the default keymap private void setupKeys() { for (int i=0; i < defaultKeyboard.length; i+=2) { setRow(i/2,Keyboard.LOWERCASE, defaultKeyboard[i]); setRow(i/2,Keyboard.UPPERCASE, defaultKeyboard[i+1]); } } // image-specific setup // Keyboard image data // upper-leftmost key private static final int row0X = 12; private static final int row0Y = 45; private static final Dimension imageDim = new Dimension(300,200); // private static final int keyHeight = 22; private static final int keyWidth = 18; private static final int tabWidth = 28; private static final int lockWidth = 34; private static final int shiftWidth = 26; private static final int toSpaceWidth = 72; // private static final int spaceWidth = 126; //about 7*keyWidth private static final int returnWidth = 36; //about 2*keyWidth // pixel distance in meters static final double DISTANCE_XPIXEL = 0.018 / keyWidth; static final double DISTANCE_YPIXEL = 0.018 / keyHeight; // set up image regions for keys private void setupKeyAreas() { keyArea[0][0] = new Rectangle(row0X, row0Y , keyWidth , keyHeight); keyArea[1][0] = new Rectangle(row0X, row0Y + keyHeight, tabWidth , keyHeight); keyArea[2][0] = new Rectangle(row0X, row0Y+2*keyHeight, lockWidth , keyHeight); keyArea[3][0] = new Rectangle(row0X, row0Y+3*keyHeight, shiftWidth , keyHeight); keyArea[4][0] = new Rectangle(row0X, row0Y+4*keyHeight, toSpaceWidth, keyHeight); //spacebar keyArea[4][1] = new Rectangle(keyArea[4][0].x + keyArea[4][0].width, keyArea[4][0].y, spaceWidth, keyHeight); for (int row = 0; row < ROWS; row++) for (int col = 1; col < COLUMNS; col++) if (keyArea[row][col] == null) { keyArea[row][col] = new Rectangle( keyArea[row][col-1].x + keyArea[row][col-1].width, keyArea[row][col-1].y, keyWidth, keyHeight ); } //return keyArea[2][12]= new Rectangle(keyArea[2][11].x + keyArea[2][11].width, keyArea[2][11].y, returnWidth, keyHeight); } }