0001 /*
0002 * KeyboardMap.java
0003 *
0004 * Copyright (c) 1998-2005, The University of Sheffield.
0005 *
0006 * This file is part of GATE (see http://gate.ac.uk/), and is free
0007 * software, licenced under the GNU Library General Public License,
0008 * Version 2, June1991.
0009 *
0010 * A copy of this licence is included in the distribution in the file
0011 * licence.html, and is also available at http://gate.ac.uk/gate/licence.html.
0012 *
0013 * Valentin Tablan, October 2000
0014 *
0015 * $Id: KeyboardMap.java 6491 2005-01-11 13:51:38Z ian $
0016 */
0017 package guk.im;
0018
0019 import java.awt.*;
0020 import java.awt.event.*;
0021 import java.util.*;
0022
0023 import javax.swing.*;
0024 import javax.swing.border.*;
0025
0026 /**
0027 * A virtual keyboard map. It uses its own thread do udate the display.
0028 *
0029 */
0030 public class KeyboardMap implements Runnable{
0031
0032 /**
0033 * Builds the keyboard map. Uses a window provided by the context of the input
0034 * method.
0035 *
0036 * @param im the input method
0037 * @param handler the active Locale handler
0038 * @param state the state of the handler.
0039 */
0040 public KeyboardMap(GateIM im, LocaleHandler handler, State state){
0041 this.im = im;
0042 this.handler = handler;
0043 this.state = state;
0044 jobs = Collections.synchronizedList(new ArrayList());
0045 myThread = new Thread(Thread.currentThread().getThreadGroup(),
0046 this);
0047 myThread.start();
0048 }
0049
0050 /**
0051 * The run method for the thread responsible for updating the display.
0052 */
0053 public void run(){
0054 //do all the initialisations
0055 this.window = im.getContext().createInputMethodJFrame(null, true);
0056 window.setTitle(handler.locale.getDisplayName() + " keyboard map");
0057 window.setVisible(false);
0058 window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
0059 window.addComponentListener(new ComponentAdapter(){
0060 public void componentHidden(ComponentEvent e){
0061 window.dispose();
0062 }
0063 });
0064
0065 window.getContentPane().setLayout(new GridLayout(1,1));
0066 GridBagLayout layout = new GridBagLayout();
0067 contentPane = new JPanel(layout);
0068 contentPane.setDoubleBuffered(true);
0069 window.getContentPane().add(contentPane, BorderLayout.CENTER);
0070
0071 labelForKey = new HashMap();
0072 GUIforString = new HashMap();
0073
0074 double [] wheights = new double[45];
0075 for(int i = 0; i < wheights.length; i++) wheights[i] = 0.001;
0076 layout.columnWeights = wheights;
0077 wheights = new double[5];
0078 for(int i = 0; i < wheights.length; i++) wheights[i] = 0.001;
0079 layout.rowWeights = wheights;
0080
0081 //read keycaps
0082 Map keyCap = handler.getKeyCap();
0083 Iterator keyIter = keyCap.keySet().iterator();
0084 Key currentKey;
0085 JLabel currentLabel;
0086 //LabelUI uLabelUI = new BasicUnicodeLabelUI(GateIM.getFontSet());
0087 while(keyIter.hasNext()){
0088 currentKey = (Key)keyIter.next();
0089 currentLabel = new JLabel();
0090 //currentLabel.setUI(uLabelUI);
0091 currentLabel.setFont(GateIM.getKeyboardFont());
0092 currentLabel.setForeground(Color.black);
0093 currentLabel.setText((String)keyCap.get(currentKey));
0094 labelForKey.put(currentKey, currentLabel);
0095 }
0096 //build the guis
0097 GUIforString = new HashMap();
0098 KeyGUI currentGui;
0099 int currentModifiers = 0;
0100 if(ctrl) currentModifiers |= InputEvent.CTRL_MASK;
0101 if(alt) currentModifiers |= InputEvent.ALT_MASK;
0102 char ch;
0103 String sKey;
0104 for(ch = 'a'; ch <= 'z'; ch++){
0105 sKey = "" + ch;
0106 if(shift) currentKey = new Key(Character.toUpperCase(ch), currentModifiers);
0107 else currentKey = new Key(ch, currentModifiers);
0108 currentGui = new KeyGUI(sKey, ch, Character.toUpperCase(ch),
0109 (JLabel)labelForKey.get(currentKey));
0110 GUIforString.put(sKey, currentGui);
0111 }
0112 if(shift) ch = '!'; else ch = '1';
0113 sKey = "1";
0114 currentKey = new Key(ch, currentModifiers);
0115 currentGui = new KeyGUI(sKey, '1', '!',(JLabel)labelForKey.get(currentKey));
0116 GUIforString.put(sKey, currentGui);
0117 if(shift) ch = '\"'; else ch = '2';
0118 sKey = "2";
0119 currentKey = new Key(ch, currentModifiers);
0120 currentGui = new KeyGUI(sKey, '2', '\"',(JLabel)labelForKey.get(currentKey));
0121 GUIforString.put(sKey, currentGui);
0122 if(shift) ch = '\u00a3'; else ch = '3'; //pound symbol
0123 sKey = "3";
0124 currentKey = new Key(ch, currentModifiers);
0125 currentGui = new KeyGUI(sKey, '3', '\u00a3',(JLabel)labelForKey.get(currentKey)); //pound symbol
0126 GUIforString.put(sKey, currentGui);
0127 if(shift) ch = '$'; else ch = '4';
0128 sKey = "4";
0129 currentKey = new Key(ch, currentModifiers);
0130 currentGui = new KeyGUI(sKey, '4', '$',(JLabel)labelForKey.get(currentKey));
0131 GUIforString.put(sKey, currentGui);
0132 if(shift) ch = '%'; else ch = '5';
0133 sKey = "5";
0134 currentKey = new Key(ch, currentModifiers);
0135 currentGui = new KeyGUI(sKey, '5', '%',(JLabel)labelForKey.get(currentKey));
0136 GUIforString.put(sKey, currentGui);
0137 if(shift) ch = '^'; else ch = '6';
0138 sKey = "6";
0139 currentKey = new Key(ch, currentModifiers);
0140 currentGui = new KeyGUI(sKey, '6', '^',(JLabel)labelForKey.get(currentKey));
0141 GUIforString.put(sKey, currentGui);
0142 if(shift) ch = '&'; else ch = '7';
0143 sKey = "7";
0144 currentKey = new Key(ch, currentModifiers);
0145 currentGui = new KeyGUI(sKey, '7', '&',(JLabel)labelForKey.get(currentKey));
0146 GUIforString.put(sKey, currentGui);
0147 if(shift) ch = '*'; else ch = '8';
0148 sKey = "8";
0149 currentKey = new Key(ch, currentModifiers);
0150 currentGui = new KeyGUI(sKey, '8', '*',(JLabel)labelForKey.get(currentKey));
0151 GUIforString.put(sKey, currentGui);
0152 if(shift) ch = '('; else ch = '9';
0153 sKey = "9";
0154 currentKey = new Key(ch, currentModifiers);
0155 currentGui = new KeyGUI(sKey, '9', '(',(JLabel)labelForKey.get(currentKey));
0156 GUIforString.put(sKey, currentGui);
0157 if(shift) ch = ')'; else ch = '0';
0158 sKey = "0";
0159 currentKey = new Key(ch, currentModifiers);
0160 currentGui = new KeyGUI(sKey, '0', ')',(JLabel)labelForKey.get(currentKey));
0161 GUIforString.put(sKey, currentGui);
0162 if(shift) ch = '\u00ac'; else ch = '`'; //negation symbol
0163 sKey = "`";
0164 currentKey = new Key(ch, currentModifiers);
0165 currentGui = new KeyGUI(sKey, '`', '\u00ac',(JLabel)labelForKey.get(currentKey)); //negation symbol
0166 GUIforString.put(sKey, currentGui);
0167 if(shift) ch = '_'; else ch = '-';
0168 sKey = "-";
0169 currentKey = new Key(ch, currentModifiers);
0170 currentGui = new KeyGUI(sKey, '-', '_',(JLabel)labelForKey.get(currentKey));
0171 GUIforString.put(sKey, currentGui);
0172 if(shift) ch = '+'; else ch = '=';
0173 sKey = "=";
0174 currentKey = new Key(ch, currentModifiers);
0175 currentGui = new KeyGUI(sKey, '=', '+',(JLabel)labelForKey.get(currentKey));
0176 GUIforString.put(sKey, currentGui);
0177 if(shift) ch = '{'; else ch = '[';
0178 sKey = "[";
0179 currentKey = new Key(ch, currentModifiers);
0180 currentGui = new KeyGUI(sKey, '[', '{',(JLabel)labelForKey.get(currentKey));
0181 GUIforString.put(sKey, currentGui);
0182 if(shift) ch = '}'; else ch = ']';
0183 sKey = "]";
0184 currentKey = new Key(ch, currentModifiers);
0185 currentGui = new KeyGUI(sKey, ']', '}',(JLabel)labelForKey.get(currentKey));
0186 GUIforString.put(sKey, currentGui);
0187 if(shift) ch = ':'; else ch = ';';
0188 sKey = ";";
0189 currentKey = new Key(ch, currentModifiers);
0190 currentGui = new KeyGUI(sKey, ';', ':',(JLabel)labelForKey.get(currentKey));
0191 GUIforString.put(sKey, currentGui);
0192 if(shift) ch = '@'; else ch = '\'';
0193 sKey = "'";
0194 currentKey = new Key(ch, currentModifiers);
0195 currentGui = new KeyGUI(sKey, '\'', '@',(JLabel)labelForKey.get(currentKey));
0196 GUIforString.put(sKey, currentGui);
0197 if(shift) ch = '~'; else ch = '#';
0198 sKey = "#";
0199 currentKey = new Key(ch, currentModifiers);
0200 currentGui = new KeyGUI(sKey, '#', '~',(JLabel)labelForKey.get(currentKey));
0201 GUIforString.put(sKey, currentGui);
0202 if(shift) ch = '|'; else ch = '\\';
0203 sKey = "\\";
0204 currentKey = new Key(ch, currentModifiers);
0205 currentGui = new KeyGUI(sKey, '\\', '|',(JLabel)labelForKey.get(currentKey));
0206 GUIforString.put(sKey, currentGui);
0207 if(shift) ch = '<'; else ch = ',';
0208 sKey = ",";
0209 currentKey = new Key(ch, currentModifiers);
0210 currentGui = new KeyGUI(sKey, ',', '<',(JLabel)labelForKey.get(currentKey));
0211 GUIforString.put(sKey, currentGui);
0212 if(shift) ch = '>'; else ch = '.';
0213 sKey = ".";
0214 currentKey = new Key(ch, currentModifiers);
0215 currentGui = new KeyGUI(sKey, '.', '>',(JLabel)labelForKey.get(currentKey));
0216 GUIforString.put(sKey, currentGui);
0217 if(shift) ch = '?'; else ch = '/';
0218 sKey = "/";
0219 currentKey = new Key(ch, currentModifiers);
0220 currentGui = new KeyGUI(sKey, '/', '?',(JLabel)labelForKey.get(currentKey));
0221 GUIforString.put(sKey, currentGui);
0222
0223 GUIforString.put("BACK_SPACE", new KeyGUI("BACK_SPACE", (char)0,(char)0,new JLabel("BackSpace")));
0224 GUIforString.put("TAB", new KeyGUI("TAB", (char)0,(char)0,new JLabel("Tab")));
0225 GUIforString.put("CAPS_LOCK", new KeyGUI("CAPS_LOCK", (char)0,(char)0,new JLabel("Caps Lock")));
0226 GUIforString.put("ENTER", new KeyGUI("ENTER", (char)0, (char)0,new JLabel("Enter")));
0227 GUIforString.put("LSHIFT", new KeyGUI("LSHIFT", (char)0,(char)0,new JLabel("Shift")));
0228 GUIforString.put("RSHIFT", new KeyGUI("RSHIFT", (char)0,(char)0,new JLabel("Shift")));
0229 GUIforString.put("LCTRL", new KeyGUI("LCTRL", (char)0,(char)0,new JLabel("Ctrl")));
0230 GUIforString.put("RCTRL", new KeyGUI("RCTRL", (char)0,(char)0,new JLabel("Ctrl")));
0231 GUIforString.put("LALT", new KeyGUI("LALT", (char)0,(char)0,new JLabel("Alt")));
0232 GUIforString.put("RALT", new KeyGUI("RALT", (char)0,(char)0,new JLabel("Alt")));
0233 GUIforString.put("SPACE", new KeyGUI("SPACE", ' ', ' ',new JLabel(" ")));
0234
0235 //add the components to the window
0236 GridBagConstraints constraints = new GridBagConstraints();
0237 constraints.fill = GridBagConstraints.BOTH;
0238 constraints.gridwidth = 3;
0239 contentPane.add((Component)GUIforString.get("`"), constraints);
0240 contentPane.add((Component)GUIforString.get("1"), constraints);
0241 contentPane.add((Component)GUIforString.get("2"), constraints);
0242 contentPane.add((Component)GUIforString.get("3"), constraints);
0243 contentPane.add((Component)GUIforString.get("4"), constraints);
0244 contentPane.add((Component)GUIforString.get("5"), constraints);
0245 contentPane.add((Component)GUIforString.get("6"), constraints);
0246 contentPane.add((Component)GUIforString.get("7"), constraints);
0247 contentPane.add((Component)GUIforString.get("8"), constraints);
0248 contentPane.add((Component)GUIforString.get("9"), constraints);
0249 contentPane.add((Component)GUIforString.get("0"), constraints);
0250 contentPane.add((Component)GUIforString.get("-"), constraints);
0251 contentPane.add((Component)GUIforString.get("="), constraints);
0252 constraints.gridwidth = 6;
0253 contentPane.add((Component)GUIforString.get("BACK_SPACE"), constraints);
0254 //second line
0255 constraints.gridy = 1;
0256 constraints.gridwidth = 5;
0257 contentPane.add((Component)GUIforString.get("TAB"), constraints);
0258 constraints.gridwidth = 3;
0259 contentPane.add((Component)GUIforString.get(""+'q'), constraints);
0260 contentPane.add((Component)GUIforString.get(""+'w'), constraints);
0261 contentPane.add((Component)GUIforString.get(""+'e'), constraints);
0262 contentPane.add((Component)GUIforString.get(""+'r'), constraints);
0263 contentPane.add((Component)GUIforString.get(""+'t'), constraints);
0264 contentPane.add((Component)GUIforString.get(""+'y'), constraints);
0265 contentPane.add((Component)GUIforString.get(""+'u'), constraints);
0266 contentPane.add((Component)GUIforString.get(""+'i'), constraints);
0267 contentPane.add((Component)GUIforString.get(""+'o'), constraints);
0268 contentPane.add((Component)GUIforString.get(""+'p'), constraints);
0269 contentPane.add((Component)GUIforString.get(""+'['), constraints);
0270 contentPane.add((Component)GUIforString.get(""+']'), constraints);
0271 constraints.gridwidth = 4;
0272 contentPane.add((Component)GUIforString.get(""+'\\'), constraints);
0273 //line 3
0274 constraints.gridy = 2;
0275 constraints.gridwidth = 6;
0276 contentPane.add((Component)GUIforString.get("CAPS_LOCK"), constraints);
0277 constraints.gridwidth = 3;
0278 contentPane.add((Component)GUIforString.get("a"), constraints);
0279 contentPane.add((Component)GUIforString.get(""+'s'), constraints);
0280 contentPane.add((Component)GUIforString.get(""+'d'), constraints);
0281 contentPane.add((Component)GUIforString.get(""+'f'), constraints);
0282 contentPane.add((Component)GUIforString.get(""+'g'), constraints);
0283 contentPane.add((Component)GUIforString.get(""+'h'), constraints);
0284 contentPane.add((Component)GUIforString.get(""+'j'), constraints);
0285 contentPane.add((Component)GUIforString.get(""+'k'), constraints);
0286 contentPane.add((Component)GUIforString.get(""+'l'), constraints);
0287 contentPane.add((Component)GUIforString.get(""+';'), constraints);
0288 contentPane.add((Component)GUIforString.get("'"), constraints);
0289 constraints.gridwidth = 6;
0290 contentPane.add((Component)GUIforString.get("ENTER"), constraints);
0291 //line 4
0292 constraints.gridy = 3;
0293 constraints.gridwidth = 5;
0294 contentPane.add((Component)GUIforString.get("LSHIFT"), constraints);
0295 constraints.gridwidth = 3;
0296 contentPane.add((Component)GUIforString.get(""+'z'), constraints);
0297 contentPane.add((Component)GUIforString.get(""+'x'), constraints);
0298 contentPane.add((Component)GUIforString.get(""+'c'), constraints);
0299 contentPane.add((Component)GUIforString.get(""+'v'), constraints);
0300 contentPane.add((Component)GUIforString.get(""+'b'), constraints);
0301 contentPane.add((Component)GUIforString.get(""+'n'), constraints);
0302 contentPane.add((Component)GUIforString.get(""+'m'), constraints);
0303 contentPane.add((Component)GUIforString.get(""+','), constraints);
0304 contentPane.add((Component)GUIforString.get(""+'.'), constraints);
0305 contentPane.add((Component)GUIforString.get(""+'/'), constraints);
0306 contentPane.add((Component)GUIforString.get(""+'#'), constraints);
0307 constraints.gridwidth = 8;
0308 contentPane.add((Component)GUIforString.get("RSHIFT"), constraints);
0309 //line 5
0310 constraints.gridy = 4;
0311 constraints.gridwidth = 5;
0312 contentPane.add((Component)GUIforString.get("LCTRL"), constraints);
0313 contentPane.add((Component)GUIforString.get("LALT"), constraints);
0314 constraints.gridwidth = 25;
0315 contentPane.add((Component)GUIforString.get("SPACE"), constraints);
0316 constraints.gridwidth = 5;
0317 contentPane.add((Component)GUIforString.get("RALT"), constraints);
0318 contentPane.add((Component)GUIforString.get("RCTRL"), constraints);
0319 window.pack();
0320
0321 if(im.mapVisible) window.setVisible(true);
0322
0323 //initialisations done
0324 //wait for jobs to do
0325 infinite:while(true){
0326 synchronized(jobs){
0327 try{
0328 if(!jobs.isEmpty()){
0329 //do the jobs in the job list
0330 while(!jobs.isEmpty()){
0331 Object job = jobs.remove(0);
0332 //do job
0333 if(job instanceof String){
0334 //job is a command
0335 String sJob = (String)job;
0336 //should we die? :(
0337 if(sJob.equalsIgnoreCase("DIE")) break infinite;
0338 else if(sJob.equalsIgnoreCase("HIDE") && window.isShowing()){
0339 window.setVisible(false);
0340 }else if(sJob.equalsIgnoreCase("SHOW") && (!window.isShowing())){
0341 window.setVisible(true);
0342 }else if(sJob.equalsIgnoreCase("UPDATE")) update();
0343 }else if(job instanceof KeyEvent){
0344 //job is an key event
0345 int code;
0346 KeyEvent kEvent = (KeyEvent)job;
0347 KeyGUI someGui;
0348 if(kEvent.getID() == KeyEvent.KEY_PRESSED){
0349 code = kEvent.getKeyCode();
0350 switch(code){
0351 case KeyEvent.VK_SHIFT: {
0352 if(!shift) {
0353 shift = true;
0354 ((KeyGUI)GUIforString.get("LSHIFT")).pressKey();
0355 ((KeyGUI)GUIforString.get("RSHIFT")).pressKey();
0356 updateLabels();
0357 }
0358 break;
0359 }
0360 case KeyEvent.VK_CONTROL:{
0361 if(!ctrl){
0362 ctrl = true;
0363 ((KeyGUI)GUIforString.get("LCTRL")).pressKey();
0364 ((KeyGUI)GUIforString.get("RCTRL")).pressKey();
0365 updateLabels();
0366 }
0367 break;
0368 }
0369 case KeyEvent.VK_ALT:{
0370 if(!alt){
0371 alt = true;
0372 ((KeyGUI)GUIforString.get("LALT")).pressKey();
0373 ((KeyGUI)GUIforString.get("RALT")).pressKey();
0374 updateLabels();
0375 }
0376 break;
0377 }
0378 case KeyEvent.VK_CAPS_LOCK:{
0379 someGui = (KeyGUI)GUIforString.get("CAPS_LOCK");
0380 someGui.pressKey();
0381 break;
0382 }
0383 case KeyEvent.VK_BACK_SPACE:{
0384 someGui = (KeyGUI)GUIforString.get("BACK_SPACE");
0385 someGui.pressKey();
0386 break;
0387 }
0388 case KeyEvent.VK_ENTER:{
0389 someGui = (KeyGUI)GUIforString.get("ENTER");
0390 someGui.pressKey();
0391 break;
0392 }
0393 case KeyEvent.VK_TAB:{
0394 someGui = (KeyGUI)GUIforString.get("TAB");
0395 someGui.pressKey();
0396 break;
0397 }
0398 case KeyEvent.VK_SPACE:{
0399 someGui = (KeyGUI)GUIforString.get("SPACE");
0400 someGui.pressKey();
0401 break;
0402 }
0403 default:{
0404 String key = "";
0405 char keyCh = kEvent.getKeyChar();
0406 if('a' <= keyCh && keyCh <= 'z'){
0407 key += keyCh;
0408 }else if('A' <= keyCh && keyCh <= 'Z'){
0409 key += Character.toLowerCase(keyCh);
0410 }else{
0411 switch(keyCh){
0412 case '`':{
0413 key += keyCh;
0414 break;
0415 }
0416 case '1':{
0417 key += keyCh;
0418 break;
0419 }
0420 case '2':{
0421 key += keyCh;
0422 break;
0423 }
0424 case '3':{
0425 key += keyCh;
0426 break;
0427 }
0428 case '4':{
0429 key += keyCh;
0430 break;
0431 }
0432 case '5':{
0433 key += keyCh;
0434 break;
0435 }
0436 case '6':{
0437 key += keyCh;
0438 break;
0439 }
0440 case '7':{
0441 key += keyCh;
0442 break;
0443 }
0444 case '8':{
0445 key += keyCh;
0446 break;
0447 }
0448 case '9':{
0449 key += keyCh;
0450 break;
0451 }
0452 case '0':{
0453 key += keyCh;
0454 break;
0455 }
0456 case '-':{
0457 key += keyCh;
0458 break;
0459 }
0460 case '=':{
0461 key += keyCh;
0462 break;
0463 }
0464 case '[':{
0465 key += keyCh;
0466 break;
0467 }
0468 case ']':{
0469 key += keyCh;
0470 break;
0471 }
0472 case ';':{
0473 key += keyCh;
0474 break;
0475 }
0476 case '\'':{
0477 key += keyCh;
0478 break;
0479 }
0480 case '#':{
0481 key += keyCh;
0482 break;
0483 }
0484 case '\\':{
0485 key += keyCh;
0486 break;
0487 }
0488 case ',':{
0489 key += keyCh;
0490 break;
0491 }
0492 case '.':{
0493 key += keyCh;
0494 break;
0495 }
0496 case '/':{
0497 key += keyCh;
0498 break;
0499 }
0500
0501
0502 case '\u00ac':{ //negation symbol
0503 key += '`';
0504 break;
0505 }
0506 case '!':{
0507 key += '1';
0508 break;
0509 }
0510 case '\"':{
0511 key += '2';
0512 break;
0513 }
0514 case '\u00a3':{ //pound symbol
0515 key += '3';
0516 break;
0517 }
0518 case '$':{
0519 key += '4';
0520 break;
0521 }
0522 case '%':{
0523 key += '5';
0524 break;
0525 }
0526 case '^':{
0527 key += '6';
0528 break;
0529 }
0530 case '&':{
0531 key += '7';
0532 break;
0533 }
0534 case '*':{
0535 key += '8';
0536 break;
0537 }
0538 case '(':{
0539 key += '9';
0540 break;
0541 }
0542 case ')':{
0543 key += '0';
0544 break;
0545 }
0546 case '_':{
0547 key += '-';
0548 break;
0549 }
0550 case '+':{
0551 key += '=';
0552 break;
0553 }
0554 case '{':{
0555 key += '[';
0556 break;
0557 }
0558 case '}':{
0559 key += ']';
0560 break;
0561 }
0562 case ':':{
0563 key += ';';
0564 break;
0565 }
0566 case '@':{
0567 key += '\'';
0568 break;
0569 }
0570 case '~':{
0571 key += '#';
0572 break;
0573 }
0574 case '|':{
0575 key += '\\';
0576 break;
0577 }
0578 case '<':{
0579 key += ',';
0580 break;
0581 }
0582 case '>':{
0583 key += '.';
0584 break;
0585 }
0586 case '?':{
0587 key += '/';
0588 break;
0589 }
0590 }//switch
0591 }
0592 someGui = (KeyGUI)GUIforString.get(key);
0593 if(someGui != null){
0594 someGui.pressKey();
0595 }
0596 }//default
0597 }//switch
0598 }else if(kEvent.getID() == KeyEvent.KEY_RELEASED){
0599 code = kEvent.getKeyCode();
0600 switch(code){
0601 case KeyEvent.VK_SHIFT: {
0602 if(shift) {
0603 shift = false;
0604 ((KeyGUI)GUIforString.get("LSHIFT")).releaseKey();
0605 ((KeyGUI)GUIforString.get("RSHIFT")).releaseKey();
0606 updateLabels();
0607 }
0608 break;
0609 }
0610 case KeyEvent.VK_CONTROL:{
0611 if(ctrl){
0612 ctrl = false;
0613 ((KeyGUI)GUIforString.get("LCTRL")).releaseKey();
0614 ((KeyGUI)GUIforString.get("RCTRL")).releaseKey();
0615 updateLabels();
0616 }
0617 break;
0618 }
0619 case KeyEvent.VK_ALT:{
0620 if(alt){
0621 alt = false;
0622 ((KeyGUI)GUIforString.get("LALT")).releaseKey();
0623 ((KeyGUI)GUIforString.get("RALT")).releaseKey();
0624 updateLabels();
0625 }
0626 break;
0627 }
0628 case KeyEvent.VK_CAPS_LOCK:{
0629 someGui = (KeyGUI)GUIforString.get("CAPS_LOCK");
0630 someGui.releaseKey();
0631 break;
0632 }
0633 case KeyEvent.VK_BACK_SPACE:{
0634 someGui = (KeyGUI)GUIforString.get("BACK_SPACE");
0635 someGui.releaseKey();
0636 break;
0637 }
0638 case KeyEvent.VK_ENTER:{
0639 someGui = (KeyGUI)GUIforString.get("ENTER");
0640 someGui.releaseKey();
0641 break;
0642 }
0643 case KeyEvent.VK_TAB:{
0644 someGui = (KeyGUI)GUIforString.get("TAB");
0645 someGui.releaseKey();
0646 break;
0647 }
0648 case KeyEvent.VK_SPACE:{
0649 someGui = (KeyGUI)GUIforString.get("SPACE");
0650 someGui.releaseKey();
0651 break;
0652 }
0653 default:{
0654 String key = "";
0655 char keyCh = kEvent.getKeyChar();
0656 if('a' <= keyCh && keyCh <= 'z'){
0657 key += keyCh;
0658 }else if('A' <= keyCh && keyCh <= 'Z'){
0659 key += Character.toLowerCase(keyCh);
0660 }else{
0661 switch(keyCh){
0662 case '`':{
0663 key += keyCh;
0664 break;
0665 }
0666 case '1':{
0667 key += keyCh;
0668 break;
0669 }
0670 case '2':{
0671 key += keyCh;
0672 break;
0673 }
0674 case '3':{
0675 key += keyCh;
0676 break;
0677 }
0678 case '4':{
0679 key += keyCh;
0680 break;
0681 }
0682 case '5':{
0683 key += keyCh;
0684 break;
0685 }
0686 case '6':{
0687 key += keyCh;
0688 break;
0689 }
0690 case '7':{
0691 key += keyCh;
0692 break;
0693 }
0694 case '8':{
0695 key += keyCh;
0696 break;
0697 }
0698 case '9':{
0699 key += keyCh;
0700 break;
0701 }
0702 case '0':{
0703 key += keyCh;
0704 break;
0705 }
0706 case '-':{
0707 key += keyCh;
0708 break;
0709 }
0710 case '=':{
0711 key += keyCh;
0712 break;
0713 }
0714 case '[':{
0715 key += keyCh;
0716 break;
0717 }
0718 case ']':{
0719 key += keyCh;
0720 break;
0721 }
0722 case ';':{
0723 key += keyCh;
0724 break;
0725 }
0726 case '\'':{
0727 key += keyCh;
0728 break;
0729 }
0730 case '#':{
0731 key += keyCh;
0732 break;
0733 }
0734 case '\\':{
0735 key += keyCh;
0736 break;
0737 }
0738 case ',':{
0739 key += keyCh;
0740 break;
0741 }
0742 case '.':{
0743 key += keyCh;
0744 break;
0745 }
0746 case '/':{
0747 key += keyCh;
0748 break;
0749 }
0750
0751 case '\u00ac':{ //negation symbol
0752 key += '`';
0753 break;
0754 }
0755 case '!':{
0756 key += '1';
0757 break;
0758 }
0759 case '\"':{
0760 key += '2';
0761 break;
0762 }
0763 case '\u00a3':{ //pound symbol
0764 key += '3';
0765 break;
0766 }
0767 case '$':{
0768 key += '4';
0769 break;
0770 }
0771 case '%':{
0772 key += '5';
0773 break;
0774 }
0775 case '^':{
0776 key += '6';
0777 break;
0778 }
0779 case '&':{
0780 key += '7';
0781 break;
0782 }
0783 case '*':{
0784 key += '8';
0785 break;
0786 }
0787 case '(':{
0788 key += '9';
0789 break;
0790 }
0791 case ')':{
0792 key += '0';
0793 break;
0794 }
0795 case '_':{
0796 key += '-';
0797 break;
0798 }
0799 case '+':{
0800 key += '=';
0801 break;
0802 }
0803 case '{':{
0804 key += '[';
0805 break;
0806 }
0807 case '}':{
0808 key += ']';
0809 break;
0810 }
0811 case ':':{
0812 key += ';';
0813 break;
0814 }
0815 case '@':{
0816 key += '\'';
0817 break;
0818 }
0819 case '~':{
0820 key += '#';
0821 break;
0822 }
0823 case '|':{
0824 key += '\\';
0825 break;
0826 }
0827 case '<':{
0828 key += ',';
0829 break;
0830 }
0831 case '>':{
0832 key += '.';
0833 break;
0834 }
0835 case '?':{
0836 key += '/';
0837 break;
0838 }
0839 }//switch
0840 }
0841 someGui = (KeyGUI)GUIforString.get(key);
0842 if(someGui != null){
0843 someGui.releaseKey();
0844 }
0845 }//default
0846 }//switch
0847 }
0848 //update the state so the rebuildGui will update the highlights
0849 // state = im.currentState;
0850 // update();
0851 }
0852 }
0853 }
0854 }catch(Exception e){}
0855 jobs.notifyAll();
0856 }//synchronized(jobs);
0857 //no more jobs, take a nap :)
0858 try{
0859 Thread.sleep(150);
0860 }catch(InterruptedException ie){
0861 ie.printStackTrace();
0862 }
0863 }//infinite: while(true)
0864
0865 }
0866
0867 /**
0868 * Adds a job to the job list of the thread.
0869 * A job is either a {@link java.lang.String} or an {@link java.awt.event.InputEvent}
0870 * The string can be one of
0871 * <ul>
0872 * <li>SHOW: shows the keyboard map window
0873 * <li>UPDATE updates the keyboard map window
0874 * <li>HIDE: hides the keyboard map window
0875 * <li>DIE: releases all the memory and terminates the thread
0876 * </ul>
0877 *
0878 * The input events refer to pressed keys and are treated accordingly.
0879 *
0880 * @param job
0881 */
0882 public void addJob(Object job){
0883 synchronized(jobs){
0884 jobs.add(job);
0885 jobs.notifyAll();
0886 }
0887 }
0888
0889 /**
0890 * Updates the keyboard map for a new Locale or a new state of the current locale handler.
0891 * Currently the state changes are ignored.
0892 * This method delegates its job to the thread which will do the actual
0893 * update.
0894 * @param newHandler
0895 * @param newState
0896 */
0897 public void update(LocaleHandler newHandler, State newState){
0898 //did anything changed?
0899 if(newHandler == handler && newState == state) return;
0900 this.newHandler = newHandler;
0901 this.newState = newState;
0902 addJob("UPDATE");
0903 }
0904
0905 /**
0906 * Does th actual update.
0907 */
0908 protected void update(){
0909 //did the locale changed?
0910 if(newHandler != handler){
0911 handler = newHandler;
0912 state = newState;
0913 window.setTitle(handler.locale.getDisplayLanguage() + " (" +
0914 handler.locale.getVariant() + ") keyboard map");
0915 //read keycaps
0916 labelForKey.clear();
0917 Map keyCap = handler.getKeyCap();
0918 Iterator keyIter = keyCap.keySet().iterator();
0919 Key currentKey;
0920 JLabel currentLabel;
0921 //LabelUI uLabelUI = new BasicUnicodeLabelUI(GateIM.getFontSet());
0922 while(keyIter.hasNext()){
0923 currentKey = (Key)keyIter.next();
0924 currentLabel = new JLabel();
0925 currentLabel.setFont(GateIM.getKeyboardFont());
0926 //currentLabel.setUI(uLabelUI);
0927 currentLabel.setText((String)keyCap.get(currentKey));
0928 labelForKey.put(currentKey, currentLabel);
0929 }
0930 updateLabels();
0931 }
0932 //did the state changed?
0933 if(newState != state){
0934 //highlight the allowed keys
0935 state = newState;
0936 //un-highlight the highlighted keys
0937 Iterator keysIter = highlightedKeys.iterator();
0938 while(keysIter.hasNext()) ((KeyGUI)keysIter.next()).unHighlight();
0939 highlightedKeys.clear();
0940
0941 //if not initial state highlight the allowed keys
0942 if(state != handler.getInitialState()){
0943 keysIter = state.transitionFunction.keySet().iterator();
0944 KeyGUI someGui;
0945 while(keysIter.hasNext()){
0946 someGui = guiForKey((Key)keysIter.next());
0947 if(someGui != null){
0948 someGui.highlight();
0949 highlightedKeys.add(someGui);
0950 }
0951 }
0952 }
0953 }
0954 }
0955
0956 /**
0957 * Updates the virtual keyboard to reflect the current state.
0958 */
0959 protected void updateLabels(){
0960 //update the labels
0961 Component[] components = contentPane.getComponents();
0962 for(int i = 0; i <components.length; i++){
0963 if(components[i] instanceof KeyGUI) ((KeyGUI)components[i]).updateLabel();
0964 }
0965 fixShape();
0966 }
0967
0968 /** */
0969 protected void fixShape(){
0970 //get the current sizes
0971 int [][] sizes = ((GridBagLayout)contentPane.getLayout()).getLayoutDimensions();
0972 //override the minimum sizes
0973 ((GridBagLayout)contentPane.getLayout()).columnWidths = sizes[0];
0974 ((GridBagLayout)contentPane.getLayout()).rowHeights = sizes[1];
0975 window.pack();
0976 contentPane.repaint(100);
0977 }
0978 /**
0979 * Gets the gui that corresponds to a Key object.
0980 *
0981 * @param key
0982 */
0983 protected KeyGUI guiForKey(Key key){
0984 char ch = key.keyChar;
0985 boolean shiftOn = false;
0986 if(Character.isUpperCase(ch)){
0987 ch = Character.toLowerCase(ch);
0988 shiftOn = true;
0989 }
0990 boolean ctrlOn = (key.modifiers & KeyEvent.CTRL_MASK) > 0;
0991 boolean altOn = (key.modifiers & KeyEvent.ALT_MASK) > 0;
0992 if(shift == shiftOn &&
0993 ctrl == ctrlOn &&
0994 alt == altOn){
0995 return (KeyGUI)GUIforString.get("" + ch);
0996 }
0997 return null;
0998 }
0999 /**
1000 * Is the Shift key pressed?
1001 *
1002 * @param shift
1003 */
1004 public void setShift(boolean shift){
1005 this.shift = shift;
1006 }
1007
1008 /**
1009 * Is the Alt key pressed?
1010 *
1011 * @param alt
1012 */
1013 public void setAlt(boolean alt){
1014 this.alt = alt;
1015 }
1016
1017 /**
1018 * Is the Ctrl key pressed?
1019 *
1020 * @param ctrl
1021 */
1022 public void setCtrl(boolean ctrl){
1023 this.ctrl = ctrl;
1024 }
1025
1026 //variables
1027
1028 //the current LocaleHandler
1029 /**
1030 * the active locale handler
1031 */
1032 LocaleHandler handler;
1033 //thenew handler that will become current on the next update
1034 /**
1035 * The new active locale handler. This member is useful during the period when the active locale handler has changed but the keyboard map is not updated yet. The keyboard map will be updated as soon as the tasks that were added to the job list before the locale change are consumed.
1036 */
1037 LocaleHandler newHandler;
1038
1039 //the current state of the current locale handler
1040 /**
1041 * The current state of the current locale handler.
1042 */
1043 State state;
1044 //the new state that will become current on the next update
1045 /**
1046 * The current state of the new current locale handler.
1047 *
1048 * @see #newHandler
1049 */
1050 State newState;
1051 /**
1052 * The window used for displaying the keyboard map
1053 */
1054 JFrame window;
1055 /**
1056 * The content pane that holds all the KeyGUIs.
1057 *
1058 * @see guk.im.KeyboardMap.KeyGUI
1059 */
1060 JPanel contentPane;
1061
1062 /**
1063 * The keys curently highlighted
1064 */
1065 java.util.List highlightedKeys = new ArrayList();
1066
1067 /** */
1068 boolean shift = false, ctrl = false, alt = false, capslock = false;
1069 /** maps from String(the English lowercase representation of the key) to
1070 * KeyGUI
1071 */
1072 Map GUIforString;
1073 //maps from Key to JLabel for the key that have keyCap defined
1074 /**
1075 * Maps from Key to JLabel for the keys that have keyCap defined
1076 * .
1077 */
1078 Map labelForKey;
1079
1080 /**
1081 * The input method.
1082 */
1083 GateIM im;
1084
1085 /**
1086 * The thread that does the updating.
1087 */
1088 Thread myThread;
1089
1090 /**
1091 * The job list.
1092 */
1093 java.util.List jobs;
1094 //classes
1095 public class KeyGUI extends JPanel {
1096 /** */
1097 Box leftBox;
1098 /** */
1099 JLabel leftUpLabel = new JLabel();
1100 /** */
1101 JLabel leftDownLabel = new JLabel();
1102 /** */
1103 Component centerLabel;
1104 /** */
1105 char low, up;
1106 /** */
1107 Border normalBorder, highlightedBorder;
1108
1109 /**
1110 * Constructs a new KeyGUI.
1111 *
1112 * @param key the String key used in the map that holds the GUIs used for
1113 * keys
1114 * @param englishLow the English char on the key
1115 * @param englishUp the English char on the key when used with the Shift
1116 * key.
1117 * @param center the center label (the Unicode character on the key)
1118 */
1119 public KeyGUI(String key, char englishLow, char englishUp,
1120 JLabel center) {
1121 this.setBackground(Color.lightGray);
1122 low = englishLow;
1123 up = englishUp;
1124 leftBox = Box.createVerticalBox();
1125 Dimension dim;
1126 if(englishUp > (char)0){
1127 leftUpLabel.setFont(leftUpLabel.getFont().deriveFont((float)10));
1128 leftUpLabel.setText("" + englishUp);
1129 leftBox.add(leftUpLabel);
1130 }else{
1131 leftBox.add(placeHolder);
1132 }
1133 if(englishLow > (char)0){
1134 leftDownLabel.setFont(leftDownLabel.getFont().deriveFont((float)10));
1135 leftDownLabel.setText("" + englishLow);
1136 leftBox.add(leftDownLabel);
1137 }else{
1138 leftBox.add(placeHolder);
1139 }
1140 leftBox.add(Box.createVerticalGlue());
1141 if(center == null) centerLabel = placeHolder;
1142 else centerLabel = center;
1143 this.setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
1144 this.add(leftBox);
1145 this.add(Box.createHorizontalGlue());
1146 this.add(centerLabel);
1147 normalBorder = new CompoundBorder(new BevelBorder(BevelBorder.RAISED),
1148 new EmptyBorder(2,3,2,3));
1149 highlightedBorder = new CompoundBorder(new BevelBorder(BevelBorder.RAISED),
1150 new MatteBorder(2,3,2,3, Color.green));
1151
1152 this.setBorder(normalBorder);
1153 addMouseListener(new MouseAdapter(){
1154 /** *
1155 * @param e
1156 */
1157 public void mouseClicked(MouseEvent e){
1158 int modifiers = 0;
1159 if(ctrl) modifiers |= KeyEvent.CTRL_MASK;
1160 if(alt) modifiers |= KeyEvent.ALT_MASK;
1161 char ch;
1162 if(shift) ch = up;
1163 else ch = low;
1164 if(ch != 0){
1165 im.dispatchEvent(new KeyEvent(window, KeyEvent.KEY_TYPED,
1166 System.currentTimeMillis(),
1167 modifiers, KeyEvent.VK_UNDEFINED, ch));
1168 }
1169 }
1170 /** */
1171 public void mousePressed(MouseEvent e){
1172 char ch;
1173 if(shift) ch = up;
1174 else ch = low;
1175 if(ch != 0){
1176 pressKey();
1177 //repaint(100);
1178 }
1179 }
1180 /** */
1181 public void mouseReleased(MouseEvent e){
1182 char ch;
1183 if(shift) ch = up;
1184 else ch = low;
1185 if(ch != 0){
1186 releaseKey();
1187 //repaint(100);
1188 }
1189 }
1190 });
1191 }
1192
1193 /** */
1194 public void updateLabel(){
1195 if(low == (char)0 || up == (char)0)return;
1196 remove(centerLabel);
1197 Key key;
1198 int modifiers = 0;
1199 if(ctrl) modifiers |= InputEvent.CTRL_MASK;
1200 if(alt) modifiers |= InputEvent.ALT_MASK;
1201 if(shift) key = new Key(up, modifiers);
1202 else key = new Key(low, modifiers);
1203 centerLabel = (JLabel)labelForKey.get(key);
1204 if(centerLabel == null) centerLabel = placeHolder;
1205 this.add(centerLabel);
1206 // this.invalidate();
1207 }
1208
1209 /**
1210 * Displays this key as pressed
1211 */
1212 public void pressKey(){
1213 this.setBackground(Color.darkGray);
1214 }
1215
1216 /**
1217 * Displays ths key as released.
1218 */
1219 public void releaseKey(){
1220 this.setBackground(Color.lightGray);
1221 }
1222
1223 /**
1224 * Renders this KeyGUI as highlighted
1225 */
1226 public void highlight(){
1227 setBorder(highlightedBorder);
1228 }
1229
1230 /**
1231 * Renders this KeyGUI normaly (not highlighted)
1232 */
1233 public void unHighlight(){
1234 setBorder(normalBorder);
1235 }
1236
1237 }//public class KeyGUI extends JPanel
1238
1239
1240
1241 /**
1242 * Empty component used for the key that are not bound to a Unicode character.
1243 */
1244 static Component placeHolder = Box.createRigidArea(new Dimension(12, 12));
1245 }//class KeyboardMap
|