mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 22:10:54 +03:00
UIDefaultsLoader: added systemColor() color function that can be used to change accent color (preparation for getting accent color from operating system)
This commit is contained in:
@@ -98,6 +98,7 @@ public abstract class FlatLaf
|
|||||||
private static List<Object> customDefaultsSources;
|
private static List<Object> customDefaultsSources;
|
||||||
private static Map<String, String> globalExtraDefaults;
|
private static Map<String, String> globalExtraDefaults;
|
||||||
private Map<String, String> extraDefaults;
|
private Map<String, String> extraDefaults;
|
||||||
|
private static Function<String, Color> systemColorGetter;
|
||||||
|
|
||||||
private String desktopPropertyName;
|
private String desktopPropertyName;
|
||||||
private String desktopPropertyName2;
|
private String desktopPropertyName2;
|
||||||
@@ -897,14 +898,14 @@ public abstract class FlatLaf
|
|||||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The global extra defaults are useful for smaller additional defaults that may change.
|
* The global extra defaults are useful for smaller additional defaults that may change.
|
||||||
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
* Otherwise, FlatLaf properties files should be used.
|
||||||
* See {@link #registerCustomDefaultsSource(String)}.
|
* See {@link #registerCustomDefaultsSource(String)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||||
* <p>
|
* <p>
|
||||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
* Sample that setups "FlatLaf Light" theme with white background color:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
* FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@background", "#fff" ) );
|
||||||
* FlatLightLaf.setup();
|
* FlatLightLaf.setup();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
@@ -929,15 +930,15 @@ public abstract class FlatLaf
|
|||||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The extra defaults are useful for smaller additional defaults that may change.
|
* The extra defaults are useful for smaller additional defaults that may change.
|
||||||
* E.g. accent color. Otherwise, FlatLaf properties files should be used.
|
* Otherwise, FlatLaf properties files should be used.
|
||||||
* See {@link #registerCustomDefaultsSource(String)}.
|
* See {@link #registerCustomDefaultsSource(String)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||||
* <p>
|
* <p>
|
||||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
* Sample that setups "FlatLaf Light" theme with white background color:
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* FlatLaf laf = new FlatLightLaf();
|
* FlatLaf laf = new FlatLightLaf();
|
||||||
* laf.setExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
* laf.setExtraDefaults( Collections.singletonMap( "@background", "#fff" ) );
|
||||||
* FlatLaf.setup( laf );
|
* FlatLaf.setup( laf );
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
@@ -979,6 +980,36 @@ public abstract class FlatLaf
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the system color getter function, or {@code null}.
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static Function<String, Color> getSystemColorGetter() {
|
||||||
|
return systemColorGetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a system color getter function that is invoked when function
|
||||||
|
* {@code systemColor()} is used in FlatLaf properties files.
|
||||||
|
* <p>
|
||||||
|
* The name of the system color is passed as parameter to the function.
|
||||||
|
* The function should return {@code null} for unknown system colors.
|
||||||
|
* <p>
|
||||||
|
* Can be used to change the accent color:
|
||||||
|
* <pre>{@code
|
||||||
|
* FlatLaf.setSystemColorGetter( name -> {
|
||||||
|
* return name.equals( "accent" ) ? Color.red : null;
|
||||||
|
* } );
|
||||||
|
* FlatLightLaf.setup();
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public static void setSystemColorGetter( Function<String, Color> systemColorGetter ) {
|
||||||
|
FlatLaf.systemColorGetter = systemColorGetter;
|
||||||
|
}
|
||||||
|
|
||||||
private static void reSetLookAndFeel() {
|
private static void reSetLookAndFeel() {
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class UIDefaultsLoader
|
|||||||
|
|
||||||
private static int parseColorDepth;
|
private static int parseColorDepth;
|
||||||
|
|
||||||
|
private static Map<String, ColorUIResource> systemColorCache;
|
||||||
private static final SoftCache<String, Object> fontCache = new SoftCache<>();
|
private static final SoftCache<String, Object> fontCache = new SoftCache<>();
|
||||||
|
|
||||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
||||||
@@ -105,6 +106,10 @@ class UIDefaultsLoader
|
|||||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// temporary cache system colors while loading defaults,
|
||||||
|
// which avoids that system color getter is invoked multiple times
|
||||||
|
systemColorCache = (FlatLaf.getSystemColorGetter() != null) ? new HashMap<>() : null;
|
||||||
|
|
||||||
// load core properties files
|
// load core properties files
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
for( Class<?> lafClass : lafClasses ) {
|
for( Class<?> lafClass : lafClasses ) {
|
||||||
@@ -276,6 +281,9 @@ class UIDefaultsLoader
|
|||||||
|
|
||||||
// remember variables in defaults to allow using them in styles
|
// remember variables in defaults to allow using them in styles
|
||||||
defaults.put( KEY_VARIABLES, variables );
|
defaults.put( KEY_VARIABLES, variables );
|
||||||
|
|
||||||
|
// clear/disable system color cache
|
||||||
|
systemColorCache = null;
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load properties files.", ex );
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load properties files.", ex );
|
||||||
}
|
}
|
||||||
@@ -769,6 +777,7 @@ class UIDefaultsLoader
|
|||||||
try {
|
try {
|
||||||
switch( function ) {
|
switch( function ) {
|
||||||
case "if": return parseColorIf( value, params, resolver );
|
case "if": return parseColorIf( value, params, resolver );
|
||||||
|
case "systemColor": return parseColorSystemColor( value, params, resolver );
|
||||||
case "rgb": return parseColorRgbOrRgba( false, params, resolver );
|
case "rgb": return parseColorRgbOrRgba( false, params, resolver );
|
||||||
case "rgba": return parseColorRgbOrRgba( true, params, resolver );
|
case "rgba": return parseColorRgbOrRgba( true, params, resolver );
|
||||||
case "hsl": return parseColorHslOrHsla( false, params );
|
case "hsl": return parseColorHslOrHsla( false, params );
|
||||||
@@ -813,6 +822,44 @@ class UIDefaultsLoader
|
|||||||
return parseColorOrFunction( resolver.apply( ifValue ), resolver );
|
return parseColorOrFunction( resolver.apply( ifValue ), resolver );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Syntax: systemColor(name[,defaultValue])
|
||||||
|
* - name: system color name
|
||||||
|
* - defaultValue: default color value used if system color is not available
|
||||||
|
*/
|
||||||
|
private static Object parseColorSystemColor( String value, List<String> params, Function<String, String> resolver ) {
|
||||||
|
if( params.size() < 1 )
|
||||||
|
throwMissingParametersException( value );
|
||||||
|
|
||||||
|
ColorUIResource systemColor = getSystemColor( params.get( 0 ) );
|
||||||
|
if( systemColor != null )
|
||||||
|
return systemColor;
|
||||||
|
|
||||||
|
String defaultValue = (params.size() > 1) ? params.get( 1 ) : "";
|
||||||
|
if( defaultValue.equals( "null" ) || defaultValue.isEmpty() )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return parseColorOrFunction( resolver.apply( defaultValue ), resolver );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ColorUIResource getSystemColor( String name ) {
|
||||||
|
Function<String, Color> systemColorGetter = FlatLaf.getSystemColorGetter();
|
||||||
|
if( systemColorGetter == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// use containsKey() because value may be null
|
||||||
|
if( systemColorCache != null && systemColorCache.containsKey( name ) )
|
||||||
|
return systemColorCache.get( name );
|
||||||
|
|
||||||
|
Color color = systemColorGetter.apply( name );
|
||||||
|
ColorUIResource uiColor = (color != null) ? new ColorUIResource( color ) : null;
|
||||||
|
|
||||||
|
if( systemColorCache != null )
|
||||||
|
systemColorCache.put( name, uiColor );
|
||||||
|
|
||||||
|
return uiColor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha)
|
* Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha)
|
||||||
* - red: an integer 0-255 or a percentage 0-100%
|
* - red: an integer 0-255 or a percentage 0-100%
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
# accent colors (blueish)
|
# accent colors (blueish)
|
||||||
# set @accentColor to use single accent color or
|
# set @accentColor to use single accent color or
|
||||||
# modify @accentBaseColor to use variations of accent base color
|
# modify @accentBaseColor to use variations of accent base color
|
||||||
@accentColor = null
|
@accentColor = systemColor(accent,null)
|
||||||
@accentBaseColor = #4B6EAF
|
@accentBaseColor = #4B6EAF
|
||||||
@accentBase2Color = lighten(saturate(spin(@accentBaseColor,-8),13%),5%)
|
@accentBase2Color = lighten(saturate(spin(@accentBaseColor,-8),13%),5%)
|
||||||
# accent color variations
|
# accent color variations
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
# accent colors (blueish)
|
# accent colors (blueish)
|
||||||
# set @accentColor to use single accent color or
|
# set @accentColor to use single accent color or
|
||||||
# modify @accentBaseColor to use variations of accent base color
|
# modify @accentBaseColor to use variations of accent base color
|
||||||
@accentColor = null
|
@accentColor = systemColor(accent,null)
|
||||||
@accentBaseColor = #2675BF
|
@accentBaseColor = #2675BF
|
||||||
@accentBase2Color = lighten(saturate(@accentBaseColor,10%),6%)
|
@accentBase2Color = lighten(saturate(@accentBaseColor,10%),6%)
|
||||||
# accent color variations
|
# accent color variations
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import java.net.URISyntaxException;
|
|||||||
import java.time.Year;
|
import java.time.Year;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.text.DefaultEditorKit;
|
import javax.swing.text.DefaultEditorKit;
|
||||||
@@ -398,6 +397,7 @@ class DemoFrame
|
|||||||
};
|
};
|
||||||
private final JToggleButton[] accentColorButtons = new JToggleButton[accentColorKeys.length];
|
private final JToggleButton[] accentColorButtons = new JToggleButton[accentColorKeys.length];
|
||||||
private JLabel accentColorLabel;
|
private JLabel accentColorLabel;
|
||||||
|
private Color accentColor;
|
||||||
|
|
||||||
private void initAccentColors() {
|
private void initAccentColors() {
|
||||||
accentColorLabel = new JLabel( "Accent color: " );
|
accentColorLabel = new JLabel( "Accent color: " );
|
||||||
@@ -416,6 +416,10 @@ class DemoFrame
|
|||||||
|
|
||||||
accentColorButtons[0].setSelected( true );
|
accentColorButtons[0].setSelected( true );
|
||||||
|
|
||||||
|
FlatLaf.setSystemColorGetter( name -> {
|
||||||
|
return name.equals( "accent" ) ? accentColor : null;
|
||||||
|
} );
|
||||||
|
|
||||||
UIManager.addPropertyChangeListener( e -> {
|
UIManager.addPropertyChangeListener( e -> {
|
||||||
if( "lookAndFeel".equals( e.getPropertyName() ) )
|
if( "lookAndFeel".equals( e.getPropertyName() ) )
|
||||||
updateAccentColorButtons();
|
updateAccentColorButtons();
|
||||||
@@ -424,17 +428,17 @@ class DemoFrame
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void accentColorChanged( ActionEvent e ) {
|
private void accentColorChanged( ActionEvent e ) {
|
||||||
String accentColor = accentColorKeys[0];
|
String accentColorKey = null;
|
||||||
for( int i = 0; i < accentColorButtons.length; i++ ) {
|
for( int i = 0; i < accentColorButtons.length; i++ ) {
|
||||||
if( accentColorButtons[i].isSelected() ) {
|
if( accentColorButtons[i].isSelected() ) {
|
||||||
accentColor = accentColorKeys[i];
|
accentColorKey = accentColorKeys[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatLaf.setGlobalExtraDefaults( (accentColor != accentColorKeys[0])
|
accentColor = (accentColorKey != null && accentColorKey != accentColorKeys[0])
|
||||||
? Collections.singletonMap( "@accentColor", "$" + accentColor )
|
? UIManager.getColor( accentColorKey )
|
||||||
: null );
|
: null;
|
||||||
|
|
||||||
Class<? extends LookAndFeel> lafClass = UIManager.getLookAndFeel().getClass();
|
Class<? extends LookAndFeel> lafClass = UIManager.getLookAndFeel().getClass();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -410,6 +410,10 @@ class FlatCompletionProvider
|
|||||||
addFunction( "lazy",
|
addFunction( "lazy",
|
||||||
"uiKey", "UI key (without leading '$')" );
|
"uiKey", "UI key (without leading '$')" );
|
||||||
|
|
||||||
|
addFunction( "systemColor",
|
||||||
|
"name", "system color name",
|
||||||
|
"defaultValue", "default color value used if system color is not available" );
|
||||||
|
|
||||||
addFunction( "rgb",
|
addFunction( "rgb",
|
||||||
"red", "0-255 or 0-100%",
|
"red", "0-255 or 0-100%",
|
||||||
"green", "0-255 or 0-100%",
|
"green", "0-255 or 0-100%",
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public class FlatThemeTokenMaker
|
|||||||
tokenMap.put( "lazy", TOKEN_FUNCTION );
|
tokenMap.put( "lazy", TOKEN_FUNCTION );
|
||||||
|
|
||||||
// color functions
|
// color functions
|
||||||
|
tokenMap.put( "systemColor", TOKEN_FUNCTION );
|
||||||
tokenMap.put( "rgb", TOKEN_FUNCTION );
|
tokenMap.put( "rgb", TOKEN_FUNCTION );
|
||||||
tokenMap.put( "rgba", TOKEN_FUNCTION );
|
tokenMap.put( "rgba", TOKEN_FUNCTION );
|
||||||
tokenMap.put( "hsl", TOKEN_FUNCTION );
|
tokenMap.put( "hsl", TOKEN_FUNCTION );
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ Prop.ifColor = lighten(if(#000,#0f0,#dfd), 10%)
|
|||||||
Prop.ifColorVar = lighten(if(@varTrue,@varTrueValue,@varFalseValue), 10%)
|
Prop.ifColorVar = lighten(if(@varTrue,@varTrueValue,@varFalseValue), 10%)
|
||||||
Prop.lazy = lazy(Prop.string)
|
Prop.lazy = lazy(Prop.string)
|
||||||
|
|
||||||
|
Prop.systemColor1 = systemColor(accent,null)
|
||||||
|
Prop.systemColor2 = systemColor(accent,#f00)
|
||||||
|
|
||||||
Prop.colorFunc1 = rgb(12,34,56)
|
Prop.colorFunc1 = rgb(12,34,56)
|
||||||
Prop.colorFunc2 = rgba(12,34,56,78)
|
Prop.colorFunc2 = rgba(12,34,56,78)
|
||||||
Prop.colorFunc3 = hsl(12,34%,56%)
|
Prop.colorFunc3 = hsl(12,34%,56%)
|
||||||
|
|||||||
Reference in New Issue
Block a user