KeyboardMap.java
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[i0.001;
0076     layout.columnWeights = wheights;
0077     wheights = new double[5];
0078     for(int i = 0; i < wheights.length; i++wheights[i0.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(ctrlcurrentModifiers |= InputEvent.CTRL_MASK;
0101     if(altcurrentModifiers |= InputEvent.ALT_MASK;
0102     char ch;
0103     String sKey;
0104     for(ch = 'a'; ch <= 'z'; ch++){
0105       sKey = "" + ch;
0106       if(shiftcurrentKey = 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(shiftch = '!'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(shiftch = '\"'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(shiftch = '\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(shiftch = '$'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(shiftch = '%'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(shiftch = '^'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(shiftch = '&'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(shiftch = '*'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(shiftch = '('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(shiftch = ')'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(shiftch = '\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(shiftch = '_'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(shiftch = '+'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(shiftch = '{'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(shiftch = '}'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(shiftch = ':'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(shiftch = '@'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(shiftch = '~'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(shiftch = '|'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(shiftch = '<'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(shiftch = '>'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(shiftch = '?'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.mapVisiblewindow.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 == statereturn;
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[iinstanceof 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_MASK0;
0991     boolean altOn = (key.modifiers & KeyEvent.ALT_MASK0;
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 == nullcenterLabel = 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(ctrlmodifiers |= KeyEvent.CTRL_MASK;
1160           if(altmodifiers |= KeyEvent.ALT_MASK;
1161           char ch;
1162           if(shiftch = 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(shiftch = 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(shiftch = 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)|| up == (char)0)return;
1196       remove(centerLabel);
1197       Key key;
1198       int modifiers = 0;
1199       if(ctrlmodifiers |= InputEvent.CTRL_MASK;
1200       if(altmodifiers |= InputEvent.ALT_MASK;
1201       if(shiftkey = new Key(up, modifiers);
1202       else key = new Key(low, modifiers);
1203       centerLabel = (JLabel)labelForKey.get(key);
1204       if(centerLabel == nullcenterLabel = 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(1212));
1245 }//class KeyboardMap