WebNFS Developer's Guide

Chapter 5 XFileChooser

Introduction

A file chooser is a standalone graphical component for selecting files. Typically, it's brought up when the user chooses Open or Save from a menu or presses an Open or Save button. A typical file chooser is shown in Figure 5-1.

Figure 5-1 The Default XFileChooser

Graphic

The Java Swing package provides a file chooser by means of the JFileChooser class. Although JFileChooser is typically used to allow a user to open or save files, an application may perform a customized action with the selected files instead. The JFileChooser does not itself perform any action on any file, including opening or saving; instead, it only provides the user with a window for selecting files to be worked with. For each file the user selects, JFileChooser returns a File object to the calling application, which can then perform the usual file operations on it.


Note -

For more on JFileChooser, see the javadocs for the JFileChooser and the section How to Use File Choosers in the Java Tutorial.


JFileChooser, however, is limited to local filesystems. To allow an application to select files on distributed filesystems such as NFS, another file chooser class is required: XFileChooser.

The XFileChooser class extends the JFileChooser class; however, it utilizes the Extended File Application Programming Interface (the XFile API, for short) for its file operations instead of java.File. Specifically, it uses XFile objects in place of the File objects used by JFileChooser. Since XFile objects include files distributed on NFS networks, an XFileChooser can access exported files anywhere on an NFS network. So, while JFileChooser allows you to select files on your own local (or "native") system, for example:



/home/marlowe/plays

XFileChooser can access not only a local file but any exported filesystem on an NFS server, using the syntax specified by the NFS classes used by the Extended File API:



nfs://playstation/export/shakespeare/sonnets


Note -

Although the XFile API theoretically provides access to other kinds of distributed filesystems, including HTTP and CIFS, currently only NFS access is implemented (along with native access).


Because XFileChooser is an extension of JFileChooser, it inherits the public methods and variables of that class. An application uses XFileChooser in virtually the same way it uses JFileChooser; in most cases "porting" an application that uses JFileChooser to using XFileChooser requires only changing the names of methods (for example, from getSelectedFile() to getSelectedXFile()) and replacing File objects with XFile objects. In many cases this may be only a few minutes' work.

XFileChooser is a Bean

XFileChooser is a Java BeanTM. This means that

Figure 5-2 The XFileChooser Bean Icon

Graphic

Here's what the XFileChooserBean looks like when loaded into BeanBox. Note that the Bean suppors a property sheet that allows users to customize the Bean:

Figure 5-3 The XFileChooser Bean in the BeanBox Editor

Graphic

Properties that can be modified from the property sheet include: the dialogue type; the dialogue title; the file-selection mode; hidden-file display; text for the "approve" button; mnemonic for the "approve" action; tooltip; look-and-feel; and current directory. See "Properties" for a list of XFileChooser's properties.

Architecture

XFileChooser inherits from JFileChooser in the following way:

Figure 5-4 The XFileChooser Class Hierarchy

Graphic

The relationship between XFileChooser, JFileChooser, and the Extended File API is shown in Figure 5-5:

Figure 5-5 XFileChooser, JFileChooser, and XFile

Graphic

Requirements

The following are required to use the XFileChooser Bean:

Basic Requirements

You must have the Extended File API (from the WebNFS SDK 1.2).

To make use of the entire WebNFS 1.2 FCS release, you must have JDK 1.2 or later installed on your system. Therefore we recommend you install JDK 1.2 if you have not already. It may be found at http://www.java.sun.com/products/index.html.

