# FileIcon Demo

## What Is It

The `FileIcon` is an abstract class creates a `javax.swing.Icon` for a `File`.

A file icon is a small (usually about 16x16) icon you can place next to a file name. Usually all files with the same file extension share the same file icon.

An "icon" is different from a "thumbnail". (A thumbnail is an image that is a rendering of a specific file.) And sometimes the word "preview" also carries special implications of interactivity (for ex: a video). So "icon", "thumbnail" and "preview" are all separate buzzwords.

## How To Use It

The simplest one-line invocation resembles:

    Icon icon = FileIcon.get().getIcon(file);

## How It Works

Each subclass is responsible for deciding how to identify the appropriate icon. And the `FileIcon` class has a static getter/setter method for maintaining the active default `FileIcon` on a given system.

## Discussion

### Implementations

There are currently 2 subclasses of `FileIcon`. (There used to a 3rd that involved reflection, but in accordance with Java guidelines I'm trying to phase out reflection.)

#### Implementation #1: FileSystemViewFileIcon

This implementation uses `FileSystemView`, and it resembles:

    public class FileSystemViewFileIcon extends FileIcon {
    	@Override
    	public Icon getIcon(File file) {
    		FileSystemView fsv = FileSystemView.getFileSystemView();
    		Icon icon = fsv.getSystemIcon(file);
    		if (icon != null)
    			return icon;
    		return super.getDefaultIcon(file);
    	}
    }

This looks like it should be the ideal way to go, because it's so clean/direct. But on Mac it only ever returns a generic file or folder icon. I tried rummaging through the source code for `FileSystemView` (and related classes) to see if I could modify (hack) it without reflection, but there aren't a lot of entry points.

#### Implementation #2: FileViewFileIcon

This implementation uses a `JFileChooser's` `FileView`, and it resembles:

    public class FileViewFileIcon extends FileIcon {
    	FileView fileView;
    	public FileViewFileIcon() {
    		JFileChooser chooser = new JFileChooser();
    		fileView = chooser.getUI().getFileView(chooser);
    	}

    	@Override
    	public Icon getIcon(File file) {
    		return fileView.getIcon(file);
    	}
    }

I don't like that this is so indirect and clunky. Sometimes creating a `JFileChooser` is not trivially cheap, either. But on Mac: this works great. It returns scalable icons for most every file type.

On Windows: both this approach and the `FileSystemView` approach produce unscaleable (kind of crappy/pixelated) 16x16 icons. But today as I wrote this I saw emails trickle in about a pull request to update this in future Java versions, so that's exciting.

### Scaling

This demo includes an option to scale the icon.

On Mac the icons we get back are high-resolution, so they can scale to most any size with great clarity.

On Windows the icons are not (yet) high-resolution. (Although in a future Java release that should change.) So if you want a universal cross-platform approach: you ought to just stick with the icon's default size. (And even that, unfortunately, will look pixelated on a high-resolution monitor on Windows.)