package org.limewire.ui.swing.util; import java.awt.Component; import java.awt.Graphics; import java.io.File; import javax.swing.Icon; import javax.swing.SwingUtilities; import org.limewire.concurrent.ThreadExecutor; import org.limewire.core.api.library.PropertiableFile; import org.limewire.util.FileUtils; import org.limewire.util.OSUtils; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; /** * Manages finding native icons for files and file types. */ @Singleton public class IconManager { /** The original basic file icon controller. **/ private final FileIconController originalFileController; /** The current FileIconController. */ private FileIconController fileController; private Icon blankIcon; @Inject IconManager(NonBlockFileIconController nonBlockFileIconController, final Provider<NativeFileIconController> nativeFileIconControllerFactory) { // Always begin with the basic controller, // whose construction can never block. this.originalFileController = nonBlockFileIconController; fileController = this.originalFileController; // Then, in a new thread, try to change it to a controller // that can block. if (OSUtils.isMacOSX() || OSUtils.isWindows()) { ThreadExecutor.startThread(new Runnable() { public void run() { final FileIconController newController = nativeFileIconControllerFactory.get(); if (newController.isValid()) { SwingUtilities.invokeLater(new Runnable() { public void run() { fileController = newController; } }); } } }, "NativeFileIconLoader"); } } /** * Function to create, cache, and provide an empty 16 by 16 icon. */ public Icon getBlankIcon() { if (this.blankIcon != null) return this.blankIcon; this.blankIcon = new Icon() { @Override public int getIconHeight() { return 16; } @Override public int getIconWidth() { return 16; } @Override public void paintIcon(Component c, Graphics g, int x, int y) { } }; return this.blankIcon; } /** * Returns the icon associated with this file. * If the file does not exist, or no icon can be found, returns * the icon associated with the extension. */ public Icon getIconForFile(File f) { validate(); return fileController.getIconForFile(f); } /** * Returns the icon associated with the extension. * TODO: Implement better. */ public Icon getIconForExtension(String ext) { validate(); return fileController.getIconForExtension(ext); } /** * Returns the icon associated with the extension for this PropertiableFile. */ public Icon getIconForPropertiableFile(PropertiableFile file) { return getIconForExtension(getExtension(file)); } /** Returns true if the icon can be returned immediately. */ public boolean isIconForFileAvailable(File f) { validate(); return fileController.isIconForFileAvailable(f); } /** * Returns a text description of the MIME type for the given PropertiableFile's extension. */ public String getMIMEDescription(PropertiableFile propertiable) { return getMIMEDescription(getExtension(propertiable)); } /** * Returns a text description of the MIME type for the given file extension. */ public String getMIMEDescription(String extension) { if (extension == null) { return null; } Icon icon = getIconForExtension(extension); if (icon == null) { return null; } String iconString = icon.toString(); if (iconString.indexOf("@") > -1) { //MIME label isn't set to something readable for the icon return null; } if (iconString.endsWith(".png")) { return null; } return iconString; } private String getExtension(PropertiableFile propertiable) { return FileUtils.getFileExtension(propertiable.getFileName()); } /** * Reverts the IconController to a basic controller if at any point * in time the controller becomes invalid. * <p> * Returns true if the current controller is already valid. */ private void validate() { if (!fileController.isValid()) fileController = this.originalFileController; } }