Display Shortcuts in the JFileChooser





Display Shortcuts in the JFileChooser

This hack will customize the JFileChooser to recognize shortcut (linked) folders and overlay them with a link graphic, mimicking the native Windows File Explorer.

Another of JFileChooser's glaring bugs is the lack of any support for linked directories. This is hardly surprising, as Java itself has no understanding of linked directories. Most operating systems support linked files, however, and often indicate to the user that a file is linkedfor example, by drawing an arrow overlaid on top of the folder or directory icon. Compare the typical JFileChooser in Figure to the standard Windows file chooser in Figure. There's more than a small difference! No wonder it's hard to get folks to move to Swing.

Normal JFileChooser


Like every Swing component, the look of the JFileChooser is controlled by the installed Look and Feel (L&F). However, the JFileChooser also uses a custom class similar to a table cell renderer for drawing the actual files and folders. That class, FileView, is the best place to start hacking the JFileChooser's display.

The FileView contains five methods that determine the names, icons, and other attributes that are actually displayed in a JFileChooser. By overriding these methods, you can change the look or text of any file. To draw shortcuts as linked folders, you just need to override the getIcon() and isTRaversable() methods. getIcon() returns the icon to use when drawing the file.

Standard Windows file chooser


isTraversable() tells the file chooser if a given file is a directory type of object, meaning the user can click and open it to list new files. These two methods will transform a shortcut.lnk file into a shortcut directory with the right icon.

For the sake of brevity, this is a Windows-specific hack. You should be able to modify this hack easily to work with sym-links on Unix and Linux, as well as Mac OS X. Consider it homework!


To get started, create the ShortcutFileView class. This extends FileView, overriding the isTraversable() method to return true if the isDirLink() method indicates that the file is indeed a link (determined by looking for the .lnk extension). If the file is not a link, isDirLink() will return null.

Notice that isTraversable() returns a Boolean instead of a boolean. This allows a null to be returned in addition to the true/false values that boolean would allow.


Any method of FileView subclasses that return null will cause the file chooser to defer to its default file view, instead of using the custom view:

	class ShortcutFileView extends FileView {

		public boolean isDirLink(File f) {         
		if(f.getName().toLowerCase().endsWith(".lnk")) {
			return true;
		}
		return false;
	}
	public Boolean isTraversable(File f) {
		if(isDirLink(f)) {
			return new Boolean(true);
		}
		return null;
	 }
  }

Below is a sample program to test the ShortcutFileView. It creates a new file chooser, sets the file view to a new ShortcutFileView, and then opens the dialog. It is important to set the view before the showOpenDialog() because file choosers cannot be changed after they have been shown on screen:

	public class DisplayShortcutTest {
		public static void main(String[] args) throws Exception {
			JFileChooser chooser = new JFileChooser();
			chooser.setFileView(new ShortcutFileView());
			chooser.showOpenDialog(null);
		}
	}

This program changes the look of shortcuts to look like folders and be clickable, but they still don't have the link icon. This will require a bit more work. The second method to override in the file view is the getIcon() method. The plan is to get a standard folder icon then draw it onto a new icon with the overlaid link graphic. This part will create a new JFileChooser and get a reference to its normal file view. The following FileChooserUI code forces the file chooser to initialize its Look and Feel subsystem, ensuring that the FileView will be valid:

	public Icon getIcon(File f) {
		if(isDirLink(f)) {

			JFileChooser chooser = new JFileChooser();
			FileChooserUI fcui = (FileChooserUI) UIManager.getUI(chooser);
			fcui.installUI(chooser);
			FileView def = fcui.getFileView(chooser);

Once you have the file view, you need to pull out a folder icon. You can do this by asking for the icon of a known folder, in this case C:\windows:

	// get the standard icon for a folder
	File tmp = new File("C:\\windows");
	Icon folder = def.getIcon(tmp);
	int w = folder.getIconWidth();
	int h = folder.getIconHeight();

Once you have the icon, you can build a new image to draw it on, and then overlay the link graphic:

	// create a buffered image the same size as the icon 
	Image img = new BufferedImage(w,h,
				BufferedImage.TYPE_4BYTE_ABGR); 
    Graphics g = img.getGraphics();
	
	// draw the normal icon
	folder.paintIcon(chooser,g,0,0);

	// draw the shortcut image on top of the icon        
	Image shortcut = new ImageIcon("shortcut.png").getImage(); 
	g.drawImage(shortcut,0,0,null);

	// clean up and return
	g.dispose();
	return new ImageIcon(img);
   }
   return super.getIcon(f);
 }

That's it. With the new icon created, your file chooser should look like Figure.

JFileChooser showing a shortcut



     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows