Editor.java
001 /*
002  * Editor.java
003  *
004  * Copyright (c) 1998-2005, The University of Sheffield.
005  *
006  * This file is part of GATE (see http://gate.ac.uk/), and is free
007  * software, licenced under the GNU Library General Public License,
008  * Version 2, June1991.
009  *
010  * A copy of this licence is included in the distribution in the file
011  * licence.html, and is also available at http://gate.ac.uk/gate/licence.html.
012  *
013  * Valentin Tablan, October 2000
014  *
015  * $Id: Editor.java 13021 2010-08-25 09:59:38Z ian_roberts $
016  */
017 package guk;
018 
019 import java.awt.*;
020 import java.awt.event.*;
021 import java.beans.PropertyChangeEvent;
022 import java.beans.PropertyChangeListener;
023 import java.io.*;
024 import java.util.*;
025 import javax.swing.*;
026 import javax.swing.event.*;
027 import javax.swing.text.*;
028 import javax.swing.undo.UndoManager;
029 import guk.im.GateIM;
030 
031 /**
032  * A simple text editor included here to demonstrate the capabilities of the GUK
033  * package.
034  *
035  @author             <a href="http://www.gate.ac.uk/people/">The Gate Team</a>
036  @version            1.0
037  */
038 public class Editor extends JFrame {
039   JPanel contentPane;
040   JMenuBar jMenuBar1 = new JMenuBar();
041   JMenu jMenuFile = new JMenu();
042   JMenu jMenuEdit = new JMenu();
043   JMenu jMenuHelp = new JMenu();
044   JMenu jMenuIM = null;
045   JMenuItem jMenuHelpAbout = new JMenuItem();
046   JToolBar jToolBar = new JToolBar();
047   JTextPane textPane = new JTextPane();
048   JMenu jMenuOptions = new JMenu();
049   JComboBox fontsComboBox;
050   JComboBox sizeComboBox;
051   JCheckBoxMenuItem jCheckBoxMenuItemKeyboardMap = new JCheckBoxMenuItem();
052   Action openAction, saveAction, saveAsAction, closeAction,
053          exitAction, undoAction, redoAction, cutAction, copyAction,
054          pasteAction, attributesChangedAction;
055   /**
056    * The current open file
057    */
058   File file = null;
059   /**
060    * The file chooser used in all operations requiring the user to select a file
061    */
062   JFileChooser filer = new JFileChooser();
063   /**
064    * The main frame
065    */
066   JFrame frame;
067   UndoManager undoManager = new UndoManager();
068   /**
069    * has the current document changed since the last save?
070    */
071   boolean docChanged = false;
072 
073   /**
074    * Construct the frame
075    */
076   public Editor() {
077     frame = this;
078     enableEvents(AWTEvent.WINDOW_EVENT_MASK);
079     try {
080       jbInit();
081     }
082     catch(Exception e) {
083       e.printStackTrace();
084     }
085     frame.validate();
086     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
087     Dimension frameSize = getSize();
088     if (frameSize.height > screenSize.height) {
089       frameSize.height = screenSize.height;
090     }
091     if (frameSize.width > screenSize.width) {
092       frameSize.width = screenSize.width;
093     }
094     setLocation((screenSize.width - frameSize.width2,
095               (screenSize.height - frameSize.height2);
096     setVisible(true);
097   }// public Editor()
098 
099   /**
100    * Component initialization
101    */
102   private void jbInit() throws Exception {
103     this.setIconImage(Toolkit.getDefaultToolkit().getImage(
104             guk.Editor.class.getResource("img/gateIcon.gif")));
105     java.util.List installedLocales = new ArrayList();
106     try{
107       //if this fails guk is not present
108       Class.forName("guk.im.GateIMDescriptor");
109       //add the Gate input methods
110       installedLocales.addAll(Arrays.asList(new guk.im.GateIMDescriptor().
111                                             getAvailableLocales()));
112     }catch(Exception e){
113       //something happened; most probably guk not present.
114       //just drop it, is not vital.
115     }
116     try{
117       //add the MPI IMs
118       //if this fails mpi IM is not present
119       Class.forName("mpi.alt.java.awt.im.spi.lookup.LookupDescriptor");
120 
121       installedLocales.addAll(Arrays.asList(
122             new mpi.alt.java.awt.im.spi.lookup.LookupDescriptor().
123             getAvailableLocales()));
124     }catch(Exception e){
125       //something happened; most probably MPI not present.
126       //just drop it, is not vital.
127     }
128     Collections.sort(installedLocales, new Comparator(){
129       public int compare(Object o1, Object o2){
130         return ((Locale)o1).getDisplayName().compareTo(((Locale)o2).getDisplayName());
131       }
132     });
133     JMenuItem item;
134     if(!installedLocales.isEmpty()) {
135       jMenuIM = new JMenu("Input methods");
136       jMenuIM.getPopupMenu().setLayout(new MenuLayout());
137       ButtonGroup bg = new ButtonGroup();
138       Iterator localIter = installedLocales.iterator();
139       while(localIter.hasNext()){
140         Locale aLocale = (Locale)localIter.next();
141         item = new LocaleSelectorMenuItem(aLocale, frame);
142         jMenuIM.add(item);
143         bg.add(item);
144       }
145     }// if
146 
147     undoManager.setLimit(1000);
148     //OPEN ACTION
149     openAction = new AbstractAction("Open"new ImageIcon(
150             guk.Editor.class.getResource("img/openFile.gif"))){
151       public void actionPerformed(ActionEvent e){
152         int res = JOptionPane.OK_OPTION;
153         if(docChanged){
154           res = JOptionPane.showConfirmDialog(
155                 frame,
156                 "Close unsaved file " +
157                 (file== null?"Untitled":file.getName()) "?",
158                 "GATE",
159                 JOptionPane.OK_CANCEL_OPTION,
160                 JOptionPane.WARNING_MESSAGE);
161         }
162         if(res == JOptionPane.OK_OPTION){
163           filer.setMultiSelectionEnabled(false);
164           filer.setDialogTitle("Select file to open...");
165           filer.setSelectedFile(null);
166           filer.setFileFilter(filer.getAcceptAllFileFilter());
167           int res1 = filer.showOpenDialog(frame);
168           if(res1 == JFileChooser.APPROVE_OPTION){
169             //we have the file, what's the encoding?
170             Object[] encodings = "Unicode""UTF-8""UTF-16BE""UTF-16LE""UTF-16",
171                                    "ISO-8859-1""US-ASCII"};
172             JComboBox encodingsCombo = new JComboBox(encodings);
173             encodingsCombo.setEditable(true);
174             int res2 = JOptionPane.showConfirmDialog(frame,
175                                           encodingsCombo,
176                                           "Encoding?",
177                                           JOptionPane.OK_CANCEL_OPTION,
178                                           JOptionPane.QUESTION_MESSAGE);
179             Object encoding = (res2 == JOptionPane.OK_OPTION?
180                               encodingsCombo.getSelectedItem() null;
181             if(encoding == nullreturn;
182             file = filer.getSelectedFile();
183             try {
184               BufferedReader reader = new GukBomStrippingInputStreamReader(new FileInputStream(file),
185                       (String)encoding);
186               textPane.selectAll();
187               textPane.replaceSelection("");
188               textPane.read(reader, null);
189               reader.close();
190             catch(FileNotFoundException fnfe) {
191               JOptionPane.showMessageDialog(frame,
192                                             "Cannot find the file specified!",
193                                             "GATE",
194                                             JOptionPane.ERROR_MESSAGE);
195               file = null;
196               docChanged = false;
197               updateTitle();
198             catch(UnsupportedEncodingException usee) {
199               JOptionPane.showMessageDialog(frame,
200                                             "Unsupported encoding!\n" +
201                                             "Please choose another.",
202                                             "GATE",
203                                             JOptionPane.ERROR_MESSAGE);
204               file = null;
205               docChanged = false;
206               updateTitle();
207             catch(IOException ioe) {
208               JOptionPane.showMessageDialog(
209                                   frame,
210                                   "Input/Output error! (wrong encoding?)\n" +
211                                   "Please try again.",
212                                   "GATE",
213                                   JOptionPane.ERROR_MESSAGE);
214               file = null;
215               docChanged = false;
216               updateTitle();
217             }
218             docChanged = false;
219             updateTitle();
220           }
221         }
222       }// actionPerformed(ActionEvent e)
223     };
224     openAction.putValue(Action.SHORT_DESCRIPTION, "Open file...");
225 
226 
227     //SAVE ACTION
228     saveAction = new AbstractAction("Save"new ImageIcon(
229             guk.Editor.class.getResource("img/saveFile.gif"))) {
230       public void actionPerformed(ActionEvent e){
231         if(docChanged){
232           if(file == nullsaveAsAction.actionPerformed(null);
233           else {
234             //get the encoding
235             Object[] encodings = "Unicode""UTF-8""UTF-16BE""UTF-16LE""UTF-16",
236                                    "ISO-8859-1""US-ASCII"};
237             JComboBox encodingsCombo = new JComboBox(encodings);
238             encodingsCombo.setEditable(true);
239             int res2 = JOptionPane.showConfirmDialog(frame,
240                                           encodingsCombo,
241                                           "Encoding?",
242                                           JOptionPane.OK_CANCEL_OPTION,
243                                           JOptionPane.QUESTION_MESSAGE);
244             Object encoding = (res2 == JOptionPane.OK_OPTION?
245                               encodingsCombo.getSelectedItem() null;
246             if(encoding == nullreturn;
247             try {
248               OutputStreamWriter writer = new OutputStreamWriter(
249                   new FileOutputStream(file)(String)encoding);
250               writer.write(textPane.getText());
251               writer.flush();
252               writer.close();
253               docChanged = false;
254               updateTitle();
255             catch(UnsupportedEncodingException usee) {
256               JOptionPane.showMessageDialog(frame,
257                                             "Unsupported encoding!\n" +
258                                             "Please choose another.",
259                                             "GATE",
260                                             JOptionPane.ERROR_MESSAGE);
261               docChanged = true;
262               updateTitle();
263             catch(IOException ioe) {
264               JOptionPane.showMessageDialog(frame,
265                                             "Input/Output error!\n" +
266                                             "Please try again.",
267                                             "GATE",
268                                             JOptionPane.ERROR_MESSAGE);
269               docChanged = true;
270               updateTitle();
271             }
272           }// else
273         }// if
274       }// actionPerformed(ActionEvent e)
275     };
276     saveAction.putValue(Action.SHORT_DESCRIPTION, "Save...");
277 
278     //SAVE AS ACTION
279     saveAsAction = new AbstractAction("Save as..."new ImageIcon(
280             guk.Editor.class.getResource("img/saveFile.gif"))){
281       public void actionPerformed(ActionEvent e) {
282           filer.setMultiSelectionEnabled(false);
283           filer.setDialogTitle("Select file to save to...");
284           filer.setSelectedFile(null);
285           filer.setFileFilter(filer.getAcceptAllFileFilter());
286           int res = filer.showSaveDialog(frame);
287           if(res == JFileChooser.APPROVE_OPTION){
288             File newFile = filer.getSelectedFile();
289             if(newFile == nullreturn;
290             int res1 = JOptionPane.OK_OPTION;
291             if(newFile.exists()){
292               res1 = JOptionPane.showConfirmDialog(
293                       frame,
294                       "Overwrite existing file " + newFile.getName() "?",
295                       "GATE",
296                       JOptionPane.OK_CANCEL_OPTION,
297                       JOptionPane.WARNING_MESSAGE);
298             }
299             if(res1 == JOptionPane.OK_OPTION){
300               file = newFile;
301               docChanged = true;
302               saveAction.actionPerformed(null);
303             }
304           }
305       }// actionPerformed(ActionEvent e)
306     };
307     saveAsAction.putValue(Action.SHORT_DESCRIPTION, "Save as...");
308 
309     //CLOSE ACTION
310     closeAction = new AbstractAction("Close"new ImageIcon(
311             guk.Editor.class.getResource("img/closeFile.gif"))){
312       public void actionPerformed(ActionEvent e){
313         int res = JOptionPane.OK_OPTION;
314         if(docChanged){
315           res = JOptionPane.showConfirmDialog(
316                 frame,
317                 "Close unsaved file " +
318                 (file== null?"Untitled":file.getName()) "?",
319                 "GATE",
320                 JOptionPane.OK_CANCEL_OPTION,
321                 JOptionPane.WARNING_MESSAGE);
322         }
323         if(res == JOptionPane.OK_OPTION){
324           textPane.selectAll();
325           textPane.replaceSelection("");
326           docChanged = false;
327           file = null;
328           updateTitle();
329         }
330       }// actionPerformed(ActionEvent e)
331     };
332     closeAction.putValue(Action.SHORT_DESCRIPTION, "Close...");
333 
334 
335     //EXIT ACTION
336     exitAction = new AbstractAction("Exit"new ImageIcon(
337             guk.Editor.class.getResource("img/exit.gif"))){
338       public void actionPerformed(ActionEvent e){
339         int res = JOptionPane.OK_OPTION;
340         if(docChanged){
341           res = JOptionPane.showConfirmDialog(
342                 frame,
343                 "Close unsaved file " +
344                 (file== null?"Untitled":file.getName()) "?",
345                 "GATE",
346                 JOptionPane.OK_CANCEL_OPTION,
347                 JOptionPane.WARNING_MESSAGE);
348         }
349         if(res == JOptionPane.OK_OPTION){
350           frame.setVisible(false);
351           frame.dispose();
352 
353         }
354       }// actionPerformed(ActionEvent e)
355     };
356     exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit...");
357 
358     //UNDO ACTION
359     undoAction = new AbstractAction("Undo"new ImageIcon(
360             guk.Editor.class.getResource("img/undo.gif"))){
361       public void actionPerformed(ActionEvent e){
362         if(undoManager.canUndo()) undoManager.undo();
363       }
364     };
365      undoAction.setEnabled(undoManager.canUndo());
366      undoAction.putValue(Action.SHORT_DESCRIPTION, "Undo...");
367 
368     //REDO ACTION
369     redoAction = new AbstractAction("Redo"new ImageIcon(
370             guk.Editor.class.getResource("img/redo.gif"))){
371       public void actionPerformed(ActionEvent e){
372         if(undoManager.canRedo()) undoManager.redo();
373       }
374     };
375     redoAction.setEnabled(undoManager.canRedo());
376     redoAction.putValue(Action.SHORT_DESCRIPTION, "Redo...");
377 
378     //COPY ACTION
379     copyAction = new AbstractAction("Copy"new ImageIcon(
380             guk.Editor.class.getResource("img/copy.gif"))){
381       public void actionPerformed(ActionEvent e){
382         textPane.copy();
383       }
384     };
385     copyAction.putValue(Action.SHORT_DESCRIPTION, "Copy...");
386 
387     //CUT ACTION
388     cutAction = new AbstractAction("Cut"new ImageIcon(
389             guk.Editor.class.getResource("img/cut.gif"))){
390       public void actionPerformed(ActionEvent e){
391         textPane.cut();
392       }
393     };
394     cutAction.putValue(Action.SHORT_DESCRIPTION, "Cut...");
395 
396     //PASTE ACTION
397     pasteAction = new AbstractAction("Paste"new ImageIcon(
398             guk.Editor.class.getResource("img/paste.gif"))){
399       public void actionPerformed(ActionEvent e){
400         textPane.paste();
401       }
402     };
403     pasteAction.putValue(Action.SHORT_DESCRIPTION, "Paste...");
404 
405     //attributesChangedAction
406     attributesChangedAction = new AbstractAction() {
407       public void actionPerformed(ActionEvent e) {
408         int start = textPane.getSelectionStart();
409         int end = textPane.getSelectionEnd();
410         //change the selection
411         MutableAttributeSet as = textPane.getInputAttributes();
412         StyleConstants.setFontFamily(as,
413                                     (String)fontsComboBox.getSelectedItem());
414         StyleConstants.setFontSize(as,
415                                    Integer.parseInt(
416                                    (String)sizeComboBox.getSelectedItem()));
417         textPane.setCharacterAttributes(as, false);
418         //restore selection
419         textPane.setCaretPosition(start);
420         textPane.moveCaretPosition(end);
421       }// actionPerformed(ActionEvent e)
422     };
423 
424     textPane.addPropertyChangeListener("document"new PropertyChangeListener(){
425       public void propertyChange(PropertyChangeEvent evt){
426         undoAction.setEnabled(undoManager.canUndo());
427         redoAction.setEnabled(undoManager.canRedo());
428         //add the document listener
429         textPane.getDocument().addDocumentListener(new DocumentListener(){
430           public void insertUpdate(DocumentEvent e){
431             changeOccured();
432           }
433           public void removeUpdate(DocumentEvent e){
434             changeOccured();
435           }
436           public void changedUpdate(DocumentEvent e){
437             changeOccured();
438           }
439           protected void changeOccured(){
440             undoAction.setEnabled(undoManager.canUndo());
441             undoAction.putValue(Action.SHORT_DESCRIPTION,
442                                 undoManager.getUndoPresentationName());
443             redoAction.setEnabled(undoManager.canRedo());
444             redoAction.putValue(Action.SHORT_DESCRIPTION,
445                                 undoManager.getRedoPresentationName());
446             if(docChangedreturn;
447             else{
448               docChanged = true;
449               updateTitle();
450             }
451           }// changeOccured()
452         });
453         //add the document UNDO listener
454         undoManager.discardAllEdits();
455         textPane.getDocument().addUndoableEditListener(undoManager);
456       }// propertyChange(PropertyChangeEvent evt)
457     });
458 
459     fontsComboBox = new JComboBox(
460                         GraphicsEnvironment.getLocalGraphicsEnvironment().
461                         getAvailableFontFamilyNames()
462                         );
463     fontsComboBox.setEditable(false);
464     fontsComboBox.addActionListener(new ActionListener(){
465       public void actionPerformed(ActionEvent e){
466         attributesChangedAction.actionPerformed(null);
467       }// actionPerformed(ActionEvent e)
468     });
469 
470 
471     sizeComboBox = new JComboBox(new Object[]{"6""8""10""12""14""16",
472                                               "18""20""22""24""26"});
473     sizeComboBox.setEditable(true);
474     sizeComboBox.addActionListener(new ActionListener(){
475       public void actionPerformed(ActionEvent e){
476         try {
477           Integer.parseInt((String)sizeComboBox.getSelectedItem());
478           //fire the action
479           attributesChangedAction.actionPerformed(null);
480         catch(NumberFormatException nfe){
481           //invalid input, go to default
482           sizeComboBox.setSelectedIndex(3);
483         }
484       }//actionPerformed(ActionEvent e)
485     });
486 
487     //initialisation for the fonts and size combos
488     fontsComboBox.setSelectedItem(StyleConstants.getFontFamily(
489                                   textPane.getInputAttributes()));
490     sizeComboBox.setSelectedItem(String.valueOf(StyleConstants.getFontSize(
491                                   textPane.getInputAttributes())));
492     //keep them updated
493     textPane.addCaretListener(new CaretListener(){
494       public void caretUpdate(CaretEvent e) {
495         if(e.getDot() == e.getMark()){
496           fontsComboBox.setSelectedItem(StyleConstants.getFontFamily(
497                                         textPane.getCharacterAttributes()));
498           sizeComboBox.setSelectedItem(String.valueOf(StyleConstants.getFontSize(
499                                         textPane.getCharacterAttributes())));
500         }
501       }//caretUpdate(CaretEvent e)
502     });
503 
504     fontsComboBox.setMaximumSize(new Dimension(150,25));
505     //fontsComboBox.setMinimumSize(new Dimension(150,25));
506     fontsComboBox.setPreferredSize(new Dimension(150,25));
507     //fontsComboBox.setSize(new Dimension(150,25));
508     sizeComboBox.setMaximumSize(new Dimension(50,25));
509     //sizeComboBox.setMinimumSize(new Dimension(30,25));
510     sizeComboBox.setPreferredSize(new Dimension(50,25));
511     //sizeComboBox.setSize(new Dimension(30,25));
512     sizeComboBox.enableInputMethods(false);
513     //setIconImage(Toolkit.getDefaultToolkit().createImage(EditorFrame.class.getResource("[Your Icon]")));
514     contentPane = (JPanelthis.getContentPane();
515     contentPane.setLayout(new BorderLayout());
516     this.setSize(new Dimension(800600));
517     updateTitle();
518     jMenuFile.setText("File");
519     jMenuEdit.setText("Edit");
520     jMenuHelp.setText("Help");
521     jMenuHelpAbout.setText("About");
522     jMenuHelpAbout.addActionListener(new ActionListener()  {
523       public void actionPerformed(ActionEvent e) {
524         jMenuHelpAbout_actionPerformed(e);
525       }
526     });
527     jMenuOptions.setText("Options");
528     jCheckBoxMenuItemKeyboardMap.setText("Keyboard Map");
529     jCheckBoxMenuItemKeyboardMap.setSelected(false);
530     jCheckBoxMenuItemKeyboardMap.setMnemonic('0');
531     jCheckBoxMenuItemKeyboardMap.addActionListener(new ActionListener()  {
532       public void actionPerformed(ActionEvent e) {
533         jCheckBoxMenuItemKeyboardMap_stateChanged(e);
534       }
535     });
536     jToolBar.add(openAction);
537     jToolBar.add(saveAction);
538     jToolBar.add(closeAction);
539     jToolBar.addSeparator();
540     jToolBar.add(undoAction);
541     jToolBar.add(redoAction);
542     jToolBar.addSeparator();
543     jToolBar.add(cutAction);
544     jToolBar.add(copyAction);
545     jToolBar.add(pasteAction);
546     jToolBar.addSeparator();
547     jToolBar.add(fontsComboBox);
548     jToolBar.addSeparator();
549     jToolBar.add(sizeComboBox);
550 
551     jToolBar.add(Box.createHorizontalGlue());
552 
553     jMenuFile.add(openAction);
554     jMenuFile.add(saveAction);
555     jMenuFile.add(saveAsAction);
556     jMenuFile.add(closeAction);
557     jMenuFile.addSeparator();
558     jMenuFile.add(exitAction);
559 
560     jMenuEdit.add(cutAction);
561     jMenuEdit.add(copyAction);
562     jMenuEdit.add(pasteAction);
563     jMenuEdit.addSeparator();
564     jMenuEdit.add(undoAction);
565     jMenuEdit.add(redoAction);
566 
567     jMenuOptions.add(jCheckBoxMenuItemKeyboardMap);
568     if(jMenuIM != nulljMenuOptions.add(jMenuIM);
569 
570     jMenuHelp.add(jMenuHelpAbout);
571 
572     jMenuBar1.add(jMenuFile);
573     jMenuBar1.add(jMenuEdit);
574     jMenuBar1.add(jMenuOptions);
575     jMenuBar1.add(jMenuHelp);
576 
577 //    textPane.setEditorKit(new UnicodeStyledEditorKit(GUK.getFontSet()));
578     textPane.setEditorKit(new StyledEditorKit());
579     textPane.setFont(new Font("Arial Unicode MS", Font.PLAIN, 14));
580     this.setJMenuBar(jMenuBar1);
581     contentPane.add(jToolBar, BorderLayout.NORTH);
582     contentPane.add(new JScrollPane(textPane), BorderLayout.CENTER);
583   }// jbInit()
584 
585   protected void updateTitle(){
586     String title = "GATE Unicode Editor - ";
587     if(file != nulltitle += file.getName();
588     else title += "Untitled";
589     if(docChangedtitle += "*";
590     frame.setTitle(title);
591   }// updateTitle()
592 
593   /**
594    * Main method
595    */
596   public static void main(String[] args) {
597     try {
598       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
599     }
600     catch(Exception e) {
601       e.printStackTrace();
602     }
603     /*
604     Object[] ffs = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
605     for(int i = 0; i < ffs.length; i++) System.out.println(ffs[i]);
606     */
607     new Editor();
608   }// main
609 
610   /**
611    * Help | About action performed
612    */
613   public void jMenuHelpAbout_actionPerformed(ActionEvent e) {
614     Editor_AboutBox dlg = new Editor_AboutBox(this);
615     dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
616     Dimension dlgSize = dlg.getPreferredSize();
617     Dimension frmSize = getSize();
618     Point loc = getLocation();
619     dlg.setLocation((frmSize.width - dlgSize.width+ loc.x,
620                     (frmSize.height - dlgSize.height+ loc.y);
621     dlg.setModal(true);
622     dlg.setVisible(true);
623   }// jMenuHelpAbout_actionPerformed(ActionEvent e)
624 
625   /**
626    * Overridden so we can exit when window is closed
627    */
628   protected void processWindowEvent(WindowEvent e) {
629     if (e.getID() == WindowEvent.WINDOW_CLOSING) {
630       exitAction.actionPerformed(null);
631     else {
632       super.processWindowEvent(e);
633     }
634   }// processWindowEvent(WindowEvent e)
635 
636   void jCheckBoxMenuItemKeyboardMap_stateChanged(ActionEvent e) {
637     Object imObject = getInputContext().getInputMethodControlObject();
638     if(imObject != null && imObject instanceof GateIM){
639       ((GateIM)imObject).setMapVisible(jCheckBoxMenuItemKeyboardMap.getState());
640     }else jCheckBoxMenuItemKeyboardMap.setState(false);
641   }// void jCheckBoxMenuItemKeyboardMap_stateChanged(ActionEvent e)
642 }// class Editor extends JFrame
643 
644 class LocaleSelectorMenuItem extends JRadioButtonMenuItem {
645   public LocaleSelectorMenuItem(Locale locale, Frame pframe){
646     super(locale.getDisplayName());
647     this.frame = pframe;
648     me = this;
649     myLocale = locale;
650     this.addActionListener(new ActionListener()  {
651       public void actionPerformed(ActionEvent e) {
652         me.setSelected(frame.getInputContext().selectInputMethod(myLocale));
653       }
654     });
655   }// LocaleSelectorMenuItem(Locale locale, Frame pframe)
656   Locale myLocale;
657   JRadioButtonMenuItem me;
658   Frame frame;
659 }// class LocaleSelectorMenuItem extends JRadioButtonMenuItem