org.freedesktop.icons.DefaultIconService.java Source code

Java tutorial

Introduction

Here is the source code for org.freedesktop.icons.DefaultIconService.java

Source

/**
 * SSHTOOLS Limited licenses this file to you under the Apache
 * License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.freedesktop.icons;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.vfs2.FileObject;
import org.freedesktop.themes.AbstractThemeService;
import org.freedesktop.util.Log;

/**
 * Default implementations of an {@link IconService}. Four image types are
 * supported. PNG, GIF, XPM and SVG.
 * <p>
 * Icon locations are also cached in memory, keyed on
 * [iconName]_[preferredSize]. Use {@link #clearCache()} to remove all cached
 * locations.
 */
public class DefaultIconService extends AbstractThemeService<IconTheme> implements IconService {

    /**
     * Support file extensions
     */
    public final static String[] SUPPORTED_EXTENSIONS = { "png", "svg", "gif", "xpm" };

    // Private instance variables
    private Map<String, FileObject> cache = new HashMap<String, FileObject>();

    private boolean returnMissingImage = true;
    private Map<String, String> existing = new TreeMap<String, String>();
    protected String defaultThemeName = null;

    public DefaultIconService() throws IOException, ParseException {
        super();
    }

    public void setDefaultThemeName(String defaultThemeName) {
        this.defaultThemeName = defaultThemeName;
    }

    public final void postInit() {
        IconTheme theme = getSelectedTheme();
        if (theme == null) {
            theme = getDefaultTheme();
        }
        if (theme != null) {
            setSelectedTheme(theme);
        }
    }

    protected IconTheme getDefaultTheme() {
        if (defaultThemeName != null) {
            IconTheme theme = getEntity(defaultThemeName);
            if (theme != null) {
                return theme;
            }
        }
        FileObject firstBase = bases.keySet().isEmpty() ? null : bases.keySet().iterator().next();
        return firstBase == null ? null : bases.get(firstBase).iterator().next();
    }

    public void addBase(FileObject base) throws IOException {
        super.addBase(base);
        clearCache();
    }

    public void removeBase(FileObject base) {
        super.removeBase(base);
        clearCache();
    }

    public void setSelectedTheme(IconTheme theme) {
        super.setSelectedTheme(theme);
        clearCache();
        preCache();
    }

    public Iterator<FileObject> icons(int size) {
        return new IconIterator(size);
    }

    public Iterator<String> iconNames() {
        return existing.keySet().iterator();
    }

    public FileObject findIcon(String name, int size) throws IOException {
        String key = name + "_" + size;
        FileObject file = null;
        if (cache.containsKey(key)) {
            return cache.get(key);
        }

        // if(!existing.containsKey(name)) {
        // return returnMissing(name, size, key, new
        // IOException("Precache didn't find"));
        // }

        IconTheme theme = getSelectedTheme();
        if (theme != null) {
            file = findIconHelper(name, size, theme);
            if (file != null) {
                cache.put(key, file);
                return file;
            }
        }
        try {
            file = lookupFallbackIcon(name);
            if (file != null) {
                cache.put(key, file);
                return file;
            }
        } catch (IOException ioe) {
            return returnMissing(name, size, key, ioe);
        }

        return null;
    }

    private FileObject returnMissing(String name, int size, String key, IOException ioe) throws IOException {
        FileObject file = null;
        if (!name.equals("image-missing") && returnMissingImage) {
            file = findIcon("image-missing", size);
            if (file != null) {
                cache.put(key, file);
            }
        } else {
            if (returnMissingImage) {
                throw ioe;
            }
        }
        return file;
    }

    public boolean isIconExists(String name, int size) throws IOException {
        String key = name + "_" + size;
        FileObject file = cache.get(key);
        ;
        if (file != null && file.exists()) {
            return true;
        }
        IconTheme theme = getSelectedTheme();
        if (theme != null) {
            file = findIconHelper(name, size, theme);
            if (file != null) {
                cache.put(key, file);
                return true;
            }
        }
        try {
            file = lookupFallbackIcon(name);
            if (file != null) {
                cache.put(key, file);
                return true;
            }
        } catch (IOException ioe) {
        }
        return false;
    }

    public void setReturnMissingImage(boolean returnMissingImage) {
        this.returnMissingImage = returnMissingImage;
    }

