Application: SimpleTextEditor: Garage Pad

     

This program, the Garage Editor, is a simple text editor that allows users to open files, save their file, copy and paste, and display help information.

This is a terrific little application because it demonstrates a number of concepts important in the creation of real Java programs.

Demonstrates

Creating a basic GUI window, creating scrollbars on demand, creating a toolbar containing menus that contain menu items, how to use the JFileChooser to save and open files, cleanly closing an open document, exiting from an application, displaying informational messages to the user (like JavaScript alerts or Visual Basic MsgBox), using keyboard mnemonics (using key combinations such as Ctrl+S for Save), and using the preferences API to save user-specific preference data regarding how the application is run. In general, this is a pretty tight application, and does all its work in one file.

graphics/fridge_icon.jpg

LUHN ALGORITHM FOR VALIDATING CREDIT CARDS

The LUHN (or MOD 10) algorithm used for validating credit card numbers is widely known and accepted. Here is how it works:

  1. Start at the second digit from the right. Double each alternating digit. (Leave the last digit on the right alone since it is the check).

  2. Add each individual digit comprising the products from step 1 to each of the unaffected digits.

  3. If the product of step 2 ends in 0 (that is, can be divided by 10 with no remainder), the number is valid.

    For example, using 4111111111111111 (the common credit card test number):

    number: 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    multiply: 2 2 2 2 2 2 2 2

    product: 8 2 2 2 2 2 2 2

    Add them up (products are in parens):

    (8) + 1 + (2) + 1 + (2) + 1 + (2) + 1 + (2) + 1 + (2) + 1 + (2) + 1 + (2) + 1 = 30

    Divide by 10: 30/10 = 3. The number is good. (Because 30 MOD 10) = 0


Running the application and entering some text looks something like what you see in Figure 35.1.

Figure 35-1. The running text editor.

graphics/35fig01.gif


This looks like a lot of code, but there are also a lot of comments explaining what's going on.

