001 /*
002 * LAPIS lightweight structured text processing system
003 *
004 * Copyright (C) 1998-2002 Carnegie Mellon University,
005 * Copyright (C) 2003 Massachusetts Institute of Technology.
006 * All rights reserved.
007 *
008 * This library is free software; you can redistribute it
009 * and/or modify it under the terms of the GNU General
010 * Public License as published by the Free Software
011 * Foundation, version 2.
012 *
013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/
014 */
015
016 package lapisx.swing;
017
018 import java.awt.*;
019 import java.awt.event.*;
020 import java.io.*;
021 import java.util.*;
022 import javax.swing.*;
023 import javax.swing.text.*;
024 import javax.swing.event.*;
025 import javax.swing.undo.*;
026
027
028 public class FileEditor extends JFrame {
029 private String defaultTitle;
030 private FileEditorPanel editorPanel;
031 private UndoManager undo = new UndoManager () {
032 };
033
034
035 public FileEditor (String title, JTextComponent editor) {
036 super (title);
037
038 defaultTitle = title;
039
040 Container contentPane = getContentPane ();
041 contentPane.setLayout (new BorderLayout ());
042
043 // Creat the file editor panel
044 editorPanel = new FileEditorPanel(editor) {
045 protected void handleInteractiveException(Exception exception) {
046 FileEditor.this.handleInteractiveException(exception);
047 }
048
049 protected FileChooser makeFileChooser() {
050 return FileEditor.this.makeFileChooser();
051 }
052
053 public void setFile (File file) {
054 editorPanel.setFile(file);
055
056 if (file == null)
057 setTitle (defaultTitle);
058 else
059 setTitle (defaultTitle + " - " + file.getName ());
060 }
061
062 };
063 contentPane.add(editorPanel, BorderLayout.CENTER);
064
065 // Create actions that depend on the editor.
066 cutAction = new AcceleratedAction
067 ("Cu&t", 'X', KeyEvent.CTRL_MASK,
068 getActionByName (DefaultEditorKit.cutAction));
069 copyAction = new AcceleratedAction
070 ("&Copy", 'C', KeyEvent.CTRL_MASK,
071 getActionByName (DefaultEditorKit.copyAction));
072 pasteAction = new AcceleratedAction
073 ("&Paste", 'V', KeyEvent.CTRL_MASK,
074 getActionByName (DefaultEditorKit.pasteAction));
075 selectAllAction = new AcceleratedAction
076 ("Select &All", 'A', KeyEvent.CTRL_MASK,
077 getActionByName (DefaultEditorKit.selectAllAction));
078
079
080 // Create the menubar
081 JMenuBar mb = new JMenuBar ();
082
083 JMenu fileMenu = new AcceleratedMenu ("&File");
084 fileMenu.add (newAction);
085 fileMenu.add (openAction);
086 fileMenu.add (saveAction);
087 fileMenu.add (saveAsAction);
088 fileMenu.add (closeAction);
089 mb.add (fileMenu);
090
091 JMenu editMenu = new AcceleratedMenu ("&Edit");
092 editMenu.add (undoAction);
093 editMenu.add (redoAction);
094 editMenu.addSeparator ();
095 editMenu.add (cutAction);
096 editMenu.add (copyAction);
097 editMenu.add (pasteAction);
098 editMenu.add (selectAllAction);
099 mb.add (editMenu);
100
101 editMenu.addMenuListener (new MenuListener () {
102 public void menuSelected(MenuEvent e) {
103 undoAction.setEnabled (undo.canUndo ());
104 redoAction.setEnabled (undo.canRedo ());
105
106 boolean selected = editorPanel.getEditorSelectionStart() <
107 editorPanel.getEditorSelectionEnd ();
108 cutAction.setEnabled (selected);
109 copyAction.setEnabled (selected);
110 }
111 public void menuDeselected(MenuEvent e) {
112 undoAction.setEnabled (true);
113 redoAction.setEnabled (true);
114 cutAction.setEnabled (true);
115 copyAction.setEnabled (true);
116 }
117 public void menuCanceled(MenuEvent e) {
118 undoAction.setEnabled (true);
119 redoAction.setEnabled (true);
120 cutAction.setEnabled (true);
121 copyAction.setEnabled (true);
122 }
123 });
124
125 setJMenuBar (mb);
126
127
128 CoalescingUndo.setUndoableEditListener(editorPanel.getEditorDocument(),
129 undo);
130
131 pack ();
132 }
133
134
135 protected JTextComponent makeEditor () {
136 return new JTextArea ();
137 }
138
139
140 protected void handleInteractiveException (Exception exception) {
141 exception.printStackTrace ();
142 JOptionPane.showMessageDialog (null, exception,
143 "Error", JOptionPane.ERROR_MESSAGE);
144 }
145
146
147 /**
148 * Action invoked by File/New command. Clears the editor.
149 */
150 public Action newAction = new AcceleratedAction ("&New", 'N',
151 KeyEvent.CTRL_MASK) {
152 public void actionPerformed (ActionEvent evt) {
153 if (okToClear ())
154 clear ();
155 }
156 };
157
158
159 /**
160 * Action invoked by File/Open command. Pops up a file-open dialog.
161 */
162 public Action openAction = new AcceleratedAction ("&Open...", 'O',
163 KeyEvent.CTRL_MASK) {
164 public void actionPerformed (ActionEvent evt) {
165 if (okToClear ())
166 open ();
167 }
168 };
169
170
171 /**
172 * Action invoked by File/Save command. Saves the contents of the edito.
173 */
174 public Action saveAction = new AcceleratedAction ("&Save", 'S',
175 KeyEvent.CTRL_MASK) {
176 public void actionPerformed (ActionEvent evt) {
177 File file = editorPanel.getFile();
178
179 if (file != null)
180 save (file);
181 else
182 save ();
183 }
184 };
185
186
187 /**
188 * Action invoked by File/Save As command. Pops up a save-as dialog.
189 */
190 public Action saveAsAction = new AcceleratedAction ("Save &As...") {
191 public void actionPerformed (ActionEvent evt) {
192 save ();
193 }
194 };
195
196
197 /**
198 * Action invoked by File/Close command. Disposes of this editor.
199 */
200 public Action closeAction = new AcceleratedAction ("&Close") {
201 public void actionPerformed (ActionEvent evt) {
202 if (okToClear ()) {
203 clear ();
204 setVisible (false);
205 }
206 }
207 };
208
209
210 /**
211 * Action invoked by Edit/Undo command. Undoes one editing action.
212 */
213 public Action undoAction = new AcceleratedAction ("&Undo", 'Z',
214 KeyEvent.CTRL_MASK) {
215 public void actionPerformed (ActionEvent evt) {
216 try {
217 undo.undo ();
218 } catch (CannotUndoException e) {
219 getToolkit ().beep ();
220 }
221 }
222 };
223
224
225 /**
226 * Action invoked by Edit/Redo command. Redoes one editing action.
227 */
228 public Action redoAction = new AcceleratedAction ("&Redo", 'Y',
229 KeyEvent.CTRL_MASK) {
230 public void actionPerformed (ActionEvent evt) {
231 try {
232 undo.redo ();
233 } catch (CannotRedoException e) {
234 getToolkit ().beep ();
235 }
236 }
237 };
238
239
240 /**
241 * Action invoked by Edit/Cut command. Cuts current selection
242 * to clipboard.
243 */
244 public Action cutAction;
245
246
247 /**
248 * Action invoked by Edit/Copy command. Copies current selection
249 * to clipboard.
250 */
251 public Action copyAction;
252
253
254 /**
255 * Action invoked by Edit/Paste action. Pastes clipboard.
256 */
257 public Action pasteAction;
258
259
260 /**
261 * Action invoked by Edit/Select All command. Selects entire editor.
262 */
263 public Action selectAllAction;
264
265
266 /**
267 * Gets original Edit/Cut, Copy, Paste, or Select-All actions
268 * from the editor.
269 */
270 Hashtable actions;
271 Action getActionByName (String name) {
272 if (actions == null) {
273 actions = new Hashtable ();
274 Action[] a = editorPanel.getEditor().getActions();
275 for (int i = 0; i < a.length; ++i)
276 actions.put (a[i].getValue (Action.NAME), a[i]);
277 }
278 return (Action) actions.get (name);
279 }
280
281
282 /**
283 * Clear the editor.
284 */
285 public void clear () {
286 editorPanel.clear();
287 undo.discardAllEdits ();
288 }
289
290
291 /**
292 * Checks whether or not the editor has unsaved content.
293 */
294 public boolean okToClear () {
295 return editorPanel.okToClear();
296 }
297
298
299 /**
300 * Pop up a file-open dialog to open a file into the editor.
301 */
302 public void open () {
303 editorPanel.open();
304
305 }
306
307
308 protected FileChooser makeFileChooser () {
309 return new FileChooser ();
310 }
311
312
313 /**
314 * Open a file (or URL) in the editor. Pops up a dialog box if
315 * an error occurs.
316 *
317 * @param f File to open
318 */
319 public void open (File f) {
320 editorPanel.open(f);
321 undo.discardAllEdits ();
322 }
323
324
325 /**
326 * Pop up a save-as dialog box, then saves the editor contents.
327 */
328 public boolean save () {
329 return editorPanel.save();
330 }
331
332
333 /**
334 * Save editor contents to a local file.
335 *
336 * @param f Local file to save
337 */
338 public boolean save (File f) {
339 return editorPanel.save(f);
340 }
341
342
343 /**
344 * Return editor contents
345 *
346 * @return editor contents as string
347 */
348 public String getText () {
349 return editorPanel.getText();
350 }
351
352
353 /**
354 * Set the editor contents.
355 */
356 public void setText (String text) {
357 editorPanel.setText(text);
358 }
359
360
361 /**
362 * Return the editor.
363 *
364 * @return editor as a JTextComponent
365 */
366 public JTextComponent getEditor () {
367 return editorPanel.getEditor();
368 }
369
370
371 /**
372 * Return the toolbar.
373 *
374 * @return toolbar as a JToolBar
375 */
376 public JToolBar getToolBar () {
377 return editorPanel.getToolBar();
378 }
379
380
381 /**
382 * Return the value of the dirty flag, which signals
383 * whether or not the editor's contents have been
384 * changed but not saved.
385 *
386 * @return the value of the dirty flag as a boolean
387 */
388 public boolean getDirty () {
389 return editorPanel.getDirty();
390 }
391
392
393 /**
394 * Set the dirty flag to the new boolean value.
395 */
396 public void setDirty (boolean dirty) {
397 editorPanel.setDirty(dirty);
398 }
399
400
401 /**
402 * Return the file from which the
403 * editor contents were loaded, or null if there
404 * was none.
405 *
406 * @return the name of the file from which the editor
407 * was loaded (or null if none exists) as a
408 * string
409 */
410 public File getFile () {
411 return editorPanel.getFile();
412 }
413
414
415 public static void main (String[] args) {
416 FileEditor fe = new FileEditor ("FileEditor", new JTextArea());
417 fe.addWindowListener (new WindowAdapter () {
418 public void windowClosing (WindowEvent event) {
419 System.exit (0);
420 }
421 });
422 if (args.length > 0)
423 fe.open (new File (args[0]));
424 fe.show ();
425 }
426
427 }