Step 3


Overview

In this step you will add the capability of reading text from a file into the application's text area. In the FileViewPane class, this involves adding a readText() method. It has a File parameter to specify the source.

In the FileViewer class, you will add a openFile()() method. This method uses a JFileChooser dialog to get a file selected by the user, then sends a readText() message to the file view pane.

In the FileViewer class, you will also create an action object for opening a file. This object will be used to create an "Open..." menu item in the "File" menu. Its actionPerformed() method just invokes the openFile() method.

The code that you will add in this step is used as follows. When a user selects the "Open..." menu item, a dialog for selecting a file pops up. After the user selects a file, it is used as the parameter in a openFile() message. In openFile(), the file is forwarded to the file view pane in a readText() message. The readText() method puts the contents of the selected file into the text area.

Reading Text into a FileViewPane

The "Open..." action is supported in the FileViewPane class with the readText() method. This method has void return type and a parameter of type File. It should be declared public since it is invoked from a different class.

Its first statement of the method should send a setText() message to the textArea instance variable with an empty string ("") as a parameter. This clears the text area.

The rest of the code is a try-catch statement. In its try clause, you should first create a FileReader local variable. It should be initialized by invoking the FileReader constructor, with the readText() parameter forwarded as the constructor parameter. Then create a LineNumberReader variable that is initialized by invoking the LineNumberReader constructor with the FileReader variable as a parameter. This is the variable that you will use for all further file operations.

Continuing in the try clause, define a String local variable that is initialized by sending a readLine() message to the line number reader. This puts the first line of text from the file into the String variable. Then write a while loop to append lines from the file onto the text in the text area.

The loop should continue while the String variable is not null. Its first statement should send an append() message to the textArea instance variable. The parameter for this message should be the String variable. The second statement should be another append() message, this time with a new line ("\n") as a parameter. Finally, you should use readLine() to get the next line from the file into the String variable.

After the loop, you should send a close() message to the line number reader. There are no parameters for this message.

For the catch clause of the try-catch statement, you can pop up an error message dialog with the following.

    try {
	// code described above
    } catch(IOException e) {
	JOptionPane.showMessageDialog(null, e.getMessage(),
		"File Error", JOptionPane.ERROR_MESSAGE);
    }
The first parameter in the showMessageDialog() message is supposed to specify the top-level window that the dialog should be used in, but a null value can be used when the top-level window is not known. The second parameter specifies the message that appears in the dialog. Here, the message from the exception is used. The third parameter specifies the title in the dialog window. The fourth specifies the type of message dialog. The ERROR_MESSAGE should normally be used when you are catching exceptions.

When you have completed the changes, recompile the FileViewPane class to check for syntax errors. The remaining changes are all in the FileViewer class.

Opening a File with a JFileChooser

A JFileChooser is useful as a dialog for user selection of files. If you need one, the best practice is to declare it as an instance variable rather than a local variable that is created when needed. This allows data to be retained about the directory from which the user is selecting files. So you should define an instance variable named fileChooser of type JFileChooser. It should be initialized by invoking the JFileChooser constructor with no parameters.

You should add the following statements to the FileViewer constructor near the top of the constructor (the location is not critical).

    String cwd = System.getProperty("user.dir");
    fileChooser.setCurrentDirectory(new File(cwd));
These statements specify the directory whose contents are initially displayed by the file chooser. In this case, the user's current working directory is used.

Finally, add the following method to the FileViewer class.

    public void openFile() {
	int status = fileChooser.showOpenDialog(this);
	if (status == JFileChooser.APPROVE_OPTION) {
	    File file = fileChooser.getSelectedFile();
	    viewPane.readText(file);
	}
    }
When using a JFileChooser, you always check its status because the user could cancel the operation. When the user clicks on the "OK" button of the chooser, this code obtains the file from the chooser an sends it to the file view pane to be read.

An Action Object for Opening a File

The last thing that you need to do in the FileViewer class is to create an action for opening a file and add it to the "File" menu. This is similar to the "Exit" action in Step 2. The name of the action variable should be openAction. Its actionPerformed() method should invoke openFile(). The name given to the action should be "Open...".

When you have made the above changes, recompile the FileViewer class and run it with the following UNIX command.

    java FileViewer
When you open the "File" menu, you should see the new "Open..." menu item. Click on it and select one of your .java files with the file chooser. Its text should appear in the text area. If it does, congratulations are in order. You are now ready for Step 4, and you have gotten through the hardest part of this programming assignment.