/** * 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 Lesser 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.mucommander.commons.file.icon; import com.mucommander.commons.file.AbstractFile; import com.mucommander.commons.file.FileFactory; import com.mucommander.commons.file.protocol.local.LocalFile; import javax.swing.*; import java.awt.*; import java.io.IOException; /** * <code>LocalFileIconProvider</code> is an abstract {@link FileIconProvider} which makes things easier for * implementations that are only able to provide icons for local files. * * <p>This class implements {@link #getFileIcon(com.mucommander.commons.file.AbstractFile, java.awt.Dimension)} and passes on * requests for local file icons to {@link #getLocalFileIcon(com.mucommander.commons.file.protocol.local.LocalFile, com.mucommander.commons.file.AbstractFile, java.awt.Dimension)}. * On the other hand, requests for non-local file icons are transformed to local ones, by creating a local temporary * file with the same name (best effort) and extension (guaranteed) as the non-local file, and passes on the file * to {@link #getLocalFileIcon(com.mucommander.commons.file.protocol.local.LocalFile, com.mucommander.commons.file.AbstractFile, java.awt.Dimension)}.</p> * * @author Maxence Bernard */ public abstract class LocalFileIconProvider implements FileIconProvider { /** * Creates a returns a temporary local file/directory with the same extension as the specified file/directory * (guaranteed), and the same filename as much as possible (best effort). * This method returns <code>null</code> if the temporary file/directory could not be created. * * @param nonLocalFile the non-local file for which to create a temporary file. * @return a temporary local file/directory with the same extension as the specified file/directory */ protected LocalFile createTempLocalFile(AbstractFile nonLocalFile) { try { // Note: the returned temporary file may be an AbstractArchiveFile if the filename's extension corresponds // to a registered archive format LocalFile tempFile = FileFactory.getTemporaryFile(nonLocalFile.getName(), false).getAncestor(LocalFile.class); // Create a directory if(nonLocalFile.isDirectory()) tempFile.mkdir(); // Create a regular file else tempFile.getOutputStream().close(); return tempFile; } catch(IOException e) { return null; } } ///////////////////////////////////// // FileIconProvider implementation // ///////////////////////////////////// public Icon getFileIcon(AbstractFile originalFile, Dimension preferredResolution) { // Specified file is a LocalFile or a ProxyFile proxying a LocalFile (e.g. an archive file): let's simply get // the icon using #getLocalFileIcon(LocalFile) AbstractFile topFile = originalFile.getTopAncestor(); Icon icon; if(topFile instanceof LocalFile) { icon = getLocalFileIcon((LocalFile)topFile, originalFile, preferredResolution); } // File is a remote file: create a temporary local file (or directory) with the same extension to grab the icon // and then delete the file. This operation is I/O bound and thus expensive, so an LRU is used to cache // frequently-accessed file extensions. else { // Create the temporary, local file LocalFile tempFile = createTempLocalFile(topFile); if(tempFile==null) { // No temp file, no icon! return null; } // Get the file icon icon = getLocalFileIcon(tempFile, originalFile, preferredResolution); // Delete the temporary file try { tempFile.delete(); } catch(IOException e) { // Not much to do } } return icon; } ////////////////////// // Abstract methods // ////////////////////// /** * Returns an icon for the given local file, <code>null</code> if the icon couldn't be retrieved. This method is * called by {@link #getFileIcon(com.mucommander.commons.file.AbstractFile, java.awt.Dimension)} with a {@link LocalFile} * equivalent to the {@link AbstractFile} originally requested. * * <p>The specified <code>Dimension</code> is used as a hint at the preferred icon's resolution; there is * absolutely no guarantee that the returned <code>Icon</code> will indeed have this resolution. This dimension is * only used to choose between different resolutions should more than one resolution be available, and return the * one that most closely matches the specified one.<br/> * This method is not expected to perform any rescaling (either up or down), returned resolutions should only be * 'native' icon resolutions. For example, if this provider is able to create icons both in 16x16 and 32x32 * resolutions, and a 48x48 resolution is preferred, the 32x32 resolution should be favored for the returned icon.</p> * * @param localFile the LocalFile instance for which an icon is requested * @param originalFile the AbstractFile for which an icon was originally requested * @param preferredResolution the preferred icon resolution * @return an icon for the requested file */ public abstract Icon getLocalFileIcon(LocalFile localFile, AbstractFile originalFile, Dimension preferredResolution); }