Добавление значков из других библиотек шрифтов

Для более тонкой настройки расширенной темы можно создать значки, встроенные в шрифты, либо использовать готовые внешние библиотеки значков. В качестве примера рассмотрим использование шрифта Font Awesome 5 со стилем Brands.

  1. Создайте класс enum, реализующий интерфейс com.vaadin.server.FontIcon, в который поместите новые значки:

    public enum FontAwesome5Brands implements FontIcon {
    
        JAVA(0XF4E4);
    
        public static final String FONT_FAMILY = "FontAwesome5Brands";
        private final int codepoint;
    
        FontAwesome5Brands(int codepoint) {
            this.codepoint = codepoint;
        }
    
    
        @Override
        public String getFontFamily() {
            return FONT_FAMILY;
        }
    
        @Override
        public int getCodepoint() {
            return codepoint;
        }
    
        @Override
        public String getHtml() {
            return GenericFontIcon.getHtml(FONT_FAMILY, codepoint);
        }
    
        @Override
        public String getMIMEType() {
            throw new UnsupportedOperationException(FontIcon.class.getSimpleName()
                    + " should not be used where a MIME type is needed.");
        }
    
        public static FontAwesome5Brands fromCodepoint(final int codepoint) {
            for (FontAwesome5Brands f : values()) {
                if (f.getCodepoint() == codepoint) {
                    return f;
                }
            }
            throw new IllegalArgumentException(
                    "Codepoint " + codepoint + " not found in FontAwesome 5");
        }
    }
  2. Добавьте новые стили и файлы шрифта в свою тему. Рекомендуется создать отдельную папку fonts в главном каталоге расширения темы, например, themes/helium-extended/fonts. Поместите в нее стили и файлы шрифтов в своих собственных подпапках, например, fonts/fontawesome.

    Файлы шрифта включают в себя набор следующих расширений:

    • .eot,

    • .svg,

    • .ttf,

    • .woff,

    • .woff2.

    Набор шрифтов fontawesome со стилем Brands представлен в виде 5 файлов: fa-brands-400.eot, fa-brands-400.svg, fa-brands-400.ttf, fa-brands-400.woff, fa-brands-400.woff2, которые используются совместно.

    Если вы хотите использовать другие стили (Solid, Regular и так далее), нужно определить уникальное имя класса для каждого варианта FontAwesome. Также необходимо реализовать отдельные IconSets и Providers для каждого варианта.

  3. Создайте файл стилей, в который включите @font-face и CSS класс со стилем для значка. Ниже представлен пример файла fontawesome5.scss, где имя класса FontAwesome5Brands соответствует значению, возвращаемому методом FontIcon.getFontFamily():

    @mixin font-icon-style {
      speak: none;
      font-style: normal;
      font-weight: normal;
      font-variant: normal;
      text-transform: none;
      line-height: 1;
    
      /* Better Font Rendering =========== */
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }
    
    /* FontAwesome 5 Brands */
    
    @mixin font-awesome-5-brands-style {
      font-family: 'FontAwesome5Brands';
      @include font-icon-style;
    }
    
    @font-face {
      font-family: 'FontAwesome5Brands';
      src: url('fa-brands-400.eot?hwgbks');
      src: url('fa-brands-400.eot?hwgbks#iefix') format('embedded-opentype'),
      url('fa-brands-400.ttf?hwgbks') format('truetype'),
      url('fa-brands-400.woff?hwgbks') format('woff'),
      url('fa-brands-400.svg?hwgbks#icomoon') format('svg');
      font-weight: normal;
      font-style: normal;
    }
    
    .FontAwesome5Brands {
      @include font-awesome-5-brands-style;
    }
  4. Подключите файл стилей шрифта в helium-extended.scss или другой файл данной темы:

    @import "fonts/fontawesome5/fontawesome5";
  5. Затем создайте новый набор значков, то есть enum, реализующий интерфейс Icons.Icon:

    public enum FontAwesome5Icon implements Icons.Icon {
    
        JAVA("font-awesome5-brands-icon:JAVA");
    
        protected String source;
    
        FontAwesome5Icon(String source) {
            this.source = source;
        }
    
        @Override
        public String source() {
            return source;
        }
    
        @Override
        public String iconName() {
            return name();
        }
    }
  6. Создайте новый IconProvider.

    Для работы с наборами значков в фреймворке Jmix есть механизм, основанный на использовании IconProvider и IconResolver.

    IconProvider – это интерфейс-маркер, который предоставляет доступ к ресурсу (com.vaadin.server.Resource) по переданному пути.

    Бин IconResolver проходится по всем бинам, реализующим IconProvider, в поисках того, кто может предоставить ресурс к данному значку.

    Чтобы использовать этот механизм, необходимо создать собственную реализацию IconProvider, например, так:

    @Order(10)
    @Component("sample_FontAwesome5BrandsIconProvider")
    public class FontAwesome5BrandsIconProvider implements IconProvider {
    
        public static final String FONT_AWESOME_5_BRANDS_PREFIX = "font-awesome5-brands-icon:";
        private final Logger log = LoggerFactory.getLogger(FontAwesome5BrandsIconProvider.class);
    
        @Override
        public Resource getIconResource(String iconPath) {
            Resource resource = null;
    
            iconPath = iconPath.split(":")[1];
    
            try {
                resource = ((Resource) FontAwesome5Brands.class
                        .getDeclaredField(iconPath)
                        .get(null));
            } catch (IllegalAccessException | NoSuchFieldException e) {
                log.warn("There is no icon with name {} in the FontAwesome5Brands icon set", iconPath);
            }
    
            return resource;
        }
    
        @Override
        public boolean canProvide(String iconPath) {
            return !Strings.isNullOrEmpty(iconPath)
                    && iconPath.startsWith(FONT_AWESOME_5_BRANDS_PREFIX);
        }
    }

    Здесь мы явно назначаем порядок для этого бина аннотацией @Order.

  7. Далее нужно зарегистрировать набор значков в файле application.properties:

    jmix.ui.icons-config = ui.ex1.icon.FontAwesome5Icon

Теперь вы можете использовать значки по прямой ссылке на класс и элемент enum в XML-дескрипторе экрана:

<button icon="font-awesome5-brands-icon:JAVA"/>

или в контроллере Java:

cIconBtn.setIconFromSet(FontAwesome5Icon.JAVA);

Переопределение значков с помощью наборов

Механизм наборов значков позволяет переопределять некоторые значки из других наборов. Для этого необходимо создать и зарегистрировать новый набор значков (enumeration) с теми же именами значков (options), но с другими путями (source). В примере ниже создан новый набор MyIcon, в котором переопределены стандартные значки из набора JmixIcon.

  1. Создайте новый набор значков:

    public enum NewIcon implements Icons.Icon {
    
        OK("classpath:/icon/custom-ok.png");
    }
  2. Зарегистрируйте новый набор значков в application.properties:

    jmix.ui.icons-config = ui.ex1.icon.NewIcon

Теперь вместо стандартного значка OK будет использован новый:

@Autowired
private Icons icons;

@Subscribe
protected void onInit(InitEvent event) {
    okIconBtn.setIcon(icons.get(JmixIcon.OK));
}

При необходимости игнорировать переопределение и использовать стандартные значки, просто используйте путь к значку вместо имени элемента перечисления:

<button caption="Custom" icon="font-icon:CHECK"/>

или

oIconBtn.setIcon(JmixIcon.OK.source());