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 }