Project Themes in 8.3

Hi,

In 8.1 we just dropped the themes css files into the data/modules/com.inductiveautomation.perspective folder and everything just worked.

In 8.3 is it necessary to use the ThemeMigrator API? If so then I'm a bit stumped about how to get started. I read the Configurtion Migration guide [ an old version at least - still can't access the latest version ] and it seemed to hint that maybe themes was part of this new way of doing things but I didn't know where to begin.

Anybody got a suggestion about working with themes in 8.3 - preferably with a code example if APIs are involved.

Thanks

Themes are now a part of the same standardized config system more or less everything is in 8.3.

You'll have to 'inject' your resources through the new configuration manager. You'll also have to make your module 'depend on' the Perspective module, if it isn't already, to get access to the PerspectiveContext and related classes.

I think something like this should work; there's one slightly unpleasant cast in the middle obscured in the instanceof, because the public type doesn't expose any modification actions, but this is a lot "cleaner" than dumping files on disk:

        PerspectiveContext context = PerspectiveContext.get(gatewayContext);
        if (context.getThemeManager() instanceof NamedResourceHandler<?> themeManager) {
            themeManager.create("myCustomTheme", new ThemeConfig(null), "myCoolModule", builder -> {
                builder.putData("extraFile.css", ImmutableBytes.fromStream(myExtraFileInputStream));
            });
        }

Regarding the configuration management guide, that can be found here: 8.3 Early Access Now Available! - #3

It's migrated to an internal doc, so we'll be adding pdf updates to the above post as needed.

1 Like

Hi Paul,

Thanks for your quick reply. The only way I could get your code to compile is if I used

themeManager.create("kanoaTheme", null);

But this causes issues further down the line with:

java.lang.NullPointerException: config object is required

If I use your code as it is above I get

The method create(String, capture#5-of ?) in the type NamedResourceHandler<capture#5-of ?> is not applicable for the arguments (String, ThemeConfig)

I used a slightly different constructor just trying to get to the bottom of the reason that the create method doesn't like the ThemeConfig object. Kinda going around in circles here so any pointers would be very much appreciated.

Probably type erasure of the generic. You'll have to do a technically-unsound cast to assure the compiler that the instance is the type you assert:

PerspectiveContext context = PerspectiveContext.get(gatewayContext);
if (context.getThemeManager() instanceof NamedResourceHandler<?> genericManager) {
    NamedResourceManager<ThemeConfig> themeManager = (NamedResourceManager<ThemeConfig>) genericManager;
    themeManager.create("myCustomTheme", new ThemeConfig(null), "myCoolModule", builder -> {
        builder.putData("extraFile.css", ImmutableBytes.fromStream(myExtraFileInputStream));
    });
}