1. ControlsFX
  2. ControlsFX
  3. ControlsFX
  4. Issues

Issues

Issue #588 resolved

FontAwesome requires network access

Patrick Martin
created an issue

When you use controls such as ListSelectionView which require Font Awesome behind a corporate firewall or without network access, the buttons come up empty.

This appears due to a required network access to download them. Can we offer a localized fallback or some other workaround?

Thanks,

  • Pat

Comments (20)

  1. Steven Yi

    While I haven't used Fontawesome in a project, I looked at the code and I think you can package the .ttf in your own program, then call:

    InputStream inputStream = getClass().getResourceAsStream("fontawesome-webfont.ttf");
    GlyphFontRegistry.register(new FontAwesome(inputStream));
    

    (The above assumes the ttf file is in the same package as the class that is executing the above.)

    If I understand correctly, that will override the default registered FontAwesome (loaded from ServiceLoader) with one using a locally-loaded version. Glyph then should grab the new version from GlyphFontRegistry.

  2. Miłosz S

    Steven Yi Hi, I'm using FontAwesome manually, like this:

    GlyphFont fontAwesome = new FontAwesome(App.class.getResourceAsStream("/font-awesome.ttf"));
    someButton.setGraphic(fontAwesome.create(FontAwesome.Glyph.THUMB_TACK));
    

    But ContorlsFX is still trying to use FontAwesome loaded from the internet, which fails without active network connection, and button has no image in that case! Using GlyphFontRegistry.register(...) works, but I think that this is still a bug.

  3. Samir Hadzic

    I am experiencing the same issue and this is indeed a very serious issue. When using this component in real world application, we cannot allow the application to freeze during 10 seconds in order to get a Font from the Internet.

    Actually, FontAwesome is loaded from the constructor like that :

    public FontAwesome() {
            this("http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/fonts/fontawesome-webfont.ttf"); //$NON-NLS-1$
        }
    

    I think we should remove that and load the TTF file directly into ControlsFX as their license allow it. Also note that our current ttf file is from Cloudflare in 4.3 version and they are in 4.7. We cannot rely on a link that can be broken anytime.

  4. Samir Hadzic

    Anirvan Sarkar Can you develop? In our gradle dependencies for ControlsFX we could add the fontawesome jar? The JAR is 673 kB whereas the TTF file is only 100kB. Apparently, the only thing we need is that TTF file if I'm not mistaken.

  5. Dave Jarvis

    For system settings, I created the following class:

    https://github.com/DaveJarvis/scrivenvar/blob/master/src/main/java/com/scrivenvar/service/impl/DefaultSettings.java

    This allows the application to read from a settings properties file:

    https://github.com/DaveJarvis/scrivenvar/blob/master/src/main/resources/com/scrivenvar/settings.properties

    The "Settings" become a global service that can be loaded by any class:

    https://github.com/DaveJarvis/scrivenvar/blob/master/src/main/java/com/scrivenvar/Services.java

    As follows:

      private final Settings settings = Services.load( Settings.class );
    

    For FontAwesome, the same pattern could be used:

    class FontAwesome {
        private final Settings settings = Services.load( Settings.class );
    
        public FontAwesome() {
            if( getSettings().getBoolean( "init.font.awesome.remote", true ) ) {
                init( getSettings().getString( "init.font.awesome.url", DEFAULT_FA_URL ) );
            }
            else {
              init();
            }
        }
    
        public FontAwesome(String url){
            init(fontName, 14, url, true);
        }
    
        public FontAwesome(InputStream is){
            init(fontName, 14, is, true);
        }
    }
    

    Anyone who wants to prevent FontAwesome from loading remote resources can tweak an external setting. No code modifications required. This would also allow them to use a different CDN, newer version, also without code changes.

  6. John Jolayemi

    This is causing a bit of an issue in our near production software. I managed to work around it when there is no internet connection, but when there is a slow connection, it still tries to load the font and in turn slows down the loading of our application by up to 40 seconds. It looks like there is a static block in GlyphFontRegistry that calls the default constructor for FontAwesome, even when I just try to register a custom font:

        static {
            // find all classes that implement GlyphFont and register them now
            ServiceLoader<GlyphFont> loader = ServiceLoader.load(GlyphFont.class);
            for (GlyphFont font : loader) {
                GlyphFontRegistry.register(font);
            }
        }
    

    Is there a way to avoid this automatic registering?

  7. Stefano Negri

    Sorry to join in the discussion late, but I had the same issue and I solved it by putting this line:

    Font.loadFont(ResourceLoader.getResourceAsStream("/fonts/fontawesome-webfont.ttf", true), -1);
    

    early in my initialization code; doing this loads the font and it becomes available across the whole application. Of course, it assumes that the "ttf" file is available in the specified position.

  8. Dennis Waldherr

    A possible but ugly workaround is to prevent the service loader to find the service config file:

                // GlyphFontRegistry tries to load fonts using ServiceLoader.
                // ServiceLoader uses the context class loader, so we just replace it with a dummy
                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                Thread.currentThread().setContextClassLoader(new ClassLoader() {
                    @Override
                    public Class<?> loadClass(String name) throws ClassNotFoundException {
                        return super.loadClass(name);
                    }
    
                    @Override
                    public Enumeration<URL> getResources(String name) throws IOException {
                        // No config files for you
                        return Collections.emptyEnumeration();
                    }
                });
                // Fill this fontAwesome variable with the font you want, I used the FontAwesome(InputStream) constructor
                GlyphFontRegistry.register(fontAwesome);
                // Restore context class loader
                Thread.currentThread().setContextClassLoader(classLoader);
    
  9. Timm Baumeister

    If you need a local jar based version of fontawesome, my recommendation is to use de.jensd:fontawesomefx instead. Added benefit is that you can add various other glyph packages as jars (https://bintray.com/jerady/maven/FontAwesomeFX/8.15#files/de/jensd) . How to use:

    build.gradle:

    repositories {
            maven {
                url  "https://dl.bintray.com/jerady/maven"
            }
        }
    dependencies {
    compile 'de.jensd:fontawesomefx-commons:8.14'
        compile 'de.jensd:fontawesomefx-fontawesome:4.7.0-3'
        compile 'de.jensd:fontawesomefx-materialdesignfont:1.7.22-2'
    }
    
    import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
    import de.jensd.fx.glyphs.fontawesome.utils.FontAwesomeIconFactory;
    import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
    import de.jensd.fx.glyphs.materialdesignicons.utils.MaterialDesignIconFactory;
    
    Text t1 = MaterialDesignIconFactory.get().createIcon(MaterialDesignIcon.CLOSE,"10");
    Text t2 = FontAwesomeIconFactory.get().createIcon(FontAwesomeIcon.CLOSE,"10");
    
  10. Log in to comment