1
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
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
60 File file = null;
61
64 JFileChooser filer = new JFileChooser();
65
68 JFrame frame;
69 UndoManager undoManager = new UndoManager();
70
73 boolean docChanged = false;
74
75
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 }
101
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 Class.forName("guk.im.GateIMDescriptor");
111 installedLocales.addAll(Arrays.asList(new guk.im.GateIMDescriptor().
113 getAvailableLocales()));
114 }catch(Exception e){
115 }
118 try{
119 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 }
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 }
149 undoManager.setLimit(1000);
150 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 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 } };
227 openAction.putValue(Action.SHORT_DESCRIPTION, "Open file...");
228
229
230 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 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 } } } };
279 saveAction.putValue(Action.SHORT_DESCRIPTION, "Save...");
280
281 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 } };
310 saveAsAction.putValue(Action.SHORT_DESCRIPTION, "Save as...");
311
312 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 } };
335 closeAction.putValue(Action.SHORT_DESCRIPTION, "Close...");
336
337
338 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 } };
359 exitAction.putValue(Action.SHORT_DESCRIPTION, "Exit...");
360
361 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 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 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 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 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 = new AbstractAction() {
410 public void actionPerformed(ActionEvent e) {
411 int start = textPane.getSelectionStart();
412 int end = textPane.getSelectionEnd();
413 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 textPane.setCaretPosition(start);
423 textPane.moveCaretPosition(end);
424 } };
426
427 textPane.addPropertyChangeListener("document", new PropertyChangeListener(){
428 public void propertyChange(PropertyChangeEvent evt){
429 undoAction.setEnabled(undoManager.canUndo());
430 redoAction.setEnabled(undoManager.canRedo());
431 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 } });
456 undoManager.discardAllEdits();
458 textPane.getDocument().addUndoableEditListener(undoManager);
459 } });
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 } });
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 attributesChangedAction.actionPerformed(null);
483 } catch(NumberFormatException nfe){
484 sizeComboBox.setSelectedIndex(3);
486 }
487 } });
489
490 fontsComboBox.setSelectedItem(StyleConstants.getFontFamily(
492 textPane.getInputAttributes()));
493 sizeComboBox.setSelectedItem(String.valueOf(StyleConstants.getFontSize(
494 textPane.getInputAttributes())));
495 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 } });
506
507 fontsComboBox.setMaximumSize(new Dimension(150,25));
508 fontsComboBox.setPreferredSize(new Dimension(150,25));
510 sizeComboBox.setMaximumSize(new Dimension(50,25));
512 sizeComboBox.setPreferredSize(new Dimension(50,25));
514 sizeComboBox.enableInputMethods(false);
516 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 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 }
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 }
596
599 public static void main(String[] args) {
600 try {
601 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
602 }
603 catch(Exception e) {
604 e.printStackTrace();
605 }
606
610 new Editor();
611 }
613
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 }
628
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 }
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 }}
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 } Locale myLocale;
660 JRadioButtonMenuItem me;
661 Frame frame;
662 }