/* * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * muCommander is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.mucommander.ui.icon; import java.awt.Dimension; import java.awt.Image; import javax.swing.Icon; import javax.swing.ImageIcon; import com.mucommander.commons.file.AbstractFile; import com.mucommander.commons.file.FileFactory; import com.mucommander.commons.file.icon.FileIconProvider; import com.mucommander.commons.runtime.OsFamily; /** * <code>FileIcons</code> provides several methods to retrieve file icons for a given file: * <ul> * <li>{@link #getSystemFileIcon(AbstractFile)}: returns a system icon, provided by the underlying OS/desktop manager. * Under supported platforms, those file icons are the same as the ones displayed in the default file manager.</li> * <li>{@link #getCustomFileIcon(AbstractFile)}: returns a custom icon, fetched from the muCommander icon set and * based on the file's kind (archive, folder...) and extension.</li> * <li}{@link #getFileIcon(AbstractFile)} returns either a system icon or a custom icon, depending on the current * system icons policy. The default policy is {@link #DEFAULT_SYSTEM_ICONS_POLICY} and can be changed using * {@link #setSystemIconsPolicy(String)}.</li> * </ul> * Icons can be requested indifferently for any type of {@link AbstractFile} files: local files, remote files, * archives entries... The </p> * * <p>It is important to note that not all platforms have proper support for system file icons. * The {@link #hasProperSystemIcons()} method can be used to determine if the current platform properly supports system * icons. Non-supported platforms may return no icon (<code>null</code> values), or icons that do not resemble the * system ones.</p> * * @author Maxence Bernard */ public class FileIcons { /** Never use system file icons */ public final static String USE_SYSTEM_ICONS_NEVER = "never"; /** Use system file icons only for applications */ public final static String USE_SYSTEM_ICONS_APPLICATIONS = "applications"; /** Always use system file icons */ public final static String USE_SYSTEM_ICONS_ALWAYS = "always"; /** Default policy for system icons */ public final static String DEFAULT_SYSTEM_ICONS_POLICY = USE_SYSTEM_ICONS_APPLICATIONS; /** Default icon scale factor (no rescaling) */ public final static float DEFAULT_SCALE_FACTOR = 1.0f; /** Base width and height of icons for a scale factor of 1 */ private final static int BASE_ICON_DIMENSION = 16; /** Controls if and when system file icons should be used instead of custom icons */ private static String systemIconsPolicy = DEFAULT_SYSTEM_ICONS_POLICY; /** Current icon scale factor */ private static float scaleFactor = DEFAULT_SCALE_FACTOR; /** FileIconProvider instance for custom icons */ private static FileIconProvider customFileIconProvider; /** FileIconProvider instance for system icons */ private static FileIconProvider systemFileIconProvider; /** Current dimension of returned file icons */ private static Dimension iconDimension = new Dimension((int)(BASE_ICON_DIMENSION * DEFAULT_SCALE_FACTOR), (int)(BASE_ICON_DIMENSION * DEFAULT_SCALE_FACTOR)); /** * Initializes the system and custom file icon providers. */ static { setCustomFileIconProvider(new CustomFileIconProvider()); setSystemFileIconProvider(FileFactory.getDefaultFileIconProvider()); } /** * Shorthand for {@link #getFileIcon(com.mucommander.commons.file.AbstractFile, java.awt.Dimension)} called with the * icon dimension returned by {@link #getIconDimension()}. * * @param file the AbstractFile instance for which an icon will be returned * @return an icon for the given file * @see #getSystemIconsPolicy() */ public static Icon getFileIcon(AbstractFile file) { return getFileIcon(file, iconDimension); } /** * Returns an icon for the given file and of the specified dimension. * The returned icon will either be a system icon, or one from the custom icon set, depending on the current * {@link #getSystemIconsPolicy() system icons policy}. * If a system icon should have been returned for the specified file but could not be resolved * ({@link #getSystemFileIcon(AbstractFile, Dimension)} returned <code>null</code>), an icon from the * custom icon set will be returned instead. Therefore, this method never returns <code>null</code>. * * @param file the AbstractFile instance for which an icon will be returned * @param iconDimension the icon's dimension * @return an icon for the given file * @see #getSystemIconsPolicy() */ public static Icon getFileIcon(AbstractFile file, Dimension iconDimension) { boolean systemIcon = false; if(USE_SYSTEM_ICONS_ALWAYS.equals(systemIconsPolicy)) systemIcon = true; if(USE_SYSTEM_ICONS_APPLICATIONS.equals(systemIconsPolicy)) systemIcon = com.mucommander.desktop.DesktopManager.isApplication(file); if(systemIcon) { Icon icon = getSystemFileIcon(file, iconDimension); if(icon!=null) return icon; // If the system icon could not be resolved, return a custom file icon } return getCustomFileIcon(file, iconDimension); } /** * Shorthand for {@link #getCustomFileIcon(com.mucommander.commons.file.AbstractFile, java.awt.Dimension)} called with the * icon dimension returned by {@link #getIconDimension()}. * * @param file the file for which an icon is to be returned * @return a custom icon for the given file */ public static Icon getCustomFileIcon(AbstractFile file) { return getCustomFileIcon(file, iconDimension); } /** * Returns an icon of the specified dimension for the given file. The icon is provided by the * {@link #getCustomFileIconProvider() custom file icon provider}. This method is guaranteed to never return * <code>null</code>. * * @param file the file for which an icon is to be returned * @param iconDimension the icon's dimension * @return a custom icon for the given file * @see #getCustomFileIconProvider() */ public static Icon getCustomFileIcon(AbstractFile file, Dimension iconDimension) { return getFileProviderIcon(customFileIconProvider, file, iconDimension); } /** * Shorthand for {@link #getSystemFileIcon(com.mucommander.commons.file.AbstractFile, java.awt.Dimension)} called with the * icon dimension returned by {@link #getIconDimension()}. * * @param file the file for which an icon is to be returned * @return a system icon for the given file */ public static Icon getSystemFileIcon(AbstractFile file) { return getSystemFileIcon(file, iconDimension); } /** * Returns an icon of the specified dimension for the given file. The returned icon is provided by the * underlying OS/desktop manager, using the {@link com.mucommander.commons.file.icon.FileIconProvider} currently set. * Returns <code>null</code> if the icon couldn't be retrieved, either because the file doesn't exist or for * any other reason. * * @param file the file for which an icon is to be returned * @param iconDimension the icon's dimension * @return a system icon for the given file */ public static Icon getSystemFileIcon(AbstractFile file, Dimension iconDimension) { return getFileProviderIcon(systemFileIconProvider, file, iconDimension); } /** * Returns an icon of the specified dimension for the given file. The return icon is provided by the specified * {@link FileIconProvider}. This method takes care of up/down-scaling the icon returned by the provider if it * doesn't match the specified dimension. * * @param fip the FileIconProvider from which to fetch the icon * @param file the file for which an icon is to be returned * @param iconDimension the icon's dimension * @return an icon for the specified file */ private static Icon getFileProviderIcon(FileIconProvider fip, AbstractFile file, Dimension iconDimension) { Icon icon = fip.getFileIcon(file, iconDimension); if(icon==null) return null; if(iconDimension.width==icon.getIconWidth() && iconDimension.height==icon.getIconHeight()) return icon; // the icon already has the right dimension // Scale the icon to the target dimension ImageIcon imageIcon = IconManager.getImageIcon(icon); return new ImageIcon(imageIcon.getImage().getScaledInstance(iconDimension.width, iconDimension.height, Image.SCALE_AREA_AVERAGING)); } /** * Returns the {@link com.mucommander.commons.file.icon.FileIconProvider} instance that provides 'custom' file icons. * * @return the FileIconProvider instance that provides 'custom' file icons. */ public static FileIconProvider getCustomFileIconProvider() { return customFileIconProvider; } /** * Sets the {@link com.mucommander.commons.file.icon.FileIconProvider} instance that provides 'custom' file icons. * * @param fip the FileIconProvider instance that provides 'custom' file icons */ public static void setCustomFileIconProvider(FileIconProvider fip) { customFileIconProvider = fip; } /** * Returns the {@link com.mucommander.commons.file.icon.FileIconProvider} instance that provides 'system' file icons. * * @return the FileIconProvider instance that provides 'custom' file icons. */ public static FileIconProvider getSystemFileIconProvider() { return systemFileIconProvider; } /** * Sets the {@link com.mucommander.commons.file.icon.FileIconProvider} instance that provides 'custom' file icons. * * @param fip the FileIconProvider instance that provides 'custom' file icons */ public static void setSystemFileIconProvider(FileIconProvider fip) { systemFileIconProvider = fip; } /** * Returns the dimension of file icons currently returned by this class, which is the base icon dimension (16x16) * multiplied by the current scale factor. * * @return the dimension of file icons currently returned by this class */ public static Dimension getIconDimension() { return iconDimension; } /** * Returns the current icon scale factor, initialized by default to {@link #DEFAULT_SCALE_FACTOR}. * * @return the current icon scale factor */ public static float getScaleFactor() { return scaleFactor; } /** * Sets the current icon scale factor. The given value must be greater than 0. * * @param factor the new icon scale factor to use * @throws IllegalArgumentException if factor is lower or equal to 0 */ public static void setScaleFactor(float factor) { if(scaleFactor<=0) throw new IllegalArgumentException("Scale factor must be greater than 0, ("+factor+")"); scaleFactor = factor; iconDimension = new Dimension((int)(BASE_ICON_DIMENSION *scaleFactor), (int)(BASE_ICON_DIMENSION*scaleFactor)); } /** * Returns the current system icons policy, controlling when system file icons should be used instead * of custom file icons, see constant fields for possible values. The system icons policy is by default initialized * to {@link #DEFAULT_SYSTEM_ICONS_POLICY}. * * @return the current system icons policy */ public static String getSystemIconsPolicy() { return systemIconsPolicy; } /** * Sets the system icons policy, controlling when system file icons should be used instead of custom file icons. * See constants fields for allowed values. * * @param policy the new system icons policy to use */ public static void setSystemIconsPolicy(String policy) { systemIconsPolicy = policy; } /** * Returns <code>true</code> if the current platform is able to retrieve system icons that match the ones used in * the OS's default file manager. If <code>false</code> is returned and {@link #getSystemFileIcon(com.mucommander.commons.file.AbstractFile)} * is used or {@link #getFileIcon(com.mucommander.commons.file.AbstractFile)} together with a system policy different from * {@link #USE_SYSTEM_ICONS_NEVER}, the returned icon will probably look very bad. * * @return true if the current platform is able to retrieve system icons that match the ones used in the OS's * default file manager */ public static boolean hasProperSystemIcons() { return OsFamily.MAC_OS_X.isCurrent() || OsFamily.WINDOWS.isCurrent(); } }