mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 14:37:13 -06:00
Merge PR #375: Accent colors
# Conflicts: # flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java # flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java
This commit is contained in:
@@ -88,6 +88,8 @@ public abstract class FlatLaf
|
||||
private static final String DESKTOPFONTHINTS = "awt.font.desktophints";
|
||||
|
||||
private static List<Object> customDefaultsSources;
|
||||
private static Map<String, String> globalExtraDefaults;
|
||||
private Map<String, String> extraDefaults;
|
||||
|
||||
private String desktopPropertyName;
|
||||
private String desktopPropertyName2;
|
||||
@@ -466,7 +468,15 @@ public abstract class FlatLaf
|
||||
}
|
||||
|
||||
protected Properties getAdditionalDefaults() {
|
||||
return null;
|
||||
if( globalExtraDefaults == null && extraDefaults == null )
|
||||
return null;
|
||||
|
||||
Properties properties = new Properties();
|
||||
if( globalExtraDefaults != null )
|
||||
properties.putAll( globalExtraDefaults );
|
||||
if( extraDefaults != null )
|
||||
properties.putAll( extraDefaults );
|
||||
return properties;
|
||||
}
|
||||
|
||||
private void initResourceBundle( UIDefaults defaults, String bundleName ) {
|
||||
@@ -779,6 +789,71 @@ public abstract class FlatLaf
|
||||
customDefaultsSources.remove( folder );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets global extra UI defaults; or {@code null}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public static Map<String, String> getGlobalExtraDefaults() {
|
||||
return globalExtraDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets global extra UI defaults, which are only used when setting up the application look and feel.
|
||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||
* <p>
|
||||
* The global extra defaults are useful for smaller additional defaults that may change.
|
||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
||||
* See {@link #registerCustomDefaultsSource(String)}.
|
||||
* <p>
|
||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||
* <p>
|
||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
||||
* <pre>{@code
|
||||
* FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
||||
* FlatLightLaf.setup();
|
||||
* }</pre>
|
||||
*
|
||||
* @see #setExtraDefaults(Map)
|
||||
* @since 2
|
||||
*/
|
||||
public static void setGlobalExtraDefaults( Map<String, String> globalExtraDefaults ) {
|
||||
FlatLaf.globalExtraDefaults = globalExtraDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extra UI defaults; or {@code null}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public Map<String, String> getExtraDefaults() {
|
||||
return extraDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extra UI defaults, which are only used when setting up the application look and feel.
|
||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||
* <p>
|
||||
* The extra defaults are useful for smaller additional defaults that may change.
|
||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
||||
* See {@link #registerCustomDefaultsSource(String)}.
|
||||
* <p>
|
||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||
* <p>
|
||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
||||
* <pre>{@code
|
||||
* FlatLaf laf = new FlatLightLaf();
|
||||
* laf.setExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
||||
* FlatLaf.setup( laf );
|
||||
* }</pre>
|
||||
*
|
||||
* @see #setGlobalExtraDefaults(Map)
|
||||
* @since 2
|
||||
*/
|
||||
public void setExtraDefaults( Map<String, String> extraDefaults ) {
|
||||
this.extraDefaults = extraDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a UI defaults value string and converts it into a binary object.
|
||||
* <p>
|
||||
|
||||
@@ -333,6 +333,24 @@ class UIDefaultsLoader
|
||||
return null;
|
||||
}
|
||||
|
||||
// check for function "if"
|
||||
// Syntax: if(condition,trueValue,falseValue)
|
||||
// - condition: evaluates to true if:
|
||||
// - is not "null"
|
||||
// - is not "false"
|
||||
// - is not an integer with zero value
|
||||
// - trueValue: used if condition is true
|
||||
// - falseValue: used if condition is false
|
||||
if( value.startsWith( "if(" ) && value.endsWith( ")" ) ) {
|
||||
List<String> params = splitFunctionParams( value.substring( 3, value.length() - 1 ), ',' );
|
||||
if( params.size() != 3 )
|
||||
throwMissingParametersException( value );
|
||||
|
||||
boolean ifCondition = parseCondition( params.get( 0 ), resolver, addonClassLoaders );
|
||||
String ifValue = params.get( ifCondition ? 1 : 2 );
|
||||
return parseValue( key, resolver.apply( ifValue ), javaValueType, resultValueType, resolver, addonClassLoaders );
|
||||
}
|
||||
|
||||
ValueType valueType = ValueType.UNKNOWN;
|
||||
|
||||
if( javaValueType != null ) {
|
||||
@@ -479,6 +497,20 @@ class UIDefaultsLoader
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean parseCondition( String condition,
|
||||
Function<String, String> resolver, List<ClassLoader> addonClassLoaders )
|
||||
{
|
||||
try {
|
||||
Object conditionValue = parseValue( "", resolver.apply( condition ), null, null, resolver, addonClassLoaders );
|
||||
return (conditionValue != null &&
|
||||
!conditionValue.equals( false ) &&
|
||||
!conditionValue.equals( 0 ) );
|
||||
} catch( IllegalArgumentException ex ) {
|
||||
// ignore errors (e.g. variable or property not found) and evaluate to false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
||||
if( value.indexOf( ',' ) >= 0 ) {
|
||||
// top,left,bottom,right[,lineColor[,lineThickness]]
|
||||
@@ -643,7 +675,7 @@ class UIDefaultsLoader
|
||||
String function = value.substring( 0, paramsStart ).trim();
|
||||
List<String> params = splitFunctionParams( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
|
||||
if( params.isEmpty() )
|
||||
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
||||
throwMissingParametersException( value );
|
||||
|
||||
if( parseColorDepth > 100 )
|
||||
throw new IllegalArgumentException( "endless recursion in color function '" + value + "'" );
|
||||
@@ -651,6 +683,7 @@ class UIDefaultsLoader
|
||||
parseColorDepth++;
|
||||
try {
|
||||
switch( function ) {
|
||||
case "if": return parseColorIf( value, params, resolver, reportError );
|
||||
case "rgb": return parseColorRgbOrRgba( false, params, resolver, reportError );
|
||||
case "rgba": return parseColorRgbOrRgba( true, params, resolver, reportError );
|
||||
case "hsl": return parseColorHslOrHsla( false, params );
|
||||
@@ -670,6 +703,7 @@ class UIDefaultsLoader
|
||||
case "mix": return parseColorMix( null, params, resolver, reportError );
|
||||
case "tint": return parseColorMix( "#fff", params, resolver, reportError );
|
||||
case "shade": return parseColorMix( "#000", params, resolver, reportError );
|
||||
case "contrast": return parseColorContrast( params, resolver, reportError );
|
||||
}
|
||||
} finally {
|
||||
parseColorDepth--;
|
||||
@@ -678,6 +712,21 @@ class UIDefaultsLoader
|
||||
throw new IllegalArgumentException( "unknown color function '" + value + "'" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: if(condition,trueValue,falseValue)
|
||||
* <p>
|
||||
* This "if" function is only used if the "if" is passed as parameter to another
|
||||
* color function. Otherwise the general "if" function is used.
|
||||
*/
|
||||
private static Object parseColorIf( String value, List<String> params, Function<String, String> resolver, boolean reportError ) {
|
||||
if( params.size() != 3 )
|
||||
throwMissingParametersException( value );
|
||||
|
||||
boolean ifCondition = parseCondition( params.get( 0 ), resolver, Collections.emptyList() );
|
||||
String ifValue = params.get( ifCondition ? 1 : 2 );
|
||||
return parseColorOrFunction( resolver.apply( ifValue ), resolver, reportError );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha)
|
||||
* - red: an integer 0-255 or a percentage 0-100%
|
||||
@@ -863,14 +912,10 @@ class UIDefaultsLoader
|
||||
if( color1Str == null )
|
||||
color1Str = params.get( i++ );
|
||||
String color2Str = params.get( i++ );
|
||||
int weight = 50;
|
||||
|
||||
if( params.size() > i )
|
||||
weight = parsePercentage( params.get( i++ ) );
|
||||
int weight = (params.size() > i) ? parsePercentage( params.get( i ) ) : 50;
|
||||
|
||||
// parse second color
|
||||
String resolvedColor2Str = resolver.apply( color2Str );
|
||||
ColorUIResource color2 = (ColorUIResource) parseColorOrFunction( resolvedColor2Str, resolver, reportError );
|
||||
ColorUIResource color2 = (ColorUIResource) parseColorOrFunction( resolver.apply( color2Str ), resolver, reportError );
|
||||
if( color2 == null )
|
||||
return null;
|
||||
|
||||
@@ -881,6 +926,34 @@ class UIDefaultsLoader
|
||||
return parseFunctionBaseColor( color1Str, function, false, resolver, reportError );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: contrast(color,dark,light[,threshold])
|
||||
* - color: a color to compare against
|
||||
* - dark: a designated dark color (e.g. #000) or a color function
|
||||
* - light: a designated light color (e.g. #fff) or a color function
|
||||
* - threshold: the threshold (in range 0-100%) to specify where the transition
|
||||
* from "dark" to "light" is (default is 43%)
|
||||
*/
|
||||
private static Object parseColorContrast( List<String> params, Function<String, String> resolver, boolean reportError ) {
|
||||
String colorStr = params.get( 0 );
|
||||
String darkStr = params.get( 1 );
|
||||
String lightStr = params.get( 2 );
|
||||
int threshold = (params.size() > 3) ? parsePercentage( params.get( 3 ) ) : 43;
|
||||
|
||||
// parse color to compare against
|
||||
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
||||
if( color == null )
|
||||
return null;
|
||||
|
||||
// check luma and determine whether to use dark or light color
|
||||
String darkOrLightColor = (ColorFunctions.luma( color ) * 100 < threshold)
|
||||
? lightStr
|
||||
: darkStr;
|
||||
|
||||
// parse dark or light color
|
||||
return parseColorOrFunction( resolver.apply( darkOrLightColor ), resolver, reportError );
|
||||
}
|
||||
|
||||
private static Object parseFunctionBaseColor( String colorStr, ColorFunction function,
|
||||
boolean derived, Function<String, String> resolver, boolean reportError )
|
||||
{
|
||||
@@ -1071,4 +1144,8 @@ class UIDefaultsLoader
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: '" + uiKey + "' not found in UI defaults.", null );
|
||||
return value;
|
||||
}
|
||||
|
||||
private static void throwMissingParametersException( String value ) {
|
||||
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ public class ColorFunctions
|
||||
|
||||
/**
|
||||
* Returns a color that is a mixture of two colors.
|
||||
* <p>
|
||||
* This can be used to animate a color change from {@code color1} to {@code color2}
|
||||
* by invoking this method multiple times with growing {@code weight} (from 0 to 1).
|
||||
*
|
||||
* @param color1 first color
|
||||
* @param color2 second color
|
||||
@@ -79,6 +82,62 @@ public class ColorFunctions
|
||||
Math.round( a2 + ((a1 - a2) * weight) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix color with white, which makes the color brighter.
|
||||
* This is the same as {@link #mix}{@code (Color.white, color, weight)}.
|
||||
*
|
||||
* @param color second color
|
||||
* @param weight the weight (in range 0-1) to mix the two colors.
|
||||
* Larger weight uses more of first color, smaller weight more of second color.
|
||||
* @return mixture of colors
|
||||
* @since 2
|
||||
*/
|
||||
public static Color tint( Color color, float weight ) {
|
||||
return mix( Color.white, color, weight );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix color with black, which makes the color darker.
|
||||
* This is the same as {@link #mix}{@code (Color.black, color, weight)}.
|
||||
*
|
||||
* @param color second color
|
||||
* @param weight the weight (in range 0-1) to mix the two colors.
|
||||
* Larger weight uses more of first color, smaller weight more of second color.
|
||||
* @return mixture of colors
|
||||
* @since 2
|
||||
*/
|
||||
public static Color shade( Color color, float weight ) {
|
||||
return mix( Color.black, color, weight );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the luma (perceptual brightness) of the given color.
|
||||
* <p>
|
||||
* Uses SMPTE C / Rec. 709 coefficients, as recommended in
|
||||
* <a href="https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef">WCAG 2.0</a>.
|
||||
*
|
||||
* @param color a color
|
||||
* @return the luma (in range 0-1)
|
||||
*
|
||||
* @see <a href="https://en.wikipedia.org/wiki/Luma_(video)">https://en.wikipedia.org/wiki/Luma_(video)</a>
|
||||
* @since 2
|
||||
*/
|
||||
public static float luma( Color color ) {
|
||||
// see https://en.wikipedia.org/wiki/Luma_(video)
|
||||
// see https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
|
||||
// see https://github.com/less/less.js/blob/master/packages/less/src/less/tree/color.js
|
||||
float r = gammaCorrection( color.getRed() / 255f );
|
||||
float g = gammaCorrection( color.getGreen() / 255f );
|
||||
float b = gammaCorrection( color.getBlue() / 255f );
|
||||
return (0.2126f * r) + (0.7152f * g) + (0.0722f * b);
|
||||
}
|
||||
|
||||
private static float gammaCorrection( float value ) {
|
||||
return (value <= 0.03928f)
|
||||
? value / 12.92f
|
||||
: (float) Math.pow( (value + 0.055) / 1.055, 2.4 );
|
||||
}
|
||||
|
||||
//---- interface ColorFunction --------------------------------------------
|
||||
|
||||
public interface ColorFunction {
|
||||
|
||||
@@ -31,6 +31,12 @@
|
||||
# which is licensed under the Apache 2.0 license. Copyright 2000-2019 JetBrains s.r.o.
|
||||
# See: https://github.com/JetBrains/intellij-community/
|
||||
|
||||
#---- variables ----
|
||||
|
||||
# accent colors (blueish)
|
||||
@accentFocusColor = if(@accentColor, darken(@accentColor,20%), shade(spin(@accentBaseColor,-8),20%))
|
||||
|
||||
|
||||
#---- Button ----
|
||||
|
||||
Button.innerFocusWidth = 0
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
|
||||
@background = #3c3f41
|
||||
@foreground = #bbb
|
||||
@selectionBackground = #4B6EAF
|
||||
@selectionForeground = @foreground
|
||||
@selectionInactiveBackground = #0D293E
|
||||
@selectionBackground = @accentSelectionBackground
|
||||
@selectionForeground = contrast(@selectionBackground,@background,@foreground,25%)
|
||||
@selectionInactiveBackground = spin(saturate(shade(@selectionBackground,70%),20%),-15)
|
||||
@selectionInactiveForeground = @foreground
|
||||
@disabledText = #888
|
||||
@textComponentBackground = #45494A
|
||||
@@ -48,6 +48,20 @@
|
||||
@cellFocusColor = #000
|
||||
@icon = #adadad
|
||||
|
||||
# accent colors (blueish)
|
||||
# set @accentColor to use single accent color or
|
||||
# modify @accentBaseColor to use variations of accent base color
|
||||
@accentColor = null
|
||||
@accentBaseColor = #4B6EAF
|
||||
@accentBase2Color = lighten(saturate(spin(@accentBaseColor,-8),13%),5%)
|
||||
# accent color variations
|
||||
@accentFocusColor = if(@accentColor, @accentColor, shade(spin(@accentBaseColor,-8),20%))
|
||||
@accentLinkColor = if(@accentColor, @accentColor, lighten(saturate(spin(@accentBaseColor,-5),50%),16%))
|
||||
@accentSelectionBackground = if(@accentColor, @accentColor, @accentBaseColor)
|
||||
@accentSliderColor = if(@accentColor, @accentColor, @accentBase2Color)
|
||||
@accentUnderlineColor = if(@accentColor, @accentColor, @accentBase2Color)
|
||||
@accentButtonDefaultBackground = if(@accentColor, @accentColor, darken(spin(@accentBaseColor,-8),13%))
|
||||
|
||||
# for buttons within components (e.g. combobox or spinner)
|
||||
@buttonArrowColor = #9A9DA1
|
||||
@buttonDisabledArrowColor = darken(@buttonArrowColor,25%)
|
||||
@@ -79,21 +93,21 @@ Button.selectedBackground = lighten($Button.background,10%,derived)
|
||||
Button.selectedForeground = @foreground
|
||||
Button.disabledSelectedBackground = lighten($Button.background,3%,derived)
|
||||
|
||||
Button.borderColor = #5e6060
|
||||
Button.borderColor = tint($Button.background,10%)
|
||||
Button.disabledBorderColor = $Button.borderColor
|
||||
Button.focusedBorderColor = $Component.focusedBorderColor
|
||||
Button.hoverBorderColor = $Button.focusedBorderColor
|
||||
|
||||
Button.innerFocusWidth = 1
|
||||
|
||||
Button.default.background = #365880
|
||||
Button.default.foreground = #bbb
|
||||
Button.default.background = @accentButtonDefaultBackground
|
||||
Button.default.foreground = contrast($Button.default.background,@background,@foreground,25%)
|
||||
Button.default.hoverBackground = lighten($Button.default.background,3%,derived)
|
||||
Button.default.pressedBackground = lighten($Button.default.background,6%,derived)
|
||||
Button.default.borderColor = #4c708c
|
||||
Button.default.hoverBorderColor = #537699
|
||||
Button.default.focusedBorderColor = #537699
|
||||
Button.default.focusColor = #43688c
|
||||
Button.default.borderColor = tint($Button.default.background,15%)
|
||||
Button.default.hoverBorderColor = tint($Button.default.background,18%)
|
||||
Button.default.focusedBorderColor = $Button.default.hoverBorderColor
|
||||
Button.default.focusColor = lighten($Component.focusColor,3%)
|
||||
Button.default.boldText = true
|
||||
|
||||
Button.toolbar.hoverBackground = lighten($Button.background,1%,derived)
|
||||
@@ -116,7 +130,7 @@ CheckBox.icon.disabledBackground = @background
|
||||
CheckBox.icon.disabledCheckmarkColor = #606060
|
||||
|
||||
# focused
|
||||
CheckBox.icon.focusedBorderColor = #466D94
|
||||
CheckBox.icon.focusedBorderColor = $Component.focusedBorderColor
|
||||
CheckBox.icon.focusedBackground = fade($CheckBox.icon.focusedBorderColor,30%)
|
||||
|
||||
# hover
|
||||
@@ -146,10 +160,11 @@ ComboBox.buttonEditableBackground = darken($ComboBox.background,2%)
|
||||
#---- Component ----
|
||||
|
||||
Component.borderColor = #646464
|
||||
Component.disabledBorderColor = #646464
|
||||
Component.focusedBorderColor = #466d94
|
||||
Component.focusColor = #3d6185
|
||||
Component.linkColor = #589df6
|
||||
Component.disabledBorderColor = $Component.borderColor
|
||||
Component.focusedBorderColor = lighten($Component.focusColor,5%)
|
||||
Component.focusColor = @accentFocusColor
|
||||
Component.linkColor = @accentLinkColor
|
||||
Component.accentColor = if(@accentColor, @accentColor, @accentBaseColor)
|
||||
Component.grayFilter = -20,-70,100
|
||||
|
||||
Component.error.borderColor = desaturate($Component.error.focusedBorderColor,25%)
|
||||
@@ -226,9 +241,9 @@ PopupMenu.borderColor = #5e5e5e
|
||||
#---- ProgressBar ----
|
||||
|
||||
ProgressBar.background = #555
|
||||
ProgressBar.foreground = #4A88C7
|
||||
ProgressBar.selectionForeground = @foreground
|
||||
ProgressBar.foreground = @accentSliderColor
|
||||
ProgressBar.selectionBackground = @foreground
|
||||
ProgressBar.selectionForeground = contrast($ProgressBar.foreground,@background,@foreground,25%)
|
||||
|
||||
|
||||
#---- RootPane ----
|
||||
@@ -255,7 +270,7 @@ Separator.foreground = #515151
|
||||
|
||||
#---- Slider ----
|
||||
|
||||
Slider.trackValueColor = #4A88C7
|
||||
Slider.trackValueColor = @accentSliderColor
|
||||
Slider.trackColor = #646464
|
||||
Slider.thumbColor = $Slider.trackValueColor
|
||||
Slider.tickColor = #888
|
||||
@@ -273,10 +288,10 @@ SplitPaneDivider.draggingColor = #646464
|
||||
|
||||
#---- TabbedPane ----
|
||||
|
||||
TabbedPane.underlineColor = #4A88C7
|
||||
TabbedPane.underlineColor = @accentUnderlineColor
|
||||
TabbedPane.disabledUnderlineColor = #7a7a7a
|
||||
TabbedPane.hoverColor = darken($TabbedPane.background,5%,derived noAutoInverse)
|
||||
TabbedPane.focusColor = #3d4b5c
|
||||
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,25%)
|
||||
TabbedPane.contentAreaColor = #646464
|
||||
|
||||
TabbedPane.buttonHoverBackground = darken($TabbedPane.background,5%,derived noAutoInverse)
|
||||
|
||||
@@ -31,17 +31,22 @@
|
||||
# which is licensed under the Apache 2.0 license. Copyright 2000-2019 JetBrains s.r.o.
|
||||
# See: https://github.com/JetBrains/intellij-community/
|
||||
|
||||
#---- variables ----
|
||||
|
||||
# accent colors (blueish)
|
||||
@accentFocusColor = if(@accentColor, lighten(@accentColor,20%), lighten(@accentBaseColor,31%))
|
||||
@accentButtonDefaultBackground = if(@accentColor, @accentColor, tint(@accentBaseColor,15%))
|
||||
|
||||
#---- Button ----
|
||||
|
||||
Button.focusedBackground = null
|
||||
|
||||
Button.default.background = #4D8AC9
|
||||
Button.default.foreground = #fff
|
||||
Button.default.background = @accentButtonDefaultBackground
|
||||
Button.default.foreground = contrast($Button.default.background,lighten(@foreground,50%),#fff,50%)
|
||||
Button.default.focusedBackground = null
|
||||
Button.default.borderColor = #3D75B2
|
||||
Button.default.hoverBorderColor = #A9C9F5
|
||||
Button.default.focusedBorderColor = #A9C9F5
|
||||
Button.default.focusColor = #97c3f3
|
||||
Button.default.borderColor = shade($Button.default.background,15%)
|
||||
Button.default.hoverBorderColor = tint($Button.default.background,50%)
|
||||
Button.default.focusedBorderColor = $Button.default.hoverBorderColor
|
||||
Button.default.boldText = true
|
||||
Button.default.borderWidth = 1
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
|
||||
@background = #f2f2f2
|
||||
@foreground = #000
|
||||
@selectionBackground = #2675BF
|
||||
@selectionForeground = #fff
|
||||
@selectionBackground = @accentSelectionBackground
|
||||
@selectionForeground = contrast(@selectionBackground,@foreground,#fff)
|
||||
@selectionInactiveBackground = #d4d4d4
|
||||
@selectionInactiveForeground = @foreground
|
||||
@disabledText = #8C8C8C
|
||||
@@ -48,6 +48,21 @@
|
||||
@cellFocusColor = #000
|
||||
@icon = #afafaf
|
||||
|
||||
# accent colors (blueish)
|
||||
# set @accentColor to use single accent color or
|
||||
# modify @accentBaseColor to use variations of accent base color
|
||||
@accentColor = null
|
||||
@accentBaseColor = #2675BF
|
||||
@accentBase2Color = lighten(saturate(@accentBaseColor,10%),6%)
|
||||
# accent color variations
|
||||
@accentCheckmarkColor = if(@accentColor, @accentColor, tint(@accentBase2Color,20%))
|
||||
@accentFocusColor = if(@accentColor, @accentColor, lighten(@accentBaseColor,31%))
|
||||
@accentLinkColor = if(@accentColor, @accentColor, darken(@accentBaseColor,3%))
|
||||
@accentSelectionBackground = if(@accentColor, @accentColor, @accentBaseColor)
|
||||
@accentSliderColor = if(@accentColor, @accentColor, @accentBase2Color)
|
||||
@accentUnderlineColor = if(@accentColor, @accentColor, tint(@accentBaseColor,10%))
|
||||
@accentButtonDefaultBorderColor = if(@accentColor, @accentColor, tint(@accentBase2Color,20%))
|
||||
|
||||
# for buttons within components (e.g. combobox or spinner)
|
||||
@buttonArrowColor = #666
|
||||
@buttonDisabledArrowColor = lighten(@buttonArrowColor,25%)
|
||||
@@ -73,7 +88,7 @@ controlDkShadow = darken($controlShadow,15%)
|
||||
#---- Button ----
|
||||
|
||||
Button.background = #fff
|
||||
Button.focusedBackground = #e3f1fa
|
||||
Button.focusedBackground = changeLightness(@selectionBackground,95%)
|
||||
Button.hoverBackground = darken($Button.background,3%,derived)
|
||||
Button.pressedBackground = darken($Button.background,10%,derived)
|
||||
Button.selectedBackground = darken($Button.background,20%,derived)
|
||||
@@ -92,7 +107,7 @@ Button.default.foreground = @foreground
|
||||
Button.default.focusedBackground = $Button.focusedBackground
|
||||
Button.default.hoverBackground = darken($Button.default.background,3%,derived)
|
||||
Button.default.pressedBackground = darken($Button.default.background,10%,derived)
|
||||
Button.default.borderColor = #4F9EE3
|
||||
Button.default.borderColor = @accentButtonDefaultBorderColor
|
||||
Button.default.hoverBorderColor = $Button.hoverBorderColor
|
||||
Button.default.focusedBorderColor = $Button.focusedBorderColor
|
||||
Button.default.focusColor = $Component.focusColor
|
||||
@@ -110,7 +125,7 @@ CheckBox.icon.borderColor = #b0b0b0
|
||||
CheckBox.icon.background = #fff
|
||||
CheckBox.icon.selectedBorderColor = $CheckBox.icon.borderColor
|
||||
CheckBox.icon.selectedBackground = $CheckBox.icon.background
|
||||
CheckBox.icon.checkmarkColor = #4F9EE3
|
||||
CheckBox.icon.checkmarkColor = @accentCheckmarkColor
|
||||
|
||||
# disabled
|
||||
CheckBox.icon.disabledBorderColor = #BDBDBD
|
||||
@@ -118,7 +133,7 @@ CheckBox.icon.disabledBackground = @background
|
||||
CheckBox.icon.disabledCheckmarkColor = #ABABAB
|
||||
|
||||
# focused
|
||||
CheckBox.icon.focusedBorderColor = #7B9FC7
|
||||
CheckBox.icon.focusedBorderColor = shade($Component.focusedBorderColor,10%)
|
||||
CheckBox.icon.focusedBackground = $Button.focusedBackground
|
||||
|
||||
# hover
|
||||
@@ -131,11 +146,11 @@ CheckBox.icon.pressedBackground = $Button.pressedBackground
|
||||
|
||||
# used if CheckBox.icon.style = filled
|
||||
# enabled
|
||||
CheckBox.icon[filled].selectedBorderColor = #4B97D9
|
||||
CheckBox.icon[filled].selectedBackground = #4F9EE3
|
||||
CheckBox.icon[filled].selectedBorderColor = shade($CheckBox.icon[filled].selectedBackground,5%)
|
||||
CheckBox.icon[filled].selectedBackground = @accentCheckmarkColor
|
||||
CheckBox.icon[filled].checkmarkColor = #fff
|
||||
# focused
|
||||
CheckBox.icon[filled].selectedFocusedBorderColor = #ACCFF7
|
||||
CheckBox.icon[filled].selectedFocusedBorderColor = tint($CheckBox.icon[filled].selectedBackground,50%)
|
||||
CheckBox.icon[filled].selectedFocusedBackground = $CheckBox.icon[filled].selectedBackground
|
||||
CheckBox.icon[filled].selectedFocusedCheckmarkColor = $CheckBox.icon.focusedBackground
|
||||
# hover
|
||||
@@ -152,10 +167,11 @@ ComboBox.buttonEditableBackground = darken($ComboBox.background,2%)
|
||||
#---- Component ----
|
||||
|
||||
Component.borderColor = #c4c4c4
|
||||
Component.disabledBorderColor = #cfcfcf
|
||||
Component.focusedBorderColor = #87afda
|
||||
Component.focusColor = #97c3f3
|
||||
Component.linkColor = #2470B3
|
||||
Component.disabledBorderColor = lighten($Component.borderColor,4%)
|
||||
Component.focusedBorderColor = shade($Component.focusColor,10%)
|
||||
Component.focusColor = @accentFocusColor
|
||||
Component.linkColor = @accentLinkColor
|
||||
Component.accentColor = if(@accentColor, @accentColor, @accentBaseColor)
|
||||
Component.grayFilter = 25,-25,100
|
||||
|
||||
Component.error.borderColor = lighten(desaturate($Component.error.focusedBorderColor,20%),25%)
|
||||
@@ -177,7 +193,7 @@ DesktopIcon.background = darken($Desktop.background,10%,derived)
|
||||
|
||||
#---- HelpButton ----
|
||||
|
||||
HelpButton.questionMarkColor = #4F9EE3
|
||||
HelpButton.questionMarkColor = @accentCheckmarkColor
|
||||
|
||||
|
||||
#---- InternalFrame ----
|
||||
@@ -214,7 +230,7 @@ MenuBar.borderColor = #cdcdcd
|
||||
|
||||
#---- MenuItemCheckBox ----
|
||||
|
||||
MenuItemCheckBox.icon.checkmarkColor = #4F9EE3
|
||||
MenuItemCheckBox.icon.checkmarkColor = @accentCheckmarkColor
|
||||
MenuItemCheckBox.icon.disabledCheckmarkColor = #ABABAB
|
||||
|
||||
|
||||
@@ -237,9 +253,9 @@ PopupMenu.borderColor = #adadad
|
||||
#---- ProgressBar ----
|
||||
|
||||
ProgressBar.background = #D1D1D1
|
||||
ProgressBar.foreground = #1E82E6
|
||||
ProgressBar.selectionForeground = @textComponentBackground
|
||||
ProgressBar.foreground = @accentSliderColor
|
||||
ProgressBar.selectionBackground = @foreground
|
||||
ProgressBar.selectionForeground = contrast($ProgressBar.foreground,@foreground,@textComponentBackground)
|
||||
|
||||
|
||||
#---- RootPane ----
|
||||
@@ -266,7 +282,7 @@ Separator.foreground = #d1d1d1
|
||||
|
||||
#---- Slider ----
|
||||
|
||||
Slider.trackValueColor = #1E82E6
|
||||
Slider.trackValueColor = @accentSliderColor
|
||||
Slider.trackColor = #c4c4c4
|
||||
Slider.thumbColor = $Slider.trackValueColor
|
||||
Slider.tickColor = #888
|
||||
@@ -284,10 +300,10 @@ SplitPaneDivider.draggingColor = #c4c4c4
|
||||
|
||||
#---- TabbedPane ----
|
||||
|
||||
TabbedPane.underlineColor = #4083C9
|
||||
TabbedPane.underlineColor = @accentUnderlineColor
|
||||
TabbedPane.disabledUnderlineColor = #ababab
|
||||
TabbedPane.hoverColor = darken($TabbedPane.background,7%,derived)
|
||||
TabbedPane.focusColor = #dae4ed
|
||||
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,10%)
|
||||
TabbedPane.contentAreaColor = #bfbfbf
|
||||
|
||||
TabbedPane.buttonHoverBackground = darken($TabbedPane.background,7%,derived)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.awt.Color;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class TestColorFunctions
|
||||
{
|
||||
@Test
|
||||
void luma() {
|
||||
assertEquals( 0, ColorFunctions.luma( Color.black ) );
|
||||
assertEquals( 1, ColorFunctions.luma( Color.white ) );
|
||||
|
||||
assertEquals( 0.2126f, ColorFunctions.luma( Color.red ) );
|
||||
assertEquals( 0.7152f, ColorFunctions.luma( Color.green ) );
|
||||
assertEquals( 0.0722f, ColorFunctions.luma( Color.blue ) );
|
||||
|
||||
assertEquals( 0.9278f, ColorFunctions.luma( Color.yellow ) );
|
||||
assertEquals( 0.7874f, ColorFunctions.luma( Color.cyan ) );
|
||||
|
||||
assertEquals( 0.051269464f, ColorFunctions.luma( Color.darkGray ) );
|
||||
assertEquals( 0.21586052f, ColorFunctions.luma( Color.gray ) );
|
||||
assertEquals( 0.52711517f, ColorFunctions.luma( Color.lightGray ) );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user