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