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.11 2002/04/26 13:20:13 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       ButtonGroup bg = new ButtonGroup();
139       Iterator localIter = installedLocales.iterator();
140       while(localIter.hasNext()){
141         Locale aLocale = (Locale)localIter.next();
142         item = new LocaleSelectorMenuItem(aLocale, frame);
143         jMenuIM.add(item);
144         bg.add(item);
145       }
146     }// if
147 
148     undoManager.setLimit(1000);
149     //OPEN ACTION
150     openAction = new AbstractAction("Open", new ImageIcon(
151             guk.Editor.class.getResource("img/openFile.gif"))){
152       public void actionPerformed(ActionEvent e){
153         int res = JOptionPane.OK_OPTION;
154         if(docChanged){
155           res = JOptionPane.showConfirmDialog(
156                 frame,
157                 "Close unsaved file " +
158                 (file== null?"Untitled":file.getName()) + "?",
159                 "Gate",
160                 JOptionPane.OK_CANCEL_OPTION,
161                 JOptionPane.WARNING_MESSAGE);
162         }
163         if(res == JOptionPane.OK_OPTION){
164           filer.setMultiSelectionEnabled(false);
165           filer.setDialogTitle("Select file to open...");
166           filer.setSelectedFile(null);
167           filer.setFileFilter(filer.getAcceptAllFileFilter());
168           int res1 = filer.showOpenDialog(frame);
169           if(res1 == filer.APPROVE_OPTION){
170             //we have the file, what's the encoding?
171             Object[] encodings = { "UTF-8", "UTF-16BE", "UTF-16LE", "UTF-16",
172                                    "ISO-8859-1", "US-ASCII"};
173             JComboBox encodingsCombo = new JComboBox(encodings);
174             encodingsCombo.setEditable(true);
175             int res2 = JOptionPane.showConfirmDialog(frame,
176                                           encodingsCombo,
177                                           "Encoding?",
178                                           JOptionPane.OK_CANCEL_OPTION,
179                                           JOptionPane.QUESTION_MESSAGE);
180             Object encoding = (res2 == JOptionPane.OK_OPTION) ?
181                               encodingsCombo.getSelectedItem() : null;
182             if(encoding == null) return;
183             file = filer.getSelectedFile();
184             try {
185               InputStreamReader reader = new InputStreamReader(
186                 new BufferedInputStream(new FileInputStream(file)),
187                 (String)encoding);
188               textPane.selectAll();
189               textPane.replaceSelection("");
190               textPane.read(reader, null);
191               reader.close();
192             } catch(FileNotFoundException fnfe) {
193               JOptionPane.showMessageDialog(frame,
194                                             "Cannot find the file specified!",
195                                             "Gate",
196                                             JOptionPane.ERROR_MESSAGE);
197               file = null;
198               docChanged = false;
199               updateTitle();
200             } catch(UnsupportedEncodingException usee) {
201               JOptionPane.showMessageDialog(frame,
202                                             "Unsupported encoding!\n" +
203                                             "Please choose another.",
204                                             "Gate",
205                                             JOptionPane.ERROR_MESSAGE);
206               file = null;
207               docChanged = false;
208               updateTitle();
209             } catch(IOException ioe) {
210               JOptionPane.showMessageDialog(
211                                   frame,
212                                   "Input/Output error! (wrong encoding?)\n" +
213                                   "Please try again.",
214                                   "Gate",
215                                   JOptionPane.ERROR_MESSAGE);
216               file = null;
217               docChanged = false;
218               updateTitle();
219             }
220             docChanged = false;
221             updateTitle();
222           }
223         }
224       }// actionPerformed(ActionEvent e)
225     };
226     openAction.putValue(Action.SHORT_DESCRIPTION, "Open file...");
227 
228 
229     //SAVE ACTION
230     saveAction = new AbstractAction("Save", new ImageIcon(
231             guk.Editor.class.getResource("img/saveFile.gif"))) {
232       public void actionPerformed(ActionEvent e){
233         if(docChanged){
234           if(file == null) saveAsAction.actionPerformed(null);
235           else {
236             //get the encoding
237             Object[] encodings = { "UTF-8", "UTF-16BE", "UTF-16LE", "UTF-16",
238                                    "ISO-8859-1", "US-ASCII"};
239             JComboBox encodingsCombo = new JComboBox(encodings);
240             encodingsCombo.setEditable(true);
241             int res2 = JOptionPane.showConfirmDialog(frame,
242                                           encodingsCombo,
243                                           "Encoding?",
244                                           JOptionPane.OK_CANCEL_OPTION,
245                                           JOptionPane.QUESTION_MESSAGE);
246             Object encoding = (res2 == JOptionPane.OK_OPTION) ?
247                               encodingsCombo.getSelectedItem() : null;
248             if(encoding == null) return;
249             try {
250               OutputStreamWriter writer = new OutputStreamWriter(
251                   new FileOutputStream(file), (String)encoding);
252               writer.write(textPane.getText());
253               writer.flush();
254               writer.close();
255               docChanged = false;
256               updateTitle();
257             } catch(UnsupportedEncodingException usee) {
258               JOptionPane.showMessageDialog(frame,
259                                             "Unsupported encoding!\n" +
260                                             "Please choose another.",
261                                             "Gate",
262                                             JOptionPane.ERROR_MESSAGE);
263               docChanged = true;
264               updateTitle();
265             } catch(IOException ioe) {
266               JOptionPane.showMessageDialog(frame,
267                                             "Input/Output error!\n" +
268                                             "Please try again.",
269                                             "Gate",
270                                             JOptionPane.ERROR_MESSAGE);
271               docChanged = true;
272               updateTitle();
273             }
274           }// else
275         }// if
276       }// actionPerformed(ActionEvent e)
277     };
278     saveAction.putValue(Action.SHORT_DESCRIPTION, "Save...");
279 
280     //SAVE AS ACTION
281     saveAsAction = new AbstractAction("Save as...", new ImageIcon(
282             guk.Editor.class.getResource("img/saveFile.gif"))){
283       public void actionPerformed(ActionEvent e) {
284           filer.setMultiSelectionEnabled(false);
285           filer.setDialogTitle("Select file to save to...");
286           filer.setSelectedFile(null);
287           filer.setFileFilter(filer.getAcceptAllFileFilter());
288           int res = filer.showSaveDialog(frame);
289           if(res == filer.APPROVE_OPTION){
290             File newFile = filer.getSelectedFile();
291             if(newFile == null) return;
292             int res1 = JOptionPane.OK_OPTION;
293             if(newFile.exists()){
294               res1 = JOptionPane.showConfirmDialog(
295                       frame,
296                       "Overwrite existing file " + newFile.getName() + "?",
297                       "Gate",
298                       JOptionPane.OK_CANCEL_OPTION,
299                       JOptionPane.WARNING_MESSAGE);
300             }
301             if(res1 == JOptionPane.OK_OPTION){
302               file = newFile;
303               docChanged = true;
304               saveAction.actionPerformed(null);
305             }
306           }
307       }// actionPerformed(ActionEvent e)
308     };
309     saveAsAction.putValue(Action.SHORT_DESCRIPTION, "Save as...");
310 
311     //CLOSE ACTION
312     closeAction = new AbstractAction("Close", new ImageIcon(
313             guk.Editor.class.getResource("img/closeFile.gif"))){
314       public void actionPerformed(ActionEvent e){
315         int res = JOptionPane.OK_OPTION;
316         if(docChanged){
317           res = JOptionPane.showConfirmDialog(
318                 frame,
319                 "Close unsaved file " +
320                 (file== null?"Untitled":file.getName()) + "?",
321                 "Gate",
322                 JOptionPane.OK_CANCEL_OPTION,
323                 JOptionPane.WARNING_MESSAGE);
324         }
325         if(res == JOptionPane.OK_OPTION){
326           textPane.selectAll();
327           textPane.replaceSelection("");
328           docChanged = false;
329           file = null;
330           updateTitle();
331         }
332       }// actionPerformed(ActionEvent e)
333     };
334     closeAction.putValue(Action.SHORT_DESCRIPTION, "Close...");
335 
336 
337     //EXIT ACTION
338     exitAction = new AbstractAction("Exit", new ImageIcon(
339             guk.Editor.class.getResource("img/exit.gif"))){
340       public void actionPerformed(ActionEvent e){
341         int res = JOptionPane.OK_OPTION;
342         if(docChanged){
343           res = JOptionPane.showConfirmDialog(
344                 frame,
345                 "Close unsaved file " +
346                 (file== null?"Untitled":file.getName()) + "?",
347                 "Gate",
348                 JOptionPane.OK_CANCEL_OPTION,
349                 JOptionPane.WARNING_MESSAGE);
350         }
351         if(res == JOptionPane.OK_OPTION){
352           frame.setVisible(false);
353           frame.dispose();
354         }
355       }// actionPerformed(ActionEvent e)
356     };
357     exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit...");
358 
359     //UNDO ACTION
360     undoAction = new AbstractAction("Undo", new ImageIcon(
361             guk.Editor.class.getResource("img/undo.gif"))){
362       public void actionPerformed(ActionEvent e){
363         if(undoManager.canUndo()) undoManager.undo();
364       }
365     };
366      undoAction.setEnabled(undoManager.canUndo());
367      undoAction.putValue(Action.SHORT_DESCRIPTION, "Undo...");
368 
369     //REDO ACTION
370     redoAction = new AbstractAction("Redo", new ImageIcon(
371             guk.Editor.class.getResource("img/redo.gif"))){
372       public void actionPerformed(ActionEvent e){
373         if(undoManager.canRedo()) undoManager.redo();
374       }
375     };
376     redoAction.setEnabled(undoManager.canRedo());
377     redoAction.putValue(Action.SHORT_DESCRIPTION, "Redo...");
378 
379     //COPY ACTION
380     copyAction = new AbstractAction("Copy", new ImageIcon(
381             guk.Editor.class.getResource("img/copy.gif"))){
382       public void actionPerformed(ActionEvent e){
383         textPane.copy();
384       }
385     };
386     copyAction.putValue(Action.SHORT_DESCRIPTION, "Copy...");
387 
388     //CUT ACTION
389     cutAction = new AbstractAction("Cut", new ImageIcon(
390             guk.Editor.class.getResource("img/cut.gif"))){
391       public void actionPerformed(ActionEvent e){
392         textPane.cut();
393       }
394     };
395     cutAction.putValue(Action.SHORT_DESCRIPTION, "Cut...");
396 
397     //PASTE ACTION
398     pasteAction = new AbstractAction("Paste", new ImageIcon(
399             guk.Editor.class.getResource("img/paste.gif"))){
400       public void actionPerformed(ActionEvent e){
401         textPane.paste();
402       }
403     };
404     pasteAction.putValue(Action.SHORT_DESCRIPTION, "Paste...");
405 
406     //attributesChangedAction
407     attributesChangedAction = new AbstractAction() {
408       public void actionPerformed(ActionEvent e) {
409         int start = textPane.getSelectionStart();
410         int end = textPane.getSelectionEnd();
411         //change the selection
412         MutableAttributeSet as = textPane.getInputAttributes();
413         StyleConstants.setFontFamily(as,
414                                     (String)fontsComboBox.getSelectedItem());
415         StyleConstants.setFontSize(as,
416                                    Integer.parseInt(
417                                    (String)sizeComboBox.getSelectedItem()));
418         textPane.setCharacterAttributes(as, false);
419         //restore selection
420         textPane.setCaretPosition(start);
421         textPane.moveCaretPosition(end);
422       }// actionPerformed(ActionEvent e)
423     };
424 
425     textPane.addPropertyChangeListener("document", new PropertyChangeListener(){
426       public void propertyChange(PropertyChangeEvent evt){
427         undoAction.setEnabled(undoManager.canUndo());
428         redoAction.setEnabled(undoManager.canRedo());
429         //add the document listener
430         textPane.getDocument().addDocumentListener(new DocumentListener(){
431           public void insertUpdate(DocumentEvent e){
432             changeOccured();
433           }
434           public void removeUpdate(DocumentEvent e){
435             changeOccured();
436           }
437           public void changedUpdate(DocumentEvent e){
438             changeOccured();
439           }
440           protected void changeOccured(){
441             undoAction.setEnabled(undoManager.canUndo());
442             undoAction.putValue(Action.SHORT_DESCRIPTION,
443                                 undoManager.getUndoPresentationName());
444             redoAction.setEnabled(undoManager.canRedo());
445             redoAction.putValue(Action.SHORT_DESCRIPTION,
446                                 undoManager.getRedoPresentationName());
447             if(docChanged) return;
448             else{
449               docChanged = true;
450               updateTitle();
451             }
452           }// changeOccured()
453         });
454         //add the document UNDO listener
455         undoManager.discardAllEdits();
456         textPane.getDocument().addUndoableEditListener(undoManager);
457       }// propertyChange(PropertyChangeEvent evt)
458     });
459 
460     fontsComboBox = new JComboBox(
461                         GraphicsEnvironment.getLocalGraphicsEnvironment().
462                         getAvailableFontFamilyNames()
463                         );
464     fontsComboBox.setEditable(false);
465     fontsComboBox.addActionListener(new ActionListener(){
466       public void actionPerformed(ActionEvent e){
467         attributesChangedAction.actionPerformed(null);
468       }// actionPerformed(ActionEvent e)
469     });
470 
471 
472     sizeComboBox = new JComboBox(new Object[]{"6", "8", "10", "12", "14", "16",
473                                               "18", "20", "22", "24", "26"});
474     sizeComboBox.setEditable(true);
475     sizeComboBox.addActionListener(new ActionListener(){
476       public void actionPerformed(ActionEvent e){
477         try {
478           Integer.parseInt((String)sizeComboBox.getSelectedItem());
479           //fire the action
480           attributesChangedAction.actionPerformed(null);
481         } catch(NumberFormatException nfe){
482           //invalid input, go to default
483           sizeComboBox.setSelectedIndex(3);
484         }
485       }//actionPerformed(ActionEvent e)
486     });
487 
488     //initialisation for the fonts and size combos
489     fontsComboBox.setSelectedItem(StyleConstants.getFontFamily(
490                                   textPane.getInputAttributes()));
491     sizeComboBox.setSelectedItem(String.valueOf(StyleConstants.getFontSize(
492                                   textPane.getInputAttributes())));
493     //keep them updated
494     textPane.addCaretListener(new CaretListener(){
495       public void caretUpdate(CaretEvent e) {
496         if(e.getDot() == e.getMark()){
497           fontsComboBox.setSelectedItem(StyleConstants.getFontFamily(
498                                         textPane.getCharacterAttributes()));
499           sizeComboBox.setSelectedItem(String.valueOf(StyleConstants.getFontSize(
500                                         textPane.getCharacterAttributes())));
501         }
502       }//caretUpdate(CaretEvent e)
503     });
504 
505     fontsComboBox.setMaximumSize(new Dimension(150,25));
506     //fontsComboBox.setMinimumSize(new Dimension(150,25));
507     fontsComboBox.setPreferredSize(new Dimension(150,25));
508     //fontsComboBox.setSize(new Dimension(150,25));
509     sizeComboBox.setMaximumSize(new Dimension(50,25));
510     //sizeComboBox.setMinimumSize(new Dimension(30,25));
511     sizeComboBox.setPreferredSize(new Dimension(50,25));
512     //sizeComboBox.setSize(new Dimension(30,25));
513     sizeComboBox.enableInputMethods(false);
514     //setIconImage(Toolkit.getDefaultToolkit().createImage(EditorFrame.class.getResource("[Your Icon]")));
515     contentPane = (JPanel) this.getContentPane();
516     contentPane.setLayout(new BorderLayout());
517     this.setSize(new Dimension(800, 600));
518     updateTitle();
519     jMenuFile.setText("File");
520     jMenuEdit.setText("Edit");
521     jMenuHelp.setText("Help");
522     jMenuHelpAbout.setText("About");
523     jMenuHelpAbout.addActionListener(new ActionListener()  {
524       public void actionPerformed(ActionEvent e) {
525         jMenuHelpAbout_actionPerformed(e);
526       }
527     });
528     jMenuOptions.setText("Options");
529     jCheckBoxMenuItemKeyboardMap.setText("Keyboard Map");
530     jCheckBoxMenuItemKeyboardMap.setSelected(false);
531     jCheckBoxMenuItemKeyboardMap.setMnemonic('0');
532     jCheckBoxMenuItemKeyboardMap.addActionListener(new ActionListener()  {
533       public void actionPerformed(ActionEvent e) {
534         jCheckBoxMenuItemKeyboardMap_stateChanged(e);
535       }
536     });
537     jToolBar.add(openAction);
538     jToolBar.add(saveAction);
539     jToolBar.add(closeAction);
540     jToolBar.addSeparator();
541     jToolBar.add(undoAction);
542     jToolBar.add(redoAction);
543     jToolBar.addSeparator();
544     jToolBar.add(cutAction);
545     jToolBar.add(copyAction);
546     jToolBar.add(pasteAction);
547     jToolBar.addSeparator();
548     jToolBar.add(fontsComboBox);
549     jToolBar.addSeparator();
550     jToolBar.add(sizeComboBox);
551 
552     jToolBar.add(Box.createHorizontalGlue());
553 
554     jMenuFile.add(openAction);
555     jMenuFile.add(saveAction);
556     jMenuFile.add(saveAsAction);
557     jMenuFile.add(closeAction);
558     jMenuFile.addSeparator();
559     jMenuFile.add(exitAction);
560 
561     jMenuEdit.add(cutAction);
562     jMenuEdit.add(copyAction);
563     jMenuEdit.add(pasteAction);
564     jMenuEdit.addSeparator();
565     jMenuEdit.add(undoAction);
566     jMenuEdit.add(redoAction);
567 
568     jMenuOptions.add(jCheckBoxMenuItemKeyboardMap);
569     if(jMenuIM != null) jMenuOptions.add(jMenuIM);
570 
571     jMenuHelp.add(jMenuHelpAbout);
572 
573     jMenuBar1.add(jMenuFile);
574     jMenuBar1.add(jMenuEdit);
575     jMenuBar1.add(jMenuOptions);
576     jMenuBar1.add(jMenuHelp);
577 
578 //    textPane.setEditorKit(new UnicodeStyledEditorKit(GUK.getFontSet()));
579     textPane.setEditorKit(new StyledEditorKit());
580     textPane.setFont(new Font("Arial Unicode MS", Font.PLAIN, 14));
581     this.setJMenuBar(jMenuBar1);
582     contentPane.add(jToolBar, BorderLayout.NORTH);
583     contentPane.add(new JScrollPane(textPane), BorderLayout.CENTER);
584   }// jbInit()
585 
586   protected void updateTitle(){
587     String title = "Gate Unicode Editor - ";
588     if(file != null) title += file.getName();
589     else title += "Untitled";
590     if(docChanged) title += "*";
591     frame.setTitle(title);
592   }// updateTitle()
593 
594   /**
595    * Main method
596    */
597   public static void main(String[] args) {
598     try {
599       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
600     }
601     catch(Exception e) {
602       e.printStackTrace();
603     }
604     /*
605     Object[] ffs = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
606     for(int i = 0; i < ffs.length; i++) System.out.println(ffs[i]);
607     */
608     new Editor();
609   }// main
610 
611   /**
612    * Help | About action performed
613    */
614   public void jMenuHelpAbout_actionPerformed(ActionEvent e) {
615     Editor_AboutBox dlg = new Editor_AboutBox(this);
616     Dimension dlgSize = dlg.getPreferredSize();
617     Dimension frmSize = getSize();
618     Point loc = getLocation();
619     dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x,
620                     (frmSize.height - dlgSize.height) / 2 + loc.y);
621     dlg.setModal(true);
622     dlg.show();
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