All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kordamp.ikonli.javafx.FontIcon Maven / Gradle / Ivy

There is a newer version: 12.3.1
Show newest version
/*
 * Copyright 2015-2016 Andres Almiray. 
 *
 * Licensed 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.kordamp.ikonli.javafx;

import com.sun.javafx.css.converters.PaintConverter;
import com.sun.javafx.css.converters.SizeConverter;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.css.CssMetaData;
import javafx.css.Styleable;
import javafx.css.StyleableIntegerProperty;
import javafx.css.StyleableObjectProperty;
import javafx.css.StyleableProperty;
import javafx.scene.paint.Color;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Paint;
import javafx.scene.paint.RadialGradient;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import org.kordamp.ikonli.Ikon;
import org.kordamp.ikonli.IkonHandler;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;

/**
 * @author Andres Almiray
 */
public class FontIcon extends Text implements Icon {
    protected StyleableIntegerProperty iconSize;
    protected StyleableObjectProperty iconColor;
    private StyleableObjectProperty iconCode;

    public FontIcon() {
        getStyleClass().setAll("ikonli-font-icon");
        setIconSize(16);
        setIconColor(Color.BLACK);

        fontProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Font oldValue, Font newValue) {
                int size = (int) newValue.getSize();
                if (size != getIconSize()) {
                    setIconSize(size);
                }
            }
        });

        fillProperty().addListener(new ChangeListener() {
            @Override
            public void changed(ObservableValue observable, Paint oldValue, Paint newValue) {
                Paint fill = getIconColor();
                if (!Objects.equals(fill, newValue)) {
                    setIconColor(newValue);
                }
            }
        });
    }

    public FontIcon(String iconCode) {
        this();
        setIconLiteral(iconCode);
    }

    public FontIcon(Ikon iconCode) {
        this();
        setIconCode(iconCode);
    }

    public String toString() {
        return getIconCode().getDescription() + ":" + getIconSize() + ":" + getIconColor();
    }

    @Override
    public IntegerProperty iconSizeProperty() {
        if (iconSize == null) {
            iconSize = new StyleableIntegerProperty(16) {
                @Override
                public CssMetaData getCssMetaData() {
                    return StyleableProperties.ICON_SIZE;
                }

                @Override
                public Object getBean() {
                    return FontIcon.this;
                }

                @Override
                public String getName() {
                    return "iconSize";
                }
            };
            iconSize.addListener(new ChangeListener() {
                @Override
                public void changed(ObservableValue observable, Number oldValue, Number newValue) {
                    Font font = FontIcon.this.getFont();
                    FontIcon.this.setFont(Font.font(font.getFamily(), newValue.doubleValue()));
                    FontIcon.this.setStyle(normalizeStyle(getStyle(), "-fx-font-size", newValue.intValue() + "px"));
                }
            });
        }
        return iconSize;
    }

    @Override
    public ObjectProperty iconColorProperty() {
        if (iconColor == null) {
            iconColor = new StyleableObjectProperty(Color.BLACK) {
                @Override
                public CssMetaData getCssMetaData() {
                    return StyleableProperties.ICON_COLOR;
                }

                @Override
                public Object getBean() {
                    return FontIcon.this;
                }

                @Override
                public String getName() {
                    return "iconColor";
                }
            };
            iconColor.addListener(new ChangeListener() {
                @Override
                public void changed(ObservableValue observable, Paint oldValue, Paint newValue) {
                    FontIcon.this.setFill(newValue);
                }
            });
        }
        return iconColor;
    }

    public ObjectProperty iconCodeProperty() {
        if (iconCode == null) {
            iconCode = new StyleableObjectProperty() {
                @Override
                public CssMetaData getCssMetaData() {
                    return StyleableProperties.ICON_CODE;
                }

                @Override
                public Object getBean() {
                    return FontIcon.this;
                }

                @Override
                public String getName() {
                    return "iconCode";
                }
            };
            iconCode.addListener(new ChangeListener() {
                @Override
                public void changed(ObservableValue observable, Ikon oldValue, Ikon newValue) {
                    FontIcon.this.setIconCode(newValue);
                }
            });
        }
        return iconCode;
    }

    public ObjectProperty getIconCodeProperty() {
        return iconCodeProperty();
    }

    @Override
    public void setIconSize(int size) {
        if (size <= 0) {
            throw new IllegalStateException("Argument 'size' must be greater than zero.");
        }
        iconSizeProperty().set(size);
    }

    @Override
    public int getIconSize() {
        return iconSizeProperty().get();
    }

    @Override
    public void setIconColor(Paint paint) {
        requireNonNull(paint, "Argument 'paint' must not be null");
        iconColorProperty().set(paint);
    }

    @Override
    public Paint getIconColor() {
        return iconColorProperty().get();
    }

    public Ikon getIconCode() {
        return iconCodeProperty().get();
    }

    public void setIconCode(Ikon iconCode) {
        iconCodeProperty().set(requireNonNull(iconCode, "Argument 'code' must not be null"));
        IkonHandler ikonHandler = IkonResolver.getInstance().resolveIkonHandler(iconCode.getDescription());
        setStyle(normalizeStyle(getStyle(), "-fx-font-family", "'" + ikonHandler.getFontFamily() + "'"));
        setText(String.valueOf(iconCode.getCode()));
    }

    private String normalizeStyle(String style, String key, String value) {
        int start = style.indexOf(key);
        if (start != -1) {
            int end = style.indexOf(";", start);
            end = end >= start ? end : style.length() - 1;
            style = style.substring(0, start) + style.substring(end + 1);
        }
        return style + key + ": " + value + ";";
    }

    public void setIconLiteral(String iconCode) {
        String[] parts = iconCode.split(":");
        setIconCode(IkonResolver.getInstance().resolveIkonHandler(parts[0]).resolve(parts[0]));
        resolveSize(iconCode, parts);
        resolvePaint(iconCode, parts);
    }

    public String getIconLiteral() {
        Ikon ikon = iconCodeProperty().get();
        return ikon != null ? ikon.getDescription() : null;
    }

    private static class StyleableProperties {
        private static final CssMetaData ICON_SIZE =
            new CssMetaData("-fx-icon-size",
                SizeConverter.getInstance(), 16.0) {

                @Override
                public boolean isSettable(FontIcon icon) {
                    return true;
                }

                @Override
                public StyleableProperty getStyleableProperty(FontIcon icon) {
                    return (StyleableProperty) icon.iconSizeProperty();
                }
            };

        private static final CssMetaData ICON_COLOR =
            new CssMetaData("-fx-icon-color",
                PaintConverter.getInstance(), Color.BLACK) {

                @Override
                public boolean isSettable(FontIcon node) {
                    return true;
                }

                @Override
                public StyleableProperty getStyleableProperty(FontIcon icon) {
                    return (StyleableProperty) icon.iconColorProperty();
                }
            };

        private static final CssMetaData ICON_CODE =
            new CssMetaData("-fx-icon-code",
                FontIconConverter.getInstance(), null) {

                @Override
                public boolean isSettable(FontIcon node) {
                    return true;
                }

                @Override
                public StyleableProperty getStyleableProperty(FontIcon icon) {
                    return (StyleableProperty) icon.iconCodeProperty();
                }
            };

        private static final List> STYLEABLES;

        static {
            final List> styleables =
                new ArrayList>(Text.getClassCssMetaData());
            styleables.add(ICON_SIZE);
            styleables.add(ICON_COLOR);
            styleables.add(ICON_CODE);
            STYLEABLES = unmodifiableList(styleables);
        }
    }

    public static List> getClassCssMetaData() {
        return StyleableProperties.STYLEABLES;
    }

    public List> getCssMetaData() {
        return FontIcon.getClassCssMetaData();
    }

    private void resolveSize(String iconCode, String[] parts) {
        if (parts.length > 1) {
            try {
                setIconSize(Integer.parseInt(parts[1]));
            } catch (NumberFormatException e) {
                throw invalidDescription(iconCode, e);
            }
        } else {
            setIconSize(16);
        }
    }

    private void resolvePaint(String iconCode, String[] parts) {
        if (parts.length > 2) {
            Paint paint = resolvePaintValue(iconCode, parts[2]);
            if (paint != null) {
                setIconColor(paint);
            }
        }
    }

    private static Paint resolvePaintValue(String iconCode, String value) {
        try { return Color.valueOf(value); } catch (IllegalArgumentException e1) {
            try { return LinearGradient.valueOf(value); } catch (IllegalArgumentException e2) {
                try { return RadialGradient.valueOf(value); } catch (IllegalArgumentException e3) {
                    throw invalidDescription(iconCode, e3);
                }
            }
        }
    }

    public static IllegalArgumentException invalidDescription(String description, Exception e) {
        throw new IllegalArgumentException("Description " + description + " is not a valid icon description", e);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy