CPSC 225, Spring 2012
Lab 9b: Not PowerPoint, Part 2

This is the second part of a two-part lab that was begin in Lab 9a last week. The complete solution to both parts of the lab is due next week, on Friday, April 6. Copy your project into your homework folder, as usual.

Files

The assignment for this part of the lab is simple to state: You should add support for files to the "Not PowerPoint" program.

You should begin by adding three new commands to the "File" menu: "New", "Open...", and "Save...". (Note that "..." in a command name is a signal to the user to expect a dialog to be popped up when the user selects that command.) As before, you will implement these commands by calling methods in the SlidePanel class.

The "New" command will discard all the slide data currently in the program and will start from the beginning, with one blank slide.

The "Save..." command should should pop up a file dialog to let the user specify where the file will be saved. All the data for the current list of slides should be written to the selected file.

The "Open..." command, similarly, should use a file dialog to let the user select the file to be opened. The program should try to read data for a list of slides from the file. If it is successful, then the data that it has read should replace the current list of slides.

A major part of the assignment is to create a file format for the data that you want to save. You should use a text-based data format. The details are up to you, but you should make sure that your program is able to read the data that you write. We will discuss this in class. Outlines for the "save" and "open" methods that you need to write are given below.

If you want to do something a little extra for this program, you can think about protecting the user against accidentally losing work that they have done on their slideshows. In many programs, when the user chooses "New", "Open", or "Quit", the program will check whether there are unsaved changes in the data. If so, the program will ask the user to confirm that they really want to lose those changes. To implement this, add a boolean variable named dirty to SlidePanel. The value of dirty should initially be false. Any time you make any change at all to the data in the program, you should also set dirty to true. In the implementations of "New", "Open", and "Quit", you should check the value of dirty. If it is true, ask whether the user wants to lose the changes they have made, before continuing with the command. Note that dirty should be reset to false at the end of the "New" and "Open" commands.

Open and Save Methods

For the file dialogs, you will use a JFileChooser, as discussed in Section 11.2.3. The methods that you need to write to implement the Open and Save commands will follow the general pattern discussed in that section. Here are outlines for typical doOpen and doSave commands, using a global instance variable named fileDialog to represent the JFileChooser:

public void doOpen() {
   if (fileDialog == null)
      fileDialog = new JFileChooser();
   fileDialog.setDialogTitle("Select File to be Opened");
   fileDialog.setSelectedFile(null);  // No file is initially selected.
   int option = fileDialog.showOpenDialog(this);
   if (option != JFileChooser.APPROVE_OPTION)
      return;  // User canceled or clicked the dialog's close box.
   File selectedFile = fileDialog.getSelectedFile();
   Scanner in;  // a scanner for reading text from the file
   try {
      in = new Scanner( selectedFile );
   }
   catch (Exception e) {
      JOptionPane.showMessageDialog(this,
            "Sorry, but an error occurred while trying to open the file:\n" + e);
      return;
   }
   try {
      // ...
      // ...   (Read data from the file.)
      // ...
   }
   catch (Exception e) {
      JOptionPane.showMessageDialog(this,
            "Sorry, but an error occurred while trying to read from the file:\n" + e);
   }   
}


private void doSave() {
   if (fileDialog == null)      
      fileDialog = new JFileChooser(); 
   fileDialog.setSelectedFile(null); // Initially no file is selected. 
   File selectedFile;  //Initially selected file name in the dialog.
   fileDialog.setDialogTitle("Select File to be Saved");
   int option = fileDialog.showSaveDialog(this);
   if (option != JFileChooser.APPROVE_OPTION)
      return;  // User canceled or clicked the dialog's close box.
   selectedFile = fileDialog.getSelectedFile();
   if (selectedFile.exists()) {  // Ask the user whether to replace the file.
      int response = JOptionPane.showConfirmDialog( this,
            "The file \"" + selectedFile.getName()
            + "\" already exists.\nDo you want to replace it?", 
            "Confirm Save",
            JOptionPane.YES_NO_OPTION, 
            JOptionPane.WARNING_MESSAGE );
      if (response != JOptionPane.YES_OPTION)
         return;  // User does not want to replace the file.
   }
   PrintWriter out;  // For writing data to the file.
   try {
      out = new PrintWriter( selectedFile );
   }
   catch (Exception e) {
      JOptionPane.showMessageDialog(this,
         "Sorry, but an error occurred while trying to open the file:\n" + e);
      return;
   }
   try {
       // ...
       // ... (Write data to the file.)
       // ...
       out.flush();  // Make sure data is actually sent to the file!
       out.close();
       if (out.checkError())
          throw new Exception("Error in PrintWriter");
   }
   catch (Exception e) {
      JOptionPane.showMessageDialog(this,
         "Sorry, but an error occurred while trying to write to the file:\n" + e);
   }   
}

Now, what you need to do is decide how to write a complete description of the current set of slides in the doSave method, and how to read that data and fully reconstruct the slides in the doOpen method.