001    /*
002     * This file is part of muCommander, http://www.mucommander.com
003     * Copyright (C) 2002-2008 Maxence Bernard
004     *
005     * muCommander is free software; you can redistribute it and/or modify
006     * it under the terms of the GNU General Public License as published by
007     * the Free Software Foundation; either version 3 of the License, or
008     * (at your option) any later version.
009     *
010     * muCommander is distributed in the hope that it will be useful,
011     * but WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013     * GNU General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     */
018    
019    package com.mucommander.file.icon;
020    
021    import com.mucommander.cache.LRUCache;
022    import com.mucommander.file.AbstractFile;
023    
024    import javax.swing.*;
025    import java.awt.*;
026    
027    /**
028     * <code>CachedFileIconProvider</code> is a <code>FileIconProvider</code> with caching capabilities.
029     *
030     * <p>This class does not actually provide icons nor does it manage the contents of the cache ; it delegates these tasks
031     * to a {@link CacheableFileIconProvider} instance. All this class does is use the cache implementation to harness its
032     * befinits and take all the credit for it.</br>
033     * When an icon is requested, a cache lookup is performed. If a cached value is found, it is returned. If not, the icon
034     * is fetched from the underlying provider and added to the cache.</p>
035     *
036     * @author Maxence Bernard
037     */
038    public class CachedFileIconProvider implements FileIconProvider {
039    
040        /** The underlying icon provider and cache manager */
041        protected CacheableFileIconProvider cacheableFip;
042    
043        /** Default capacity of icon caches */
044        public final static int DEFAULT_FILE_CACHE_CAPACITY = 100;
045    
046        /** Current capacity of icon caches */
047        protected static int cacheCapacity = DEFAULT_FILE_CACHE_CAPACITY;
048    
049    
050        /**
051         * Creates a new CachedFileIconProvider that uses the given {@link CacheableFileIconProvider} to access the cache
052         * and retrieve the icons.
053         *
054         * @param cacheableFip the underlying icon provider and cache manager
055         */
056        public CachedFileIconProvider(CacheableFileIconProvider cacheableFip) {
057            this.cacheableFip = cacheableFip;
058        }
059    
060        /**
061         * Creates and returns an {@link com.mucommander.cache.LRUCache} instance with a capacity equal to
062         * {@link #getCacheCapacity()}.
063         *
064         * @return an LRUCache instance
065         */
066        public static LRUCache createCache() {
067            return LRUCache.createInstance(cacheCapacity);
068        }
069    
070        /**
071         * Sets the capacity of the {@link LRUCache} that caches frequently accessed file instances. The more the capacity,
072         * the more frequent the cache is hit but the higher the memory usage. By default, the capacity is
073         * {@link #DEFAULT_FILE_CACHE_CAPACITY}.
074         *
075         * <p>Note that calling this method does not change the capacity of existing caches so to be effective, this method
076         * must be called before {@link #createCache()} is called.</p>
077         *
078         * @param capacity the capacity of the LRU cache that caches frequently accessed icon instances
079         * @see com.mucommander.cache.LRUCache
080         */
081        public static void setCacheCapacity(int capacity) {
082            cacheCapacity = capacity;
083        }
084    
085        /**
086         * Returns the capacity of the {@link LRUCache} that caches frequently accessed icon instances. By default, the
087         * capacity is {@link #DEFAULT_FILE_CACHE_CAPACITY}.
088         *
089         * @return the capacity of the LRU cache that caches frequently accessed icon instances
090         */
091        public static int getCacheCapacity() {
092            return cacheCapacity;
093        }
094    
095    
096        /////////////////////////////////////
097        // FileIconProvider implementation //
098        /////////////////////////////////////
099    
100        /**
101         * <i>Implementation notes</i>: this method first calls {@link CacheableFileIconProvider#isCacheable(com.mucommander.file.AbstractFile, java.awt.Dimension)}
102         * to determine if the icon cache is used.
103         *
104         * <p><b>If the file icon is cacheable</b>, {@link CacheableFileIconProvider#lookupCache(com.mucommander.file.AbstractFile, java.awt.Dimension)}
105         * is called to look for a previously cached icon. If a value is found, it is returned. If not,
106         * {@link #getFileIcon(com.mucommander.file.AbstractFile, java.awt.Dimension)} is called on the <code>CacheableFileIconProvider</code>
107         * to retrieve the icon. This icon is then added to the cache by calling
108         * {@link CacheableFileIconProvider#addToCache(com.mucommander.file.AbstractFile, javax.swing.Icon, java.awt.Dimension)}.
109         * </p>
110         *
111         * <p><b>If the file icon is not cacheable</b>, {@link #getFileIcon(com.mucommander.file.AbstractFile, java.awt.Dimension)}
112         * is simply called on the <code>CacheableFileIconProvider</code> and its value returned.</p>
113         */
114        public Icon getFileIcon(AbstractFile file, Dimension preferredResolution) {
115            Icon icon;
116            boolean isCacheable = cacheableFip.isCacheable(file, preferredResolution);
117    
118            // Look for the file icon in the provider's cache
119            if(isCacheable)
120                icon = cacheableFip.lookupCache(file, preferredResolution);
121            else
122                icon = null;
123    
124            // Icon is not cacheable or isn't present in the cache, retrieve it from the provider
125            if(icon==null) {
126                icon = cacheableFip.getFileIcon(file, preferredResolution);
127    
128                // Cache the icon
129                if(isCacheable && icon!=null)
130                    cacheableFip.addToCache(file, icon, preferredResolution);
131            }
132    
133            return icon;
134        }
135    }