net.sf.jabref.gui.IconTheme.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jabref.gui.IconTheme.java

Source

/*  Copyright (C) 2003-2015 JabRef contributors.
This program 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 2 of the License, or
(at your option) any later version.
    
This program 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package net.sf.jabref.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import javax.swing.Icon;
import javax.swing.ImageIcon;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class IconTheme {

    public static Font FONT;
    public static Font FONT_16;

    /* Colors */

    // JabRef's default colors
    public static final Color DEFAULT_COLOR = new Color(79, 95, 143); // The purple color of the logo
    public static final Color DEFAULT_DISABLED_COLOR = new Color(200, 200, 200);

    // Christmas edition
    //public static final Color DEFAULT_COLOR = new Color(0x155115);
    //public static final Color DEFAULT_DISABLED_COLOR = new Color(0x990000);

    public static final int DEFAULT_SIZE = 24;
    public static final int SMALL_SIZE = 16;

    private static final Map<String, String> KEY_TO_ICON = readIconThemeFile(
            IconTheme.class.getResource("/images/Icons.properties"), "/images/external/");
    private static final String DEFAULT_ICON_PATH = "/images/external/red.png";

    private static final Log LOGGER = LogFactory.getLog(IconTheme.class);

    static {
        try (InputStream stream = FontBasedIcon.class
                .getResourceAsStream("/fonts/materialdesignicons-webfont.ttf")) {
            FONT = Font.createFont(Font.TRUETYPE_FONT, stream);
            FONT_16 = FONT.deriveFont(Font.PLAIN, 16f);
        } catch (FontFormatException | IOException e) {
            LOGGER.warn("Error loading font", e);
        }
    }

    public enum JabRefIcon {

        ADD("\uf416") /*css: mdi-plus-box*/, ADD_NOBOX("\uf415") /*css: plus */, ADD_ENTRY(
                "\uf527") /*css: tooltip-outline-plus */, EDIT_ENTRY("\uf524") /*css: tooltip-edit */, EDIT_STRINGS(
                        "\uf528") /*css: tooltip-text */, FOLDER("\uf24b"), /*css: folder */
        REMOVE("\uf375"), /*css: minus-box */
        REMOVE_NOBOX("\uf374") /*css: minus */, FILE("\uf214"), /* css: file*/
        PDF_FILE("\uf225"), /* css: file-pdf*/
        DOI("\uF072") /*css: barcode-scan*/, DUPLICATE("\uf191") /*css: content-duplicate */, EDIT(
                "\uf3eb") /*css: pencil */, NEW("\uf224") /* css: file-outline */, SAVE(
                        "\uf193") /*css: content-save*/, SAVE_ALL("\uf194") /*css: content-save-all*/, CLOSE(
                                "\uf156") /* css: close */, PASTE("\uf192") /*css: content-paste*/, CUT(
                                        "\uf190") /*css: content-cut*/, COPY("\uf18f") /*css: content-copy */, REDO(
                                                "\uf44e") /*css: redo*/, UNDO("\uf54c") /*css: undo*/, MARK_ENTRIES(
                                                        "\uf0c0") /*css: bookmark */, UNMARK_ENTRIES(
                                                                "\uf0c3") /*css: bookmark-outline */, REFRESH(
                                                                        "\uf450") /*css: refresh */, DELETE_ENTRY(
                                                                                "\uf1c0") /*css: delete */, SEARCH(
                                                                                        "\uf349") /*css: magnify */, PREFERENCES(
                                                                                                "\uf493") /*css: settings */, HELP(
                                                                                                        "\uf2d7") /*css: help-circle*/, UP(
                                                                                                                "\uf143") /*css: chevron-up */, DOWN(
                                                                                                                        "\uf140") /*css: chevron-down */, LEFT(
                                                                                                                                "\uf04e") /* css; arrow-left-bold */, RIGHT(
                                                                                                                                        "\uf055") /*css: arrow-right-bold */, SOURCE(
                                                                                                                                                "\uf169") /*css: code-braces*/, MAKE_KEY(
                                                                                                                                                        "\uf30b") /*css: key-variant */, CLEANUP_ENTRIES(
                                                                                                                                                                "\uf0e2") /*css: broom */, PRIORITY(
                                                                                                                                                                        "\uf23b") /*css: flag */, PRIORITY_HIGH(
                                                                                                                                                                                "\uF23B",
                                                                                                                                                                                Color.RED) /*css: flag */, PRIORITY_MEDIUM(
                                                                                                                                                                                        "\uF23B",
                                                                                                                                                                                        Color.ORANGE) /*css: flag */, PRIORITY_LOW(
                                                                                                                                                                                                "\uF23B",
                                                                                                                                                                                                new Color(
                                                                                                                                                                                                        111,
                                                                                                                                                                                                        204,
                                                                                                                                                                                                        117)) /*css: flag */, PRINTED(
                                                                                                                                                                                                                "\uf42a") /*css: printer */, RANKING(
                                                                                                                                                                                                                        "\uf4ce") /*css: star + star-outline: f4d2*/, RANK1(
                                                                                                                                                                                                                                "\uF4CE\uF4D2\uF4D2\uF4D2\uf4d2"), RANK2(
                                                                                                                                                                                                                                        "\uF4CE\uF4CE\uF4D2\uF4D2\uF4D2"), RANK3(
                                                                                                                                                                                                                                                "\uF4CE\uF4CE\uF4CE\uF4D2\uF4D2"), RANK4(
                                                                                                                                                                                                                                                        "\uF4CE\uF4CE\uF4CE\uF4CE\uF4D2"), RANK5(
                                                                                                                                                                                                                                                                "\uF4CE\uF4CE\uF4CE\uF4CE\uF4CE"), WWW(
                                                                                                                                                                                                                                                                        "\uf59f") /*css: web*/, GROUP_INCLUDING(
                                                                                                                                                                                                                                                                                "\uf233") /*css: filter-outline*/, GROUP_REFINING(
                                                                                                                                                                                                                                                                                        "\uf232") /*css: filter*/, AUTO_GROUP(
                                                                                                                                                                                                                                                                                                "\uf068"), /*css: auto-fix*/
        EMAIL("\uf1ee") /*css: email*/, EXPORT_TO_CLIPBOARD("\uf14b") /*css: clipboard-arrow-left */, ATTACH_FILE(
                "\uf3e2") /*css: paperclip*/, AUTO_FILE_LINK(
                        "\uf21e") /*css: file-find */, QUALITY_ASSURED("\uf124"), /*css: certificate */
        QUALITY("\uF124"), /*css: certificate */
        OPEN("\uf24b") /*css: folder */, ADD_ROW("\uf490") /* css: server-plus*/, REMOVE_ROW(
                "\uf48c") /*css: server-minus */, PICTURE("\uf21f") /*css: file-image */, READ_STATUS_READ("\uf208",
                        new Color(111, 204, 117)), /*css: eye */
        READ_STATUS_SKIMMED("\uF208", Color.ORANGE), /*css: eye */
        READ_STATUS("\uF208"), /*css: eye */
        RELEVANCE("\uf4cf"), /*css: star-circle */
        MERGE_ENTRIES("\uf18a"), /* css: compare */
        CONNECT_OPEN_OFFICE("\uf3cb") /*css: open-in-app */, PLAIN_TEXT_IMPORT_TODO(
                "\uf130") /* css: checkbox-blank-circle-outline*/, PLAIN_TEXT_IMPORT_DONE(
                        "\uf134") /* checkbox-marked-circle-outline */, DONATE("\uf2a1"), /* css: gift */
        MOVE_TAB_ARROW("\uf05e"), /*css:  arrow-up-bold */
        OPTIONAL("\uf316"), /*css: label-outline */
        REQUIRED("\uf315"), /*css: label */
        INTEGRITY_FAIL("\uf159", Color.RED), /*css: close-circle */
        INTEGRITY_INFO("\uf2fc"), /*css: information */
        INTEGRITY_WARN("\uf028"), /*css alert-circle */
        INTEGRITY_SUCCESS("\uF134") /*css: checkbox-marked-circle-outline */, GITHUB(
                "\uf2a4"), /*css: github-circle*/
        TOGGLE_ENTRY_PREVIEW("\uf332"), /*css: library-books */
        TOGGLE_GROUPS("\uf572"), /*css: view-list */
        WRITE_XMP("\uf2fa"), /* css: import */
        FILE_WORD("\uf22c"), /*css: file-word */
        FILE_EXCEL("\uf21b"), /*css: file-excel */
        FILE_POWERPOINT("\uf227"), /*css: file-powerpoint */
        FILE_TEXT("\uf219"), /*css: file-document */
        FILE_MULTIPLE("\uf222"), /*css: file-multiple */
        KEY_BINDINGS("\uf30c"), /*css: keyboard */
        FIND_DUPLICATES("\uf16b"), /*css: code-equal */

        OPEN_IN_NEW_WINDOW("\uf3cc"), /*css: open-in-new */
        CASE_SENSITIVE("\uf02c"), /* css: mdi-alphabetical */
        REG_EX("\uf451"), /*css: mdi-regex */
        CONSOLE("\uf18d"), /*css: console */
        FORUM("\uF28C"), /* css: forum */
        // STILL MISSING:
        GROUP_REGULAR("\uF4E6", Color.RED);

        private final String code;
        private final Color color;

        JabRefIcon(String code) {
            this(code, IconTheme.DEFAULT_COLOR);
        }

        JabRefIcon(String code, Color color) {
            this.code = code;
            this.color = color;
        }

        public FontBasedIcon getIcon() {
            return new FontBasedIcon(this.code, this.color);
        }

        public FontBasedIcon getSmallIcon() {
            return new FontBasedIcon(this.code, this.color, IconTheme.SMALL_SIZE);
        }

        public String getCode() {
            return this.code;
        }
    }

    public static class FontBasedIcon implements Icon {

        private final String iconCode;
        private final Color iconColor;
        private final int size;

        public FontBasedIcon(String code, Color iconColor) {
            this.iconCode = code;
            this.iconColor = iconColor;
            this.size = IconTheme.DEFAULT_SIZE;
        }

        public FontBasedIcon(String code, Color iconColor, int size) {
            this.iconCode = code;
            this.iconColor = iconColor;
            this.size = size;
        }

        @Override
        public void paintIcon(Component c, Graphics g, int x, int y) {
            Graphics2D g2 = (Graphics2D) g.create();

            RenderingHints rh = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING,
                    RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2.setRenderingHints(rh);

            g2.setFont(FONT.deriveFont(Font.PLAIN, size));
            g2.setColor(iconColor);
            FontMetrics fm = g2.getFontMetrics();

            g2.translate(x, y + fm.getAscent());
            g2.drawString(iconCode, 0, 0);

            g2.dispose();
        }

        @Override
        public int getIconWidth() {
            return size;
        }

        @Override
        public int getIconHeight() {
            return size;
        }

        public FontBasedIcon createDisabledIcon() {
            return new FontBasedIcon(this.iconCode, IconTheme.DEFAULT_DISABLED_COLOR, this.size);
        }

        public FontBasedIcon createSmallIcon() {
            return new FontBasedIcon(this.iconCode, this.iconColor, IconTheme.SMALL_SIZE);
        }

        public FontBasedIcon createWithNewColor(Color newColor) {
            return new FontBasedIcon(this.iconCode, newColor, this.size);
        }

    }

    /**
     * Constructs an ImageIcon for the image representing the given function, in the resource
     * file listing images.
     *
     * @param name The name of the icon, such as "open", "save", "saveAs" etc.
     * @return The ImageIcon for the function.
     */
    public static ImageIcon getImage(String name) {
        return new ImageIcon(getIconUrl(name));
    }

    /**
     * Looks up the URL for the image representing the given function, in the resource
     * file listing images.
     *
     * @param name The name of the icon, such as "open", "save", "saveAs" etc.
     * @return The URL to the actual image to use.
     */
    public static URL getIconUrl(String name) {
        String key = Objects.requireNonNull(name, "icon name");
        if (!KEY_TO_ICON.containsKey(key)) {
            LOGGER.warn("Could not find icon url by name " + name + ", so falling back on default icon "
                    + DEFAULT_ICON_PATH);
        }
        String path = KEY_TO_ICON.getOrDefault(key, DEFAULT_ICON_PATH);
        return Objects.requireNonNull(IconTheme.class.getResource(path), "Path must not be null for key " + key);
    }

    /**
     * Read a typical java property url into a Map. Currently doesn't support escaping
     * of the '=' character - it simply looks for the first '=' to determine where the key ends.
     * Both the key and the value is trimmed for whitespace at the ends.
     *
     * @param url    The URL to read information from.
     * @param prefix A String to prefix to all values read. Can represent e.g. the directory
     *               where icon files are to be found.
     * @return A Map containing all key-value pairs found.
     */
    // FIXME: prefix can be removed?!
    private static Map<String, String> readIconThemeFile(URL url, String prefix) {
        Objects.requireNonNull(url, "url");
        Objects.requireNonNull(prefix, "prefix");

        Map<String, String> result = new HashMap<>();

        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(url.openStream(), StandardCharsets.ISO_8859_1))) {
            String line;
            while ((line = in.readLine()) != null) {
                if (!line.contains("=")) {
                    continue;
                }

                int index = line.indexOf('=');
                String key = line.substring(0, index).trim();
                String value = prefix + line.substring(index + 1).trim();
                result.put(key, value);
            }
        } catch (IOException e) {
            LOGGER.warn("Unable to read default icon theme.", e);
        }
        return result;
    }
}