1   /*
2    * Editor.java
3    *
4    * Copyright (c) 1998-2005, 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.20 2005/01/11 13:51:38 ian Exp $
16   */
17  package guk;
18  
19  import java.awt.*;
20  import java.awt.event.*;
21  import java.beans.PropertyChangeEvent;
22  import java.beans.PropertyChangeListener;
23  import java.io.*;
24  import java.util.*;
25  
26  import javax.swing.*;
27  import javax.swing.event.*;
28  import javax.swing.text.*;
29  import javax.swing.undo.UndoManager;
30  
31  import guk.im.GateIM;
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 == JFileChooser.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 == JFileChooser.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         }
357       }// actionPerformed(ActionEvent e)
358     };
359     exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit...");
360 
361     //UNDO ACTION
362     undoAction = new AbstractAction("Undo", new ImageIcon(
363             guk.Editor.class.getResource("img/undo.gif"))){
364       public void actionPerformed(ActionEvent e){
365         if(undoManager.canUndo()) undoManager.undo();
366       }
367     };
368      undoAction.setEnabled(undoManager.canUndo());
369      undoAction.putValue(Action.SHORT_DESCRIPTION, "Undo...");
370 
371     //REDO ACTION
372     redoAction = new AbstractAction("Redo", new ImageIcon(
373             guk.Editor.class.getResource("img/redo.gif"))){
374       public void actionPerformed(ActionEvent e){
375         if(undoManager.canRedo()) undoManager.redo();
376       }
377     };
378     redoAction.setEnabled(undoManager.canRedo());
379     redoAction.putValue(Action.SHORT_DESCRIPTION, "Redo...");
380 
381     //COPY ACTION
382     copyAction = new AbstractAction("Copy", new ImageIcon(
383             guk.Editor.class.getResource("img/copy.gif"))){
384       public void actionPerformed(ActionEvent e){
385         textPane.copy();
386       }
387     };
388     copyAction.putValue(Action.SHORT_DESCRIPTION, "Copy...");
389 
390     //CUT ACTION
391     cutAction = new AbstractAction("Cut", new ImageIcon(
392             guk.Editor.class.getResource("img/cut.gif"))){
393       public void actionPerformed(ActionEvent e){
394         textPane.cut();
395       }
396     };
397     cutAction.putValue(Action.SHORT_DESCRIPTION, "Cut...");
398 
399     //PASTE ACTION
400     pasteAction = new AbstractAction("Paste", new ImageIcon(
401             guk.Editor.class.getResource("img/paste.gif"))){
402       public void actionPerformed(ActionEvent e){
403         textPane.paste();
404       }
405     };
406     pasteAction.putValue(Action.SHORT_DESCRIPTION, "Paste...");
407 
408     //attributesChangedAction
409     attributesChangedAction = new AbstractAction() {
410       public void actionPerformed(ActionEvent e) {
411         int start = textPane.getSelectionStart();
412         int end = textPane.getSelectionEnd();
413         //change the selection
414         MutableAttributeSet as = textPane.getInputAttributes();
415         StyleConstants.setFontFamily(as,
416                                     (String)fontsComboBox.getSelectedItem());
417         StyleConstants.setFontSize(as,
418                                    Integer.parseInt(
419                                    (String)sizeComboBox.getSelectedItem()));
420         textPane.setCharacterAttributes(as, false);
421         //restore selection
422         textPane.setCaretPosition(start);
423         textPane.moveCaretPosition(end);
424       }// actionPerformed(ActionEvent e)
425     };
426 
427     textPane.addPropertyChangeListener("document", new PropertyChangeListener(){
428       public void propertyChange(PropertyChangeEvent evt){
429         undoAction.setEnabled(undoManager.canUndo());
430         redoAction.setEnabled(undoManager.canRedo());
431         //add the document listener
432         textPane.getDocument().addDocumentListener(new DocumentListener(){
433           public void insertUpdate(DocumentEvent e){
434             changeOccured();
435           }
436           public void removeUpdate(DocumentEvent e){
437             changeOccured();
438           }
439           public void changedUpdate(DocumentEvent e){
440             changeOccured();
441           }
442           protected void changeOccured(){
443             undoAction.setEnabled(undoManager.canUndo());
444             undoAction.putValue(Action.SHORT_DESCRIPTION,
445                                 undoManager.getUndoPresentationName());
446             redoAction.setEnabled(undoManager.canRedo());
447             redoAction.putValue(Action.SHORT_DESCRIPTION,
448                                 undoManager.getRedoPresentationName());
449             if(docChanged) return;
450             else{
451               docChanged = true;
452               updateTitle();
453             }
454           }// changeOccured()
455         });
456         //add the document UNDO listener
457         undoManager.discardAllEdits();
458         textPane.getDocument().addUndoableEditListener(undoManager);
459       }// propertyChange(PropertyChangeEvent evt)
460     });
461 
462     fontsComboBox = new JComboBox(
463                         GraphicsEnvironment.getLocalGraphicsEnvironment().
464                         getAvailableFontFamilyNames()
465                         );
466     fontsComboBox.setEditable(false);
467     fontsComboBox.addActionListener(new ActionListener(){
468       public void actionPerformed(ActionEvent e){
469         attributesChangedAction.actionPerformed(null);
470       }// actionPerformed(ActionEvent e)
471     });
472 
473 
474     sizeComboBox = new JComboBox(new Object[]{"6", "8", "10", "12", "14", "16",
475                                               "18", "20", "22", "24", "26"});
476     sizeComboBox.setEditable(true);
477     sizeComboBox.addActionListener(new ActionListener(){
478       public void actionPerformed(ActionEvent e){
479         try {
480           Integer.parseInt((String)sizeComboBox.getSelectedItem());
481           //fire the action
482           attributesChangedAction.actionPerformed(null);
483         } catch(NumberFormatException nfe){
484           //invalid input, go to default
485           sizeComboBox.setSelectedIndex(3);
486         }
487       }//actionPerformed(ActionEvent e)
488     });
489 
490     //initialisation for the fonts and size combos
491     fontsComboBox.setSelectedItem(StyleConstants.getFontFamily(
492                                   textPane.getInputAttributes()));
493     sizeComboBox.setSelectedItem(String.valueOf(StyleConstants.getFontSize(
494                                   textPane.getInputAttributes())));
495     //keep them updated
496     textPane.addCaretListener(new CaretListener(){
497       public void caretUpdate(CaretEvent e) {
498         if(e.getDot() == e.getMark()){
499           fontsComboBox.setSelectedItem(StyleConstants.getFontFamily(
500                                         textPane.getCharacterAttributes()));
501           sizeComboBox.setSelectedItem(String.valueOf(StyleConstants.getFontSize(
502                                         textPane.getCharacterAttributes())));
503         }
504       }//caretUpdate(CaretEvent e)
505     });
506 
507     fontsComboBox.setMaximumSize(new Dimension(150,25));
508     //fontsComboBox.setMinimumSize(new Dimension(150,25));
509     fontsComboBox.setPreferredSize(new Dimension(150,25));
510     //fontsComboBox.setSize(new Dimension(150,25));
511     sizeComboBox.setMaximumSize(new Dimension(50,25));
512     //sizeComboBox.setMinimumSize(new Dimension(30,25));
513     sizeComboBox.setPreferredSize(new Dimension(50,25));
514     //sizeComboBox.setSize(new Dimension(30,25));
515     sizeComboBox.enableInputMethods(false);
516     //setIconImage(Toolkit.getDefaultToolkit().createImage(EditorFrame.class.getResource("[Your Icon]")));
517     contentPane = (JPanel) this.getContentPane();
518     contentPane.setLayout(new BorderLayout());
519     this.setSize(new Dimension(800, 600));
520     updateTitle();
521     jMenuFile.setText("File");
522     jMenuEdit.setText("Edit");
523     jMenuHelp.setText("Help");
524     jMenuHelpAbout.setText("About");
525     jMenuHelpAbout.addActionListener(new ActionListener()  {
526       public void actionPerformed(ActionEvent e) {
527         jMenuHelpAbout_actionPerformed(e);
528       }
529     });
530     jMenuOptions.setText("Options");
531     jCheckBoxMenuItemKeyboardMap.setText("Keyboard Map");
532     jCheckBoxMenuItemKeyboardMap.setSelected(false);
533     jCheckBoxMenuItemKeyboardMap.setMnemonic('0');
534     jCheckBoxMenuItemKeyboardMap.addActionListener(new ActionListener()  {
535       public void actionPerformed(ActionEvent e) {
536         jCheckBoxMenuItemKeyboardMap_stateChanged(e);
537       }
538     });
539     jToolBar.add(openAction);
540     jToolBar.add(saveAction);
541     jToolBar.add(closeAction);
542     jToolBar.addSeparator();
543     jToolBar.add(undoAction);
544     jToolBar.add(redoAction);
545     jToolBar.addSeparator();
546     jToolBar.add(cutAction);
547     jToolBar.add(copyAction);
548     jToolBar.add(pasteAction);
549     jToolBar.addSeparator();
550     jToolBar.add(fontsComboBox);
551     jToolBar.addSeparator();
552     jToolBar.add(sizeComboBox);
553 
554     jToolBar.add(Box.createHorizontalGlue());
555 
556     jMenuFile.add(openAction);
557     jMenuFile.add(saveAction);
558     jMenuFile.add(saveAsAction);
559     jMenuFile.add(closeAction);
560     jMenuFile.addSeparator();
561     jMenuFile.add(exitAction);
562 
563     jMenuEdit.add(cutAction);
564     jMenuEdit.add(copyAction);
565     jMenuEdit.add(pasteAction);
566     jMenuEdit.addSeparator();
567     jMenuEdit.add(undoAction);
568     jMenuEdit.add(redoAction);
569 
570     jMenuOptions.add(jCheckBoxMenuItemKeyboardMap);
571     if(jMenuIM != null) jMenuOptions.add(jMenuIM);
572 
573     jMenuHelp.add(jMenuHelpAbout);
574 
575     jMenuBar1.add(jMenuFile);
576     jMenuBar1.add(jMenuEdit);
577     jMenuBar1.add(jMenuOptions);
578     jMenuBar1.add(jMenuHelp);
579 
580 //    textPane.setEditorKit(new UnicodeStyledEditorKit(GUK.getFontSet()));
581     textPane.setEditorKit(new StyledEditorKit());
582     textPane.setFont(new Font("Arial Unicode MS", Font.PLAIN, 14));
583     this.setJMenuBar(jMenuBar1);
584     contentPane.add(jToolBar, BorderLayout.NORTH);
585     contentPane.add(new JScrollPane(textPane), BorderLayout.CENTER);
586   }// jbInit()
587 
588   protected void updateTitle(){
589     String title = "GATE Unicode Editor - ";
590     if(file != null) title += file.getName();
591     else title += "Untitled";
592     if(docChanged) title += "*";
593     frame.setTitle(title);
594   }// updateTitle()
595 
596   /**
597    * Main method
598    */
599   public static void main(String[] args) {
600     try {
601       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
602     }
603     catch(Exception e) {
604       e.printStackTrace();
605     }
606     /*
607     Object[] ffs = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
608     for(int i = 0; i < ffs.length; i++) System.out.println(ffs[i]);
609     */
610     new Editor();
611   }// main
612 
613   /**
614    * Help | About action performed
615    */
616   public void jMenuHelpAbout_actionPerformed(ActionEvent e) {
617     Editor_AboutBox dlg = new Editor_AboutBox(this);
618     dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
619     Dimension dlgSize = dlg.getPreferredSize();
620     Dimension frmSize = getSize();
621     Point loc = getLocation();
622     dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x,
623                     (frmSize.height - dlgSize.height) / 2 + loc.y);
624     dlg.setModal(true);
625     dlg.setVisible(true);
626   }// jMenuHelpAbout_actionPerformed(ActionEvent e)
627 
628   /**
629    * Overridden so we can exit when window is closed
630    */
631   protected void processWindowEvent(WindowEvent e) {
632     if (e.getID() == WindowEvent.WINDOW_CLOSING) {
633       exitAction.actionPerformed(null);
634     } else {
635       super.processWindowEvent(e);
636     }
637   }// processWindowEvent(WindowEvent e)
638 
639   void jCheckBoxMenuItemKeyboardMap_stateChanged(ActionEvent e) {
640     Object imObject = getInputContext().getInputMethodControlObject();
641     if(imObject != null && imObject instanceof GateIM){
642       ((GateIM)imObject).setMapVisible(jCheckBoxMenuItemKeyboardMap.getState());
643     }else jCheckBoxMenuItemKeyboardMap.setState(false);
644   }// void jCheckBoxMenuItemKeyboardMap_stateChanged(ActionEvent e)
645 }// class Editor extends JFrame
646 
647 class LocaleSelectorMenuItem extends JRadioButtonMenuItem {
648   public LocaleSelectorMenuItem(Locale locale, Frame pframe){
649     super(locale.getDisplayName());
650     this.frame = pframe;
651     me = this;
652     myLocale = locale;
653     this.addActionListener(new ActionListener()  {
654       public void actionPerformed(ActionEvent e) {
655         me.setSelected(frame.getInputContext().selectInputMethod(myLocale));
656       }
657     });
658   }// LocaleSelectorMenuItem(Locale locale, Frame pframe)
659   Locale myLocale;
660   JRadioButtonMenuItem me;
661   Frame frame;
662 }// class LocaleSelectorMenuItem extends JRadioButtonMenuItem