5.5.8.2. Using Icons from Other Font Libraries

To enhance the theme extension, you may need to create icons and embed them into fonts, as well as use any external icons library.

  1. In the web module create the enum class implementing com.vaadin.server.FontIcon interface for the new icons:

    import com.vaadin.server.FontIcon;
    import com.vaadin.server.GenericFontIcon;
    
    public enum IcoMoon implements FontIcon {
    
        HEADPHONES(0XE900),
        SPINNER(0XE905);
    
        public static final String FONT_FAMILY = "IcoMoon";
        private int codepoint;
    
        IcoMoon(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 IcoMoon fromCodepoint(final int codepoint) {
            for (IcoMoon f : values()) {
                if (f.getCodepoint() == codepoint) {
                    return f;
                }
            }
            throw new IllegalArgumentException("Codepoint " + codepoint
                    + " not found in IcoMoon");
        }
    }
  2. Add new styles to the theme extension. We recommend creating a special subfolder fonts in the main folder of theme extension, for example, modules/web/themes/halo/com.company.demo/fonts. Put the styles and font files in their own subfolders, for example, fonts/icomoon.

    Files of fonts are represented by the following extensions:

    • .eot,

    • .svg,

    • .ttf,

    • .woff.

      The set of fonts icomoon from an open library, used in this example, consists of 4 joint used files: icomoon.eot, icomoon.svg, icomoon.ttf, icomoon.woff.

  3. Create a file with styles that includes @font-face and a CSS class with the icon style. Below is an example of the icomoon.scss file, where IcoMoon class name corresponds to the value returned by FontIcon#getFontFamily method:

    @mixin icomoon-style {
        /* use !important to prevent issues with browser extensions that change fonts */
        font-family: 'icomoon' !important;
        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;
    }
    
    @font-face {
        font-family: 'icomoon';
        src:url('icomoon.eot?hwgbks');
        src:url('icomoon.eot?hwgbks#iefix') format('embedded-opentype'),
            url('icomoon.ttf?hwgbks') format('truetype'),
            url('icomoon.woff?hwgbks') format('woff'),
            url('icomoon.svg?hwgbks#icomoon') format('svg');
        font-weight: normal;
        font-style: normal;
    }
    
    .IcoMoon {
        @include icomoon-style;
    }
  4. Create a reference to the file with font styles in halo-ext.scss or other file of theme extension:

    @import "fonts/icomoon/icomoon";
  5. Then create new icon set which is an enumeration implementing the Icons.Icon interface:

    import com.haulmont.cuba.gui.icons.Icons;
    
    public enum IcoMoonIcon implements Icons.Icon {
        HEADPHONES("ico-moon:HEADPHONES"),
        SPINNER("ico-moon:SPINNER");
    
        protected String source;
    
        IcoMoonIcon(String source) {
            this.source = source;
        }
    
        @Override
        public String source() {
            return source;
        }
    }
  6. Create new IconProvider.

    For managing custom icon sets CUBA platform provides the mechanism that consists of IconProvider and IconResolver.

    IconProvider is a marker interface that exists only in the web module and can provide resources (com.vaadin.server.Resource) by the icon path.

    The IconResolver bean obtains all beans that implement IconProvider interface and iterates over them to find the one that can provide a resource for the icon.

    There are two IconResolver interfaces and two corresponding implementations for desktop and web modules. They both are facade beans designed for resolving module-specific icon objects by the icon paths:

    • com.vaadin.server.Resource in the web module,

    • javax.swing.Icon for the desktop module.

    In order to use this mechanism, you should create your implementation of IconProvider:

    import com.haulmont.cuba.web.gui.icons.IconProvider;
    import com.vaadin.server.Resource;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    @Order(10)
    @Component
    public class IcoMoonIconProvider implements IconProvider {
        private final Logger log = LoggerFactory.getLogger(IcoMoonIconProvider.class);
    
        @Override
        public Resource getIconResource(String iconPath) {
            Resource resource = null;
    
            iconPath = iconPath.split(":")[1];
    
            try {
                resource = ((Resource) IcoMoon.class
                        .getDeclaredField(iconPath)
                        .get(null));
            } catch (IllegalAccessException | NoSuchFieldException e) {
                log.warn("There is no icon with name {} in the FontAwesome icon set", iconPath);
            }
    
            return resource;
        }
    
        @Override
        public boolean canProvide(String iconPath) {
            return iconPath.startsWith("ico-moon:");
        }
    }

    Here we explicitly assign order for this bean with @Order annotation.

  7. Register your icon set in the application properties file:

    cuba.iconsConfig = +com.company.demo.gui.icons.IcoMoonIcon

Now you can use new icons by direct reference to their class and enum element in XML-descriptor of the screen:

<button caption="Headphones" icon="ico-moon:HEADPHONES"/>

or in the Java controller:

spinnerBtn.setIconFromSet("ico-moon:SPINNER");

As a result, new icons are added to the buttons:

add icons
Overriding icons with icon sets

The mechanism of icon sets enables you to override icons from other sets. In order to do this, you should create and register a new icon set (enumeration) with the same icons (options) but with different icon paths (source). In the following example the new MyIcon enum is created to override the standard icons from CubaIcon set.

  1. The default icon set:

    public enum CubaIcon implements Icons.Icon {
        OK("font-icon:CHECK"),
        CANCEL("font-icon:BAN"),
       ...
    }
  2. The new icon set:

    public enum MyIcon implements Icons.Icon {
        OK("icons/my-custom-ok.png"),
       ...
    }
  3. Register the new icon set in web-app.properties:

    cuba.iconsConfig = +com.company.demo.gui.icons.MyIcon

Now, the new OK icon will be used instead of the standard one:

Icons icons = AppBeans.get(Icons.NAME);
button.setIcon(icons.getIcon(CubaIcon.OK))

In case you need to ignore redefinitions, you still can use the standard icons by using the path to an icon instead of the option name:

<button caption="Created" icon="icons/create.png"/>

or

button.setIcon(CubaIcon.CREATE_ACTION.source());