GarageEditor.java
 

 /**<p>  * Presents a simple editor that allows  * you to create a new file, open a file,  * and save a file.  * <p>  * The chief benefit here is that you can see  * how to interact with a meaningful program  * without getting bogged down by layout manager  * details.  * <p>  * Illustrates how to create a menu and menu items  * <p>  * Shows how to attach commands to be invoked when  * an item is clicked.  * <p>  * Shows how to use common keystrokes for commands (ie,  * press CTRL+S on the keyboard to Save the file).  * <p>  * Shows how to read files in and out for editing.  * <p>  * Shows how to use OK/Cancel dialogs  * <p>  * Shows how to use user preferences  * </p>  * Could benefit from threading to improve  * responsiveness.  * @author Eben Hewitt  * @see JFrame  * @see JTextArea  * @see JOptionPane  **/ import java.io.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.prefs.*; public class GarageEditor extends JFrame {    //holds user preferences private Preferences prefs = null;    //the user will type into this    private JTextArea textArea;    //lets you easily specify where you want    messages to go.    private static final int STDOUT = 0;    private static final int ALERT = 1;    //hold File menu commands    private static final String NEW_CMD = "New";    //default location at which to open window    private static final int DEF_WINDOW_X_LOCATION = 150;    private static final int DEF_WINDOW_Y_LOCATION = 150;    public GarageEditor() {        // Add a menu bar and a JTextArea to the        // window, and show it on the screen. The        // first line of this routine calls the        // constructor from the superclass to specify        // a title for the window. The pack() command        // sets the size of the window to        // be just large enough to hold its contents.             super("Garage Editor");           //make a menu bar to hold menus               JMenuBar menuBar = new JMenuBar();           //add the File menu to it               menuBar.add(makeFileMenu());           //add the About menu to it               menuBar.add(makeHelpMenu());              //put the completed menu bar into                  the frame                setJMenuBar(menuBar);              //create a new JTextArea              //give it some default text and set its size                int rows = 25;                int cols = 35;              textArea = new JTextArea("choose                               file...",                               rows, cols);           //white by default anyway, but highlights it             textArea.setBackground(Color.WHITE);             textArea.setMargin(new Insets(3,3,3,3));              //make a set of scrolling controls to hold              //the text area              JScrollPane scroller =                            new JScrollPane(textArea);            //put the scroller into the content pane            setContentPane(scroller);            //stop app when user closes window             setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);           pack();         doLocation();         //show the frame         setVisible(true);     }    /**     * Sets up the location of the window using     * preferences data. Opens the editor in the     * last location that the user had it in. If     * not set, use a default value defined in     * class constants above.     */    private void doLocation() {       //get reference to preferences       Preferences prefs = Preferences.userNodeForPackage(this.getClass());       //retrieve the int. if there is no int stored       //in prefs of the given string name, use the       default       int xLocation = prefs.getInt("WINDOW_X_LOCATION",       DEF_WINDOW_X_LOCATION);       int yLocation = prefs.getInt("WINDOW_Y_LOCATION",       DEF_WINDOW_Y_LOCATION);       //open the window at either the last       //user location, or the default       setLocation(xLocation,yLocation);    }       /**        * Makes the File menu        * @return JMenu containing the New, Open, Save,        * and Exit items        */       private JMenu makeFileMenu() {           //get the action command from the menu           //to determine what the user wants to do           //and call a separate method to do the           //dirty work           ActionListener listener = new                     ActionListener() {           public void actionPerformed(ActionEvent                     event) {              String command = event.getActionCommand();              if (command.equals("New")){                   doNew();              }              else if(command.equals("Open...")){                   doOpen();              }              else if(command.equals("Save...")){                   doSave();              }              else if(command.equals("Close")){                   doClose();              }              else if (command.equals("Exit")){                   doExit();              }           }           };        JMenu fileMenu = new JMenu("File");             //NEW        JMenuItem newCmd = new JMenuItem("New");        newCmd.setAccelerator(KeyStroke.getKeyStroke               ("ctrl N"));        newCmd.addActionListener(listener);        fileMenu.add(newCmd);        //OPEN        JMenuItem openCmd = new JMenuItem("Open...");        openCmd.setAccelerator(KeyStroke .            getKeyStroke("ctrl O"));        openCmd.addActionListener(listener);        fileMenu.add(openCmd);        //SAVE        JMenuItem saveCmd = new JMenuItem("Save...");        saveCmd.setAccelerator(KeyStroke .            getKeyStroke("ctrl S"));        saveCmd.addActionListener(listener);        fileMenu.add(saveCmd);        //CLOSE        JMenuItem closeCmd = new JMenuItem("Close");        closeCmd.setAccelerator(KeyStroke .            getKeyStroke("ctrl L"));        closeCmd.addActionListener(listener);        fileMenu.add(closeCmd);        //QUIT        JMenuItem exitCmd = new JMenuItem("Exit");        exitCmd.setAccelerator(KeyStroke             .getKeyStroke("ctrl E"));        exitCmd.addActionListener(listener);        fileMenu.add(exitCmd);        return fileMenu;         }     /**      * Creates the About Menu      * @return JMenu The Help menu containing the      * About item.      */    private JMenu makeHelpMenu() {        //get the action command from the menu        //to determine what the user wants to do        //and call a separate method to do the        //dirty work        ActionListener listener = new ActionListener() {        public void actionPerformed(ActionEvent event) {              String command = event.getActionCommand();              if (command.equals("About"))                         doAbout();               }         };    JMenu helpMenu = new JMenu("Help");      //ABOUT    JMenuItem aboutCmd = new JMenuItem("About");       aboutCmd.setAccelerator                (KeyStroke.getKeyStroke("ctrl A"));    aboutCmd.addActionListener(listener);    helpMenu.add(aboutCmd);    return helpMenu;  }  private void doAbout() {    JOptionPane.showMessageDialog(this,              "Java Garage Hardcore\nWhoever 2004");   }   private void doNew() {   // Carry out the "New" command from the File menu   // by clearing all the text from the JTextArea.         textArea.setText("");   }  private void doSave() {     // Carry out the Save command by letting the user     // specify an output file and writing the text     // from the JTextArea to that file.          File file; // The file that the user wants                        to save.     JFileChooser fd; // File dialog that lets the                           //user specify the file.          fd = new JFileChooser(new File("."));          fd.setDialogTitle("Save As...");          int action = fd.showSaveDialog(this);          if (action != JFileChooser.APPROVE_OPTION) {                  //user cancelled, so quit the dialog                  return;          }          file = fd.getSelectedFile();          if (file.exists()) {                   //if file already exists, ask                   before replacing it                   action =                   JOptionPane.showConfirmDialog(this,                   "Replace existing file?");                   if (action !=                         JOptionPane.YES_OPTION)                         return;          }          try {             //Create a PrintWriter for writing to the             //specified file and write the text from             //the window to that stream.          PrintWriter out = new PrintWriter(new                         FileWriter(file));          String contents = textArea.getText();          out.print(contents);          if (out.checkError())               throw new IOException("Error while writing to file.");                   out.close();        }        catch (IOException e) {               // Some error has occurred while               trying to write.               // Show an error message.                    JOptionPane.showMessageDialog(this,                "IO Exception:\n" +                e.getMessage());        }    }     private void doOpen() {         //open the file the user selected by         //printing its contents to the text area         //will hold the user's file            File file;            //creates the complete dialog the user            //needs to select file            JFileChooser fd;            //use the current directory            //(specified as ".")            //as a starting place            fd = new JFileChooser(new File("."));            fd.setDialogTitle("Select a File...");            int action = fd.showOpenDialog(this);            if (action != JFileChooser.APPROVE_OPTION) {                     return;            }            //set the file to what the user selected            file = fd.getSelectedFile();            try {                  //reset the text area to be blank               textArea.setText("");                  //read in the selected file               BufferedReader in = new BufferedReader(new FileReader(file));               String lines = "";               int lineCt = 0;               String str;               while ((str = in.readLine()) != null) {                     lines += str + "\n";               }               textArea.setText(lines);               in.close();         } catch (Exception e) {               JOptionPane.showMessageDialog(this,               "Unable to open file:\n" + e.getMessage());                  }       }       private void doClose(){               Object[] options = { "OK", "CANCEL" };               int action =                    JOptionPane.showOptionDialog(null,                           "OK to close without                           saving?", "Closing",                           JOptionPane.DEFAULT_OPTION,                           JOptionPane.WARNING_MESSAGE,                           null, options, options[0]);               if (action == JOptionPane.OK_OPTION) {                     //reset the text area                     textArea.setText("");                     return;               } else {                     //do nothing and leave their                     file alone                     return;               }      }   /**    * Exit the application and stop the VM.    */   private void doExit() {         //store the current location of the window         //as a user preference so we can open it here         //next time         Preferences prefs =             Preferences.userNodeForPackage             (this.getClass());         prefs.putInt("WINDOW_X_LOCATION", getX());         prefs.putInt("WINDOW_Y_LOCATION", getY());         // stop the application         System.exit(0);    }      /**       * Allows you to easily switch logging locations.       * You could add a FILE case here too for moving       * into production.       * @param msg       * @param type       */      private void log(String msg, int type){          switch (type){          default : //fall through          case STDOUT:          System.out.println(">" + msg);          break;          case ALERT:          JOptionPane.showMessageDialog(this, msg);          break;          }      }    public static void main(String[] args) {       //start the application             new GarageEditor();    } } 

Results

We can enter some text, and then save the file just as you'd expect. Let's do that and then open it in a browser to prove that it works (see Figure 35.2).

Figure 35.2. Entering text into the editor is a breeze .
graphics/35fig02.gif

We also use the file chooser to browse to a local file (see Figure 35.3).

Figure 35.3. Using the JFileChooser.

graphics/35fig03.gif


If we open an existing file written in XML, such as the Eclipse project file, we see that the program honors the line breaks, tabs, and so forth that were already present in the file (see Figure 35.4).

Figure 35.4. The editor honors formatting.
graphics/35fig04.gif

If you choose to close an open document without saving, the app asks if you're sure you know what you're doing. If you choose OK, changes are not saved; if you choose Cancel, you are returned to the editor (see Figure 35.5).

Figure 35.5. The JOptionPane at work.
graphics/35fig05.gif

When you perform an action on the editor, you see the toolbar containing the File and Help menus. Choose a menu, and you see its items (see Figure 35.6).

Figure 35.6. The File menu and its items, including the mnemonics.

graphics/35fig06.gif




Java Garage
Java Garage
ISBN: 0321246233
EAN: 2147483647
Year: 2006
Pages: 228
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net