Mac Java tip: How to access Aqua file and folder icons

Technologies: Java 5+, Mac OS X 10.5+

File and folder icons are an important part of the look and feel of the Mac. These icons are available to Java applications through several different classes in Swing and sometimes as UI defaults for Apple's "Mac OS X" look and feel. This article shows to how to get at these icons using Java on a Mac.

Using the DefaultTreeCellRenderer to get folder tree icons

JTree's DefaultTreeCellRenderer uses icons for tree leaves, and for open and closed parent nodes. The icons are available by calling methods on an instance of the renderer:

DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer( );
 
Icon leafIcon   = renderer.getDefaultLeafIcon( );
Icon openIcon   = renderer.getDefaultOpenIcon( );
Icon closedIcon = renderer.getDefaultClosedIcon( );

The same icons are also available in the hash table of UI defaults for the "Mac OS X" look and feel:

UIDefaults defaults = UIManager.getDefaults( );
 
Icon leafIcon   = defaults.getIcon( "Tree.leafIcon" );
Icon openIcon   = defaults.getIcon( "Tree.openIcon" );
Icon closedIcon = defaults.getIcon( "Tree.closedIcon" );

The UI defaults also include icons for the open and close triangles shown by DefaultTreeCellRenderer next to parent node icons. These icons are not otherwise available through the Swing API. (See the article on All UI defaults names for common Java look and feels on Windows, Mac OS X, and Linux for more about UI defaults)

Icon collapsedIcon = defaults.getIcon( "Tree.collapsedIcon" );
Icon expandedIcon  = defaults.getIcon( "Tree.expandedIcon" );
Tree icons
Figure 1. Icons returned by a DefaultTreeCellRenderer instance (the first three)
or from its UI defaults (all five).

While these icons currently look like files and folders, that might not remain the case in future OS and Java upgrades. Semantically, these are tree leaf/open/closed icons, and not file and folder icons since a JTree can be used to organize any hierarchical data, not just files. They just happen to look like files and folders right now.

These icons are also dependent upon the current look and feel. If you change the look and feel from the default "Mac OS X" on a Mac to Sun's "Metal" or "CDE/Motif" look and feel, these icons will change. That can be awkward if your intent was to show your users Mac-style file and folder icons.

Advantages:

  • Uses the standard Java API
  • Uses UI defaults common to all look and feels

Disadvantages:

  • Semantically awkward to assume tree icons are files and folders
  • If not using the "Mac OS X" look and feel, the icons won't be Mac-like
  • Icons are all 16 x 16

Using the FileSystemView to get default file and folder icons

JFileChooser's FileSystemView includes includes methods to create new folders, return lists of files in a folder, and get the default icon for a file.

To get a FileSystemView instance, call the static getFileSystemView( ) method on FileSystemView. Call the view's getSystemIcon( ) with a File object to get the default icon for that file:

FileSystemView view = FileSystemView.getFileSystemView( );
 
Icon fileIcon = view.getSystemIcon( file );

For example, to get the icon for a folder, pass in a path to a folder, such as "/tmp". To get the icon for a document, pass in a path to a document, such as "/mach_kernel". The file must exist or the call will throw an exception.

Default file and folder icons
Figure 2. Default folder and file icons returned by a
FileSystemView instance.

Unfortunately, this method always returns the default icon for a file or folder. All folders get the Mac's generic blue folder icon, and all files get the page-with-folded-corner icon, no matter what their file type.

In principal, device icons are also available through FileSystemView if you query a File object for a device. In practice, file paths to devices (such as "/dev/disk0") don't get anything but the default document icon. Instead, use UI defaults for the "Mac OS X" look and feel:

UIDefaults defaults = UIManager.getDefaults( );
 
Icon computerIcon = defaults.getIcon( "FileView.computerIcon" );
Icon floppyIcon   = defaults.getIcon( "FileView.floppyDriveIcon" );
Icon diskIcon     = defaults.getIcon( "FileView.hardDriveIcon" );

Generic file and folder icons are also available:

Icon fileIcon   = defaults.getIcon( "FileView.fileIcon" );
Icon folderIcon = defaults.getIcon( "FileView.directoryIcon" );
FileView icons
Figure 3. Default device, folder, and file icons from FileView's UI defaults.

These UI defaults icons are again dependent upon the "Mac OS X" look and feel. If you use a different look and feel, you'll get different non-Mac-like icons.

Advantages:

  • Uses the standard Java API
  • Uses UI defaults common to all look and feels

Disadvantages:

  • Only generic default icons are available
  • If not using the "Mac OS X" look and feel, the icons won't be Mac-like
  • Icons are all 16 x 16

Using the JFileChooser to get Mac file and folder icons

JFileChooser creates a panel or dialog for selecting files to open and save. The chooser has two sets of icons: those that are sometimes used in the user interface for buttons, and those used in the file list for files and folders.

Icons used for buttons are not available through the Swing API. The current implementation of JFileChooser for the Mac doesn't even use them. However, these icons are available as UI defaults for the "Mac OS X" look and feel:

UIDefaults defaults = UIManager.getDefaults( );
 
Icon newFolderIcon  = defaults.getIcon( "FileChooser.newFolderIcon" );
Icon upFolderIcon   = defaults.getIcon( "FileChooser.upFolderIcon" );
Icon homeFolderIcon = defaults.getIcon( "FileChooser.homeFolderIcon" );
FileChooser icons
Figure 4. User interface icons from JFileChooser's UI defaults.

Semantically, these icons are for actions (new folder, go up, go home) and not for objects. They happen to look like folders, but in a future OS upgrade they might change to something else. For example, the "FileChooser.upFolderIcon" might become a folder with an up arrow. So, if you want folder icons, this isn't the way to go.

For file list icons, JFileChooser uses an internal FileView object for icons (and other information) about specific files and folders. Call getIcon( ) on the chooser to get the icon for a File:

JFileChooser chooser = new JFileChooser( );

Icon fileIcon = chooser.getIcon( file );

At last, this is the way to get the Mac's file and folder-specific icons:

FileChooser icons
Figure 5. Folder icons returned by a JFileChooser instance.
FileChooser icons
Figure 6. File icons returned by a JFileChooser instance.
FileChooser icons
Figure 7. Application icons returned by a JFileChooser instance.

To get an icon, you need a File object with a path to that file. This means you have to hardcode paths, like "/Applications/Address Book.app" to get an application's icon. And, of course, the application has to be there.

Embedding file paths to specific folders, like "/Applications", is discouraged by Apple since the locations of those folders might change in a future OS upgrade. Instead, Apple provides a mechanism for referring to special folders by reference, instead of by path. For instance, to get the path to "/Applications", use:

String appPath = com.apple.eio.FileManager.findFolder(
    com.apple.eio.FileManager.kSystemDomain,
    com.apple.eio.FileManager.OSTypeToInt( "apps" ) );

This uses Apple's FileManager extension class for Java. It's available on any Mac after Mac OS X 10.5, but only on Macs. So, if you use it your Java code will only compile and run on a Mac. It's also a fairly awkward class that requires that you understand Apple's Objective C FSFindFolder class.

Advantages:

  • Uses the standard Java API
  • Gets Mac icons on a Mac, regardless of the look and feel
  • Gets icons for specific types of files and folders

Disadvantages:

  • Requires file system access, which may not be allowed in an Applet
  • Requires that you know the paths to files, folders, and applications
  • A file of a specific type must exist to get the icon for that type
  • Icons are all 16 x 16

Using "NSImage" to get special file, folder, and application icons

Apple's implementation of the JDK includes a back door to get standard icons available in the underlying AppKit framework for Objective C. I've discussed these before in the article Mac Java tip: How to access Mac-specific "NSImage" icons.

A few of these icons are relevant here. To get a standard icon, get the default AWT Toolkit and call its getImage( ) method. Pass a pseudo-URL "NSImage://" followed by the name of an icon. The "NSComputer" icon gives you a generic computer icon. "NSFolderBurnable" is a CD-burn folder, "NSFolderSmart" is a smart list folder, "NSApplicationIcon" is a generic application icon, and "NSMysteryDocument" is a generic document icon.

Toolkit toolkit = Toolkit.getDefaultToolkit( );
 
Icon computerIcon    = new ImageIcon( toolkit.getImage( "NSImage://NSComputer" ) );
Icon burnFolderIcon  = new ImageIcon( toolkit.getImage( "NSImage://NSFolderBurnable" ) );
Icon smartFolderIcon = new ImageIcon( toolkit.getImage( "NSImage://NSFolderSmart" ) );
Icon appIcon         = new ImageIcon( toolkit.getImage( "NSImage://NSApplicationIcon" ) );
Icon fileIcon        = new ImageIcon( toolkit.getImage( "NSImage://NSMysteryDocument" ) );
FileChooser icons
Figure 8. Standard NSImage file and folder icons.

Advantages:

  • Icons are 128 x 128
  • Gets a generic application icon

Disadvantages:

  • Only a few generic icons are available
  • Requires "NSImage" backdoor that only works on a Mac

Using Sun's ShellFolder to get larger icons (not)

The web has multiple articles about using Sun's undocumented internal ShellFolder class to get larger versions of file icons. The code goes like this:

sun.awt.shell.ShellFolder sf = sun.awt.shell.ShellFolder.getShellFolder( file );
Image image = sf.getIcon( true );

This won't work on a Mac. Sun's ShellFolder class is a support class for the default implementation of JFileChooser. Windows, Linux, and Solaris JDKs are written by Sun and use this class. Apple's JDK is ported by Apple and uses different support classes for JFileChooser. While ShellFolder does exist in the Apple JDK, it does nothing. The getIcon( ) method always returns a null.

Getting large file and folder icons on a Mac

At this time, there is no public API for getting larger file and folder icons from Java on a Mac.

Further reading

Related articles at NadeauSoftware.com

Web articles and specifications

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options

Nadeau software consulting
Nadeau software consulting