/* Edit.java -- A simple text editor. Matt Mahoney, mmahoney@cs.fit.edu To edit a file, enter the following command: java Edit [filename] where [filename] is optional. You can then edit or create a file by typing into the text box. If the file does not exist, then a new one will be created. If no filename is given, then you can begin typing and then are prompted to enter a file name when saving or exiting. The program displays a text box for editing and a menu bar as follows: ------------------------------------------------ | Edit - Untitled _ [] X | |----------------------------------------------| | File | |----------------------------------------------| | New | | | Open | | | Save Ctrl+S | | | Save as | | | Print | -------------------- | | ------------ | | Save changes? | | | Exit Ctrl+X | | ------- ------- | | |--------------| | | Yes | | No | | | | | ------- ------- | | | -------------------- | | | ------------------------------------------------ Selecting NEW creates a blank, untitled file for editing. If the previous file has been changed since last being saved, you are prompted to save the file. If you click "Yes" and the file is untitled, you are prompted for a file name in a "Save as" dialog box. Selecting OPEN prompts for a file name with an "Open" dialog box. If the file exists, it is loaded into the text box. Otherwise the text box is cleared. If the contents of the text box have changed, then you are first prompted to save as with NEW. Selecting SAVE saves the current file to disk. If the file is untitled, you are prompted for a file name, which then appears in the title bar. Selecting SAVE AS prompts you to enter a file name whether or not the file is untitled. The new file name then becomes the new title. Selecting PRINT prints the file to the printer. Selecting EXIT or clicking on the [X] (close) box exits the program and closes the window. If the file has been changed since the last save, you are asked whether you wish to save the file as with NEW. */ import java.io.*; import java.util.*; import java.awt.*; import java.awt.event.*; // The main program public class Edit extends Frame implements ActionListener, WindowListener, TextListener { private TextArea textArea=new TextArea("", 25, 80); // Edit window private String filename="Untitled"; // File name private boolean isChanged=false; // Does the file need saving? // Constructor, args are passed from main() public Edit(String args[]) { // Add menus. Add self as event handler to menu items. MenuBar mb=new MenuBar(); setMenuBar(mb); Menu m=new Menu("File"); mb.add(m); MenuItem mi; mi=new MenuItem("New"); mi.addActionListener(this); m.add(mi); mi=new MenuItem("Open"); mi.addActionListener(this); m.add(mi); mi=new MenuItem("Save", new MenuShortcut(KeyEvent.VK_S)); mi.addActionListener(this); m.add(mi); mi=new MenuItem("Save as"); mi.addActionListener(this); m.add(mi); mi=new MenuItem("Print"); mi.addActionListener(this); m.add(mi); m.insertSeparator(5); // Insert line mi=new MenuItem("Exit", new MenuShortcut(KeyEvent.VK_X)); mi.addActionListener(this); m.add(mi); // Add the textArea to the window. Add self as event handler setLayout(new BorderLayout()); add("Center", textArea); textArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); // 12pt courier textArea.addTextListener(this); // Add self as event handler for window closing addWindowListener(this); // Set the title and load the file. If no file name is given, create // a blank file titled "Untitled". if (args.length>0) loadFile(args[0]); // Read or create file else loadFile("Untitled"); // Create new untitled file // Make the window visible pack(); // Set the window size to fit all components show(); // Make window visible } // Start the program public static void main(String[] args) { new Edit(args); } // saveChanges() -- If the text has been edited since the last // load or save, ask the user (in a Yes-No dialog) whether to save // changes. If yes, then save the file with the current filename. // If untitled, prompt for a filename (using a Save-as file dialog). private void saveChanges() { if (isChanged && new ChoiceDialog(this, new String[] { "Save changes to "+filename+"?", "Yes", "No"}).get()==1) // yes? saveFile(false); } // loadFile(newfile) -- Clear the edit window and load a new file into // the editor. If the previous file needs saving, then save it first. Set // the title to the new file. If the new file is null, then create a new // blank untitled file. If the new file does not exist, then // start with a blank text field and warn the user. private void loadFile(String newfile) { saveChanges(); textArea.setText(""); rename(newfile); // Read the file if it exists if (!filename.equals("Untitled")) { try { InputStream in=new FileInputStream(filename); int n; byte[] a=new byte[4096]; while ((n=in.read(a))>0) textArea.append(new String(a, 0, n)); in.close(); } catch (FileNotFoundException x) { // Warn if new file new ChoiceDialog(this, new String[] { "Creating new file: "+filename, "OK"}).get(); } catch (IOException x) {} } isChanged=false; } // Save the file. Prompt for a filename if untitled or prompt is true private void saveFile(boolean prompt) { if (filename.equals("Untitled") || prompt) { FileDialog d=new FileDialog(this, "", FileDialog.SAVE); d.show(); if (d.getFile()!=null) rename(d.getDirectory()+d.getFile()); } // Save the file. Display any errors in an OK dialog box try { Writer out=new FileWriter(filename); out.write(textArea.getText()); out.close(); isChanged=false; } catch (IOException x) { new ChoiceDialog(this, new String[] { "Error saving "+filename+": "+x, "OK"}); } } // If the file needs saving, prompt user before exiting private void exit(Window parent) { saveChanges(); dispose(); System.exit(0); } // Change filename and the title bar to newname private void rename(String newname) { filename=newname; setTitle("Edit - "+filename); } // Event handlers public void windowActivated(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} // User clicks on [X] public void windowClosing(WindowEvent e) { exit(e.getWindow()); } // Text is edited public void textValueChanged(TextEvent e) { isChanged=true; } // Menu item event handlers public void actionPerformed(ActionEvent e) { // New -- Create untitled file if (e.getActionCommand().equals("New")) loadFile("Untitled"); // Open -- prompt for file name and load else if (e.getActionCommand().equals("Open")) { System.out.println("Open"); FileDialog d=new FileDialog(this, "", FileDialog.LOAD); d.show(); if (d.getFile()!=null) loadFile(d.getDirectory()+d.getFile()); } // Save -- use current file name unless untitled else if (e.getActionCommand().equals("Save")) saveFile(false); // Save as -- prompt for new file name else if (e.getActionCommand().equals("Save as")) saveFile(true); // Print to printer else if (e.getActionCommand().equals("Print")) { PrintJob pj=Toolkit.getDefaultToolkit().getPrintJob(this, filename, new Properties()); // opens printer properties dialog box if (pj!=null) { // user has a printer and didn't cancel? final int fontsize=10; // in pts final Font f=new Font("Monospaced", Font.PLAIN, fontsize); final int height=pj.getPageDimension().height; // in pts final int margin=pj.getPageResolution()/2; // 1/2 inch margins String text=textArea.getText(); // text to be printed int ypos=height; // vertical position from top of page in pts Graphics g=null; // graphics for current page while (text!=null && text.length()>0) { if (ypos>height-margin) { // start a new page if (g!=null) g.dispose(); // eject previous page if any g=pj.getGraphics(); // start next page g.setFont(f); g.setColor(Color.black); ypos=margin+fontsize; // go to top of page } String s=""; // next line of text to print int i=text.indexOf('\n'); // remove first line of text, put in s if (i<0) { // last line? s=text; text=null; } else if (i>80) { // break long line s=text.substring(0, 80); text=text.substring(80); } else { // normal line of text s=text.substring(0, i); text=text.substring(i+1); } if (s.endsWith("\r")) // chop off CR in case lines end in CR-LF s=s.substring(0, s.length()-1); g.drawString(s, margin, ypos); // print s ypos+=fontsize+2; } if (g!=null) g.dispose(); // eject last page pj.end(); // send job to printer } } // Exit -- same as click on [X] else if (e.getActionCommand().equals("Exit")) exit(this); } } /* A ChoiceDialog is used to display a message and obtain a multiple choice response. The constructor is passed the parent frame and an array of strings. The first string is the question, and the remaining strings are the labels of the buttons which the user may press. The get() method returns the number of the button pressed (starting with 1), or 0 if the user closed the box without pressing a button. The dialog box is modal: it remains active until dismissed by the user. For instance (when called from a Frame): new ChoiceDialog(this, new String[] {"Save changes?", "Yes", "No"}).get() displays a dialog window like this on the center of the screen: |----------------------| | Save changes? | | | | |-----| |-----| | | | Yes | | No | | | |-----| |-----| | | | |----------------------| then waits for the user to press a button. It returns 1 for "Yes" and 2 for "No". */ class ChoiceDialog extends Dialog implements ActionListener { private Label label; // question (args[0]) private Button[] buttons; // answer buttons (labelled args[1..n]) private Panel panel; // Container for buttons at bottom of dialog box private int answer=0; // Last button clicked (1-n) // Constructor. parent is the window creating the dialog. // args[0] is the question, args[1..n] are n possible answers. public ChoiceDialog(Frame parent, String[] args) { super(parent, "", true); // no title, modal panel=new Panel(); panel.setLayout(new FlowLayout()); setLayout(new BorderLayout()); add("Center", new Label(args[0])); add("South", panel); label=new Label(args[0]); buttons=new Button[args.length-1]; for (int i=0; i