If you are using JDK 1.1.6, you must also have the Swing 1.1 set (available at http://java.sun.com/products/jfc/index.html#download-swing) in order to use the XFileChooser. You can use the other WebNFS components without Swing 1.1.

Events

An file chooser can notify other Beans of changes. Changes can be of two types:

Action Events

XFileChooser has two actions for which other Beans can register to listen with addActionListener(): CANCEL_SELECTION, if the Cancel button is pushed, and APPROVE_SELECTION, if the Open or Save (or custom) button is pushed.

Rather than listen for events on these buttons, however, an application can simply bring up a file chooser and then check its return status using one of XFileChooser's properties:


Xfilechooser xfc = new XFileChooser;
retval = xfc.show{Open,Save}Dialog(this);
if (retval == xfc.APPROVE_OPTION)
     // open  or save or whatever ...

Properties

Other Beans can listen to events in the file chooser by using the addPropertyChangeListener() method.


public MyListener(XFileChooser xfc) {
     xfc.addPropertyChangeListener(this);
     new PropertyChangeEvent e;
     if e.getPropertyName() == xfc.SELECTED_XFILE_PROPERTY_CHANGED {
          do_something();
...

Most of the properties in XFileChooser are inherited from JFileChooser, so you should refer to thejavadocs of the JFileChooser for a complete list of JFileChooser fields. Properties that can be changed through the XFileChooser Bean's property sheet (in a Bean-aware editor) are listed in "XFileChooser is a Bean".

XFileChooser does have three variables unique to itself, however:

Classes

As mentioned earlier, XFileChooser inherits from JFileChooser; check the javadocs of the JFileChooser for a list of the methods and fields in that class.

The following is a list of the methods unique to XFileChooser. For a list of variables, see "Properties".

See also the XFileChooser javadocs.

Constructors

In addition to creating the file chooser and pointing it to an initial directory, these constructors initialize some of the variables needed for using a Bean editor.

Other Methods

Customizing the File Chooser

A file chooser can be customized in a number of ways. (Several of these modifications are shown in Figure 5-7.) Most of the modifications are of the sort that one normally sees with GUI components, such as changing the string in the file chooser's title bar or setting button mnemonics. Certain customizations are more specific to the file chooser, however, and deserve special mention.

Performing a Unique Action

Although the most common use for a file chooser is to open or save files, XFileChooser allows you to select a file for any other action you specify. To this end, a "generic" method for bringing up a file chooser window, showDialog(), is provided in addition to showOpenDialog() and showSaveDialog(). (Since the file chooser itself doesn't affect files, the only difference between a custom dialog and the others is the title on the dialog window and the label on the "accept" button.)

File Filtering

As with the JFileChooser, three types of file filtering are available to the application in bringing up a file chooser:

Setting the FileView

The FileView is the way each file is shown in the file chooser's list of files. By default a small icon and the file's name appear; this can be customized, for example, to show a unique icon next to each filename. An example of this is shown in "Modifying the FileView".

Setting the Accessory

An accessory is a component that is invoked in the file chooser when a file is selected. One example of an accessory might be a panel with controls in it. Another might be a small preview area in the file chooser that displays a thumbnail of a selected graphic file. An example of this kind of customization is given in "Setting the Accessory".

Sample Programs

Two sample programs that make use of XFileChooser are included with this release:

The DemoEditor Sample Program

The DemoEditor program allows a user to open a text file and perform simple edits on it (Cut, Paste, etc.). The file can then be saved to another name.

Figure 5-6 The DemoEditor Program

Graphic

As part of the initialization of the application,

  1. menu items are created for opening, closing, and saving a file, and for exiting;

  2. listeners are added to the menu items;

  3. the menu items are attached to the File menu.

For brevity's sake, only the code for opening files is shown below:


JMenu filemenu = new JMenu("File");
openItem = new JMenuItem("Open");
openItem.addActionListener(this);
fileMenu.add(openItem);

If an item on the File menu is selected, an actionEvent is fired off which causes the actionPerformed() method to be called. actionPerformed() checks the type of menu item selected and acts accordingly: it creates an XFileChooser object, and, if Open or Save is selected from the menu, brings up a file chooser.


public void actionPerformed(ActionEvent ae) {
   int retval;
   XFileChooser chooser = new XFileChooser();
   if (ae.getSource == closeItem)
     closeDocument();
   } else if (ae.getSource() == openItem) {
      retval = chooser.showOpenDialog(this);
      if (retval == XFileChooser.APPROVE_OPTION) {
        XFile theFile = chooser.getSelectedXFile();
   // make sure we're not already editing a file!
        closeDocument(); 
        if (theFile != null)
          readFromFile(theFile);
     }
   } else if (ae.getSource() == saveItem) {
     retval = chooser.showSaveDialog(this);
     if (retval == XFileChooser.APPROVE_OPTION) {
        XFile theFile = chooser.getSelectedXFile();
        if (theFile != null)
          writeToFile(theFile);
        }
   } else if (ae.getSource() == exitItem) {
     System.exit(0);
   }
}

Some things to note about the foregoing:

The XFileChooserDemo Sample Program

The XFileChooserDemo program is a mock application designed to show the different ways an XFileChooser can be customized.


Note -

Since this program is just a modification of the sample program FileChooserDemo2 shown in the Java Tutorial, much of the description has been left out. Please see How To Use File Choosers for a description of that program.


Figure 5-7 The XFileChooserDemo Sample Program

Graphic

When the settings are as shown in Figure 5-7, a default file chooser (shown in Figure 5-1), will pop up when the Show File Chooser button is pressed.

This sample program differs from DemoEditor in several aspects:

First, the file chooser that comes up has been customized in three different ways:

(See "Customizing the File Chooser" for information on other ways a file chooser may be customized.)

The second way that this program differs from DemoEditor is that the file chooser is invoked not from a menu but from a single button, the Show File Chooser button. Which kind of file chooser is brought up -- Open, Save, or a custom operation -- depends upon the settings in the main window.

Finally, unlike DemoEditor, the look-and-feel of this sample program is changeable by the user. The file chooser inherits the look-and-feel of its parent application.

Determining Which File Chooser to Bring Up

The DemoEditor program had separate menu items for opening and saving a file, so that a different file chooser would appear, depending on the item selected. (Remember, however, that the same XFileChooser object is instantiated in both cases.) Things are different with the XFileChooserDemo program: There's a single button, Show File Chooser, and which dialogue this button brings up depends on which radio button (Open, Save, or Custom) in the main window has been selected. The code for using the Open button is shown below.


// Create an `Open' radio button
openButton = new JRadioButton("Open")
...
openButton.addActionListener(optionListener);
// Create `Show File Chooser' button
button = new JButton("Show File Chooser");
button.addActionListener(this);

When a radio button is selected, OptionListener() is called. If the Open radio button is selected, the OptionListener() sets the file chooser to be an Open file chooser with the setDialogType() method:


class OptionListener implements ActionListener {
   public void actionPerformed(ActionEvent e) {
     JComponent c = (JComponent) e.getSource();
     if (c == openButton) {
        chooser.setDialogType(XFileChooser.OPEN_DIALOG);
...

OptionListener() does the same sort of thing when Save is chosen, except that the dialogue type is set to SAVE_DIALOG. Note, by the way, that setDialogType() and the OPEN_DIALOG field are inherited from JFileChooser.

In the DemoEditor program, the actionPerformed() method chose between bringing up a file chooser with showOpenDialog() or showSaveDialog(), depending on whether Open or Save was selected off the File menu. Since the dialog type is already set here, it is not necessary to differentiate between them in actionPerformed(). Instead, a "generic" method, showDialog(), is used to bring up the file chooser:


public void actionPerformed(ActionEvent e) {
   int retval = chooser.showDialog(frame, null);
...

Another difference to note is that the XFileChooser is not instantiated in actionPerformed(), as it was in the DemoEditor program. Instead, it's instantiated at the class level so that the dialog type can be set in OptionListener(). In both programs, however, a single file chooser is instantiated for all operations (Open, Save, or custom).

Filtering Files

As mentioned in "Customizing the File Chooser", three different file filters can be applied to a file chooser. In this program, a filter chosen by the user is enabled. If the Add JPEG and GIF Filters radio button is selected, the resulting file chooser presents the user with several filters to choose from, as shown in Figure 5-8:

Figure 5-8 Filtering Files

Graphic

The file filters used by XFileChooserDemo are described in the class ExampleFileFilter, found in ExampleFileFilter.java (shown in "ExampleFileFilter"). ExampleFileFilter takes two arguments: a file extension (for example, .jpg) and a description of the file, and filters files appropriately.

Here is where XFileChooserDemo instantiates the various filters:


jpegFilter = new ExampleFileFilter("jpg", "JPEG
Compressed Image Files");
gifFilter = new ExampleFileFilter("gif", "GIF
Image Files");
bothFilter = new ExampleFileFilter(new String[] ""jpg", "gif"}, "JPEG
and GIF Image Files");

The program's OptionListener() checks to see if the radio buttons governing filters have been changed. If the user has selected the Add JPEG and GIFs button, OptionListener() adds the various filters provided by ExampleFileFilter, using the addChoosableFileFilter() method inherited from JFileChooser:


class OptionListener implements ActionListener {
   public void actionPerformed(ActionEvent e) {
      JComponent c = (JComponent) (e.getsource();
...
        else if (c == addFiltersButton) {
           chooser.addChoosableFileFilter(bothFilter);
              chooser.addChoosableFileFilter(jpgFilter);
           chooser.addChoosableFileFilter(gifFilter);
        }

(The program could have used finer control in determining which filters to add to the file chooser, but the approach used here minimizes the number of radio buttons cluttering the main window.)

When the user chooses a new filter in the file chooser, a CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY is fired off, and the panel displaying the list of files gets updated accordingly, to show only the filtered files.

Modifying the FileView

The FileView is the way a file in a list is presented. By default, a file chooser shows each file with a small icon showing whether the file is a directory of a flat file. An example of a modified FileView is seen in Figure 5-8; compare the icon shown next to the file shakes2.gif to the icon that appears in next to it in Figure 5-1.

Setting the FileView works in the same way as filtering files does. Here's how it's done in XFileChooserDemo:

  1. Create a custom subclass of the class FileViewapi, overriding any of its abstract methods you need. For this sample program, one has been created called ExampleFileView (see "ExampleFileView"), which looks at a file's extension (for example,.jpg) and returns the file's name and, if the extension indicates that the file is a graphic file, an icon representing that type of file.

  2. Create a FileView object.


    fileView = new ExampleFileView();

  3. Add a checkbox for changing the FileView, and add a listener to it.


    useFileViewButton = new JCheckbox("Use FileView");
    useFileViewButton.addActionListener(optionListener);

  4. In optionListener(), call setFileView() when the Use FileView checkbox gets selected.


    if (c == useFileViewButton) {
         if (useFileViewButton.isSelected() {
              chooser.setFileView(fileView);
         else
                    chooser.setFileView(null);
    

Now when a file chooser is brought up ExampleFileView will be used to display the files in the file list.

Setting the Accessory

The XFileChooserDemo's accessory component is a small panel on the right side of the file chooser that displays a preview of GIF and JPEG graphics files. In Figure 5-9 it's the picture of William Shakespeare:

Figure 5-9 The XFileChooserDemo's Accessory

Graphic

Another use for an accessory is a panel with more controls in it (say, checkboxes to toggle certain features).

Two aspects of accessories are important:

The XFileChooserDemo program begins by creating the file chooser; the accessory (here called the previewer), which is declared to be a FilePreviewer object; and a related checkbox. It adds a listener (ActionListener) to the checkbox, as we've seen with the file view and file filtering:


chooser = new XFileChooser;
...
previewer = new FilePreviewer(chooser);
...
accessoryButton = new JCheckBox("Show Preview");
accessoryButton.addActionListener(optionListener);

The OptionListener() checks to see if the Show Preview checkbox is checked; if it is, it calls setAccessory():


if (c == accessoryButton) {
     if (AccessoryButton.isSelected()) {
          chooser.setAccessory(previewer);
     else
          chooser.setAccessory(null);

The previewer itself just sets its preferred size and adds a PropertyChangeListener() that listens for changes to the file chooser's state.

This is its only method, its constructor:


public FilePreviewr(XFileChooser fc) {
     setPreferredSize(new Dimension(100, 50));
     fc.addPropertyChangeListener(this);

If a property is changed, addPropertyChangeListener() calls the abstract method PropertyChange(). Here's how PropertyChange() defined for the XFileChooserDemo program. It first checks to see what property has changed; if a new file has been selected, then a new preview is required.


public void propertyChange(PropertyChangeEvent e) {
     String prop = e.getPropertyName();
     if (prop.equals(XFileChooser.SELECTED_XFILE_CHANGED_PROPERTY)) {
          f = (File) e.getNewValue()
          if (isShowing()) {
               loadImage();
               repaint();
          }
     }
}