    public void clearCache() {
        existing.clear();
        cache.clear();
    }

    void preCache() {
        // Log.warn("Precaching, may take a while");
        // long started = System.currentTimeMillis();
        // IconTheme selectedTheme = getSelectedTheme();
        // List<String> extensions = Arrays.asList(SUPPORTED_EXTENSIONS);
        // if (selectedTheme != null) {
        // List<IconTheme> toPreCache = new ArrayList<IconTheme>();
        // addParents(selectedTheme, toPreCache);
        // for (IconTheme theme : toPreCache) {
        // for (Directory dir : theme.getDirectories()) {
        // File dirFile = new File(theme.getBase(), dir.getKey());
        // File[] images = dirFile.listFiles();
        // if (images != null) {
        // for (File image : images) {
        // String imageName = image.getName();
        // int lidx = imageName.lastIndexOf('.');
        // if (lidx != -1) {
        // String ext = imageName.substring(lidx + 1);
        // if (extensions.contains(ext)) {
        // existing.put(imageName.substring(0, lidx), ext);
        // }
        // }
        // }
        // }
        // }
        // }
        // }
        // Log.warn("Precaching done (" + existing.size() + " took " +
        // ((System.currentTimeMillis() - started) / 1000) + ")");
    }

    void addParents(IconTheme theme, List<IconTheme> toPreCache) {
        if (!toPreCache.contains(theme)) {
            toPreCache.add(theme);
        }
        for (String parent : theme.getParents()) {
            IconTheme parentTheme = getEntity(parent);
            if (parentTheme != null) {
                addParents(parentTheme, toPreCache);
            }
        }
    }

    protected Collection<IconTheme> scanBase(FileObject base) throws IOException {
        List<IconTheme> themes = new ArrayList<IconTheme>();
        FileObject[] listDirs = listDirs(base);
        for (FileObject dir : listDirs) {
            // TODO cursor themes not supported here
            FileObject cursorTheme = dir.resolveFile("cursor.theme");
            FileObject cursorsDir = dir.resolveFile("cursors");
            if (cursorTheme.exists() || cursorsDir.exists()) {
                // Skip
                Log.debug("Skipping " + dir + " because it is a cursor theme.");
                continue;
            }

            try {
                themes.add(new IconTheme(dir));
            } catch (FileNotFoundException fnfe) {
                // Skip
                Log.debug("Skipping " + dir + " because index.theme is missing.");
            } catch (IOException ioe) {
                Log.warn("Invalid theme directory " + dir.getName().getPath() + "." + ioe.getMessage());
            }
        }
        return themes;
    }

    FileObject lookupFallbackIcon(String iconname) throws IOException {
        for (FileObject base : bases.keySet()) {
            for (String extension : SUPPORTED_EXTENSIONS) {
                FileObject f = base.resolveFile(iconname + "." + extension);
                if (f.exists()) {
                    return f;
                }
            }
        }
        throw new IOException("No theme or fallback icon for " + iconname + ".");
    }

    FileObject findIconHelper(String icon, int size, IconTheme theme) throws IOException {
        FileObject filename = theme.lookupIcon(icon, size);
        if (filename != null) {
            return filename;
        }

        Collection<String> parents = new ArrayList<String>();
        if (theme.isParents()) {
            parents.addAll(theme.getParents());
        }

        if (!theme.getInternalName().equals(HICOLOR) && !parents.contains(HICOLOR)) {
            parents.add(HICOLOR);
        }

        for (String parent : parents) {
            IconTheme parentTheme = getEntity(parent);
            if (parentTheme == null) {
                Log.debug(
                        "Parent theme " + parent + " specified in " + theme.getInternalName() + " does not exist.");
            } else {
                filename = findIconHelper(icon, size, parentTheme);
                if (filename != null) {
                    return filename;
                }
            }
        }
        return null;
    }

    private static final String HICOLOR = "hicolor";

    class IconIterator implements Iterator<FileObject> {

        private int size;
        private Iterator<String> icons;

        IconIterator(int size) {
            this.size = size;
            icons = existing.keySet().iterator();
        }

        public boolean hasNext() {
            return icons.hasNext();
        }

        public FileObject next() {
            String icon = icons.next();
            try {
                return findIcon(icon, size);
            } catch (IOException e) {
                throw new Error(e);
            }
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

    }
}