From b208017117503e25a9ea8a13a7e1b7e475828667 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 26 Aug 2020 11:01:41 +0200 Subject: [PATCH] added API to register packages or folders where FlatLaf searches for application specific properties files with custom UI defaults --- CHANGELOG.md | 3 + .../java/com/formdev/flatlaf/FlatLaf.java | 84 +++++++++++++++++++ .../com/formdev/flatlaf/UIDefaultsLoader.java | 38 +++++++++ .../flatlaf/testing/FlatTestFrame.java | 3 + .../customdefaults/FlatDarkLaf.properties | 1 + .../testing/customdefaults/FlatLaf.properties | 2 + .../customdefaults/FlatLightLaf.properties | 1 + 7 files changed, 132 insertions(+) create mode 100644 flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatDarkLaf.properties create mode 100644 flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLaf.properties create mode 100644 flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLightLaf.properties diff --git a/CHANGELOG.md b/CHANGELOG.md index ae1b128b..04b913a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ FlatLaf Change Log #### New features +- Added API to register packages or folders where FlatLaf searches for + application specific properties files with custom UI defaults (see + `FlatLaf.registerCustomDefaultsSource(...)` methods). - Extras: `FlatSVGIcon` now allows specifying `ClassLoader` that is used to load SVG file. (issue #163) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java index 6273b8b3..6fe7f5f4 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -29,6 +29,7 @@ import java.awt.image.ImageFilter; import java.awt.image.ImageProducer; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; @@ -76,6 +77,8 @@ public abstract class FlatLaf static final Logger LOG = Logger.getLogger( FlatLaf.class.getName() ); private static final String DESKTOPFONTHINTS = "awt.font.desktophints"; + private static List customDefaultsSources; + private String desktopPropertyName; private String desktopPropertyName2; private PropertyChangeListener desktopPropertyListener; @@ -552,6 +555,87 @@ public abstract class FlatLaf defaults.put( key, value ); } + static List getCustomDefaultsSources() { + return customDefaultsSources; + } + + /** + * Registers a package where FlatLaf searches for properties files with custom UI defaults. + *

+ * This can be used to specify application specific UI defaults that override UI values + * of existing themes or to define own UI values used in custom controls. + *

+ * There may be multiple properties files in that package for multiple themes. + * The properties file name must match the used theme class names. + * E.g. {@code FlatLightLaf.properties} for class {@link FlatLightLaf} + * or {@code FlatDarkLaf.properties} for class {@link FlatDarkLaf}. + * {@code FlatLaf.properties} is loaded first for all themes. + *

+ * These properties files are loaded after theme and addon properties files + * and can therefore override all UI defaults. + *

+ * Invoke this method before setting the look and feel. + * + * @param packageName a package name (e.g. "com.myapp.resources") + */ + public static void registerCustomDefaultsSource( String packageName ) { + registerCustomDefaultsSource( packageName, null ); + } + + public static void unregisterCustomDefaultsSource( String packageName ) { + unregisterCustomDefaultsSource( packageName, null ); + } + + /** + * Registers a package where FlatLaf searches for properties files with custom UI defaults. + *

+ * See {@link #registerCustomDefaultsSource(String)} for details. + * + * @param packageName a package name (e.g. "com.myapp.resources") + * @param classLoader a class loader used to find resources, or {@code null} + */ + public static void registerCustomDefaultsSource( String packageName, ClassLoader classLoader ) { + if( customDefaultsSources == null ) + customDefaultsSources = new ArrayList<>(); + customDefaultsSources.add( packageName ); + customDefaultsSources.add( classLoader ); + } + + public static void unregisterCustomDefaultsSource( String packageName, ClassLoader classLoader ) { + if( customDefaultsSources == null ) + return; + + int size = customDefaultsSources.size(); + for( int i = 0; i < size - 1; i++ ) { + Object source = customDefaultsSources.get( i ); + if( packageName.equals( source ) && customDefaultsSources.get( i + 1 ) == classLoader ) { + customDefaultsSources.remove( i + 1 ); + customDefaultsSources.remove( i ); + break; + } + } + } + + /** + * Registers a folder where FlatLaf searches for properties files with custom UI defaults. + *

+ * See {@link #registerCustomDefaultsSource(String)} for details. + * + * @param folder a folder + */ + public static void registerCustomDefaultsSource( File folder ) { + if( customDefaultsSources == null ) + customDefaultsSources = new ArrayList<>(); + customDefaultsSources.add( folder ); + } + + public static void unregisterCustomDefaultsSource( File folder ) { + if( customDefaultsSources == null ) + return; + + customDefaultsSources.remove( folder ); + } + private static void reSetLookAndFeel() { EventQueue.invokeLater( () -> { LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java index 467f90b7..d1303d48 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java @@ -19,6 +19,8 @@ package com.formdev.flatlaf; import java.awt.Color; import java.awt.Dimension; import java.awt.Insets; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -107,6 +109,42 @@ class UIDefaultsLoader } } + // load custom properties files (usually provides by applications) + List customDefaultsSources = FlatLaf.getCustomDefaultsSources(); + int size = (customDefaultsSources != null) ? customDefaultsSources.size() : 0; + for( int i = 0; i < size; i++ ) { + Object source = customDefaultsSources.get( i ); + if( source instanceof String && i + 1 < size ) { + // load from package in classloader + String packageName = (String) source; + ClassLoader classLoader = (ClassLoader) customDefaultsSources.get( ++i ); + + packageName = packageName.replace( '.', '/' ); + if( classLoader == null ) + classLoader = FlatLaf.class.getClassLoader(); + + for( Class lafClass : lafClasses ) { + String propertiesName = packageName + '/' + lafClass.getSimpleName() + ".properties"; + try( InputStream in = classLoader.getResourceAsStream( propertiesName ) ) { + if( in != null ) + properties.load( in ); + } + } + } else if( source instanceof File ) { + // load from folder + File folder = (File) source; + for( Class lafClass : lafClasses ) { + File propertiesFile = new File( folder, lafClass.getSimpleName() + ".properties" ); + if( !propertiesFile.isFile() ) + continue; + + try( InputStream in = new FileInputStream( propertiesFile ) ) { + properties.load( in ); + } + } + } + } + // collect addon class loaders List addonClassLoaders = new ArrayList<>(); for( FlatDefaultsAddon addon : addons ) { diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java index ee909e32..ea0c8e4f 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTestFrame.java @@ -77,6 +77,9 @@ public class FlatTestFrame // disable animated Laf change System.setProperty( "flatlaf.animatedLafChange", "false" ); + // test loading custom defaults from package + FlatLaf.registerCustomDefaultsSource( "com.formdev.flatlaf.testing.customdefaults" ); + // set look and feel DemoPrefs.initLaf( args ); diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatDarkLaf.properties b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatDarkLaf.properties new file mode 100644 index 00000000..0228f31a --- /dev/null +++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatDarkLaf.properties @@ -0,0 +1 @@ +# @background=#000 diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLaf.properties b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLaf.properties new file mode 100644 index 00000000..cc1b0e74 --- /dev/null +++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLaf.properties @@ -0,0 +1,2 @@ +# Component.arc=9999 +# TextComponent.arc=9999 diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLightLaf.properties b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLightLaf.properties new file mode 100644 index 00000000..33afe328 --- /dev/null +++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/customdefaults/FlatLightLaf.properties @@ -0,0 +1 @@ +# @background=#fff