mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-12 06:57:13 -06:00
UIDefaultsDump: dump contrast ratios
This commit is contained in:
@@ -38,6 +38,7 @@ import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -45,6 +46,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Predicate;
|
||||
import javax.swing.*;
|
||||
import javax.swing.UIDefaults.ActiveValue;
|
||||
@@ -63,6 +65,7 @@ import com.formdev.flatlaf.testing.FlatTestLaf;
|
||||
import com.formdev.flatlaf.themes.*;
|
||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
|
||||
import com.jidesoft.plaf.LookAndFeelFactory;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
@@ -181,20 +184,20 @@ public class UIDefaultsDump
|
||||
// the lazy color InternalFrame.closeHoverBackground is resolved)
|
||||
defaults = (UIDefaults) defaults.clone();
|
||||
|
||||
dump( dir, "", lookAndFeel, defaults, key -> !key.contains( "InputMap" ) );
|
||||
dump( dir, "", lookAndFeel, defaults, key -> !key.contains( "InputMap" ), true );
|
||||
|
||||
if( lookAndFeel.getClass() == FlatLightLaf.class || !(lookAndFeel instanceof FlatLaf) ) {
|
||||
dump( dir, "_InputMap", lookAndFeel, defaults, key -> key.contains( "InputMap" ) );
|
||||
dump( dir, "_InputMap", lookAndFeel, defaults, key -> key.contains( "InputMap" ), false );
|
||||
dumpActionMaps( dir, "_ActionMap", lookAndFeel, defaults );
|
||||
}
|
||||
}
|
||||
|
||||
private static void dump( File dir, String nameSuffix,
|
||||
LookAndFeel lookAndFeel, UIDefaults defaults, Predicate<String> keyFilter )
|
||||
LookAndFeel lookAndFeel, UIDefaults defaults, Predicate<String> keyFilter, boolean contrastRatios )
|
||||
{
|
||||
// dump to string
|
||||
StringWriter stringWriter = new StringWriter( 100000 );
|
||||
new UIDefaultsDump( lookAndFeel, defaults ).dump( new PrintWriter( stringWriter ), keyFilter );
|
||||
new UIDefaultsDump( lookAndFeel, defaults ).dump( new PrintWriter( stringWriter ), keyFilter, contrastRatios );
|
||||
|
||||
String name = lookAndFeel instanceof MyBasicLookAndFeel
|
||||
? BasicLookAndFeel.class.getSimpleName()
|
||||
@@ -354,12 +357,15 @@ public class UIDefaultsDump
|
||||
Map<String, String> defaults = new LinkedHashMap<>();
|
||||
try( BufferedReader reader = new BufferedReader( in ) ) {
|
||||
String lastKey = null;
|
||||
boolean inContrastRatios = false;
|
||||
|
||||
String line;
|
||||
while( (line = reader.readLine()) != null ) {
|
||||
String trimmedLine = line.trim();
|
||||
if( trimmedLine.isEmpty() || trimmedLine.startsWith( "#" ) ) {
|
||||
lastKey = null;
|
||||
if( trimmedLine.contains( "#-------- Contrast Ratios --------" ) )
|
||||
inContrastRatios = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -374,6 +380,8 @@ public class UIDefaultsDump
|
||||
|
||||
String key = line.substring( 0, sep );
|
||||
String value = line.substring( sep );
|
||||
if( inContrastRatios )
|
||||
key = "contrast ratio: " + key;
|
||||
defaults.put( key, value );
|
||||
|
||||
lastKey = key;
|
||||
@@ -403,7 +411,7 @@ public class UIDefaultsDump
|
||||
out.printf( "OS %s%n", System.getProperty( "os.name" ) );
|
||||
}
|
||||
|
||||
private void dump( PrintWriter out, Predicate<String> keyFilter ) {
|
||||
private void dump( PrintWriter out, Predicate<String> keyFilter, boolean contrastRatios ) {
|
||||
dumpHeader( out );
|
||||
|
||||
defaults.entrySet().stream()
|
||||
@@ -428,6 +436,9 @@ public class UIDefaultsDump
|
||||
dumpValue( out, strKey, value );
|
||||
out.println();
|
||||
} );
|
||||
|
||||
if( contrastRatios )
|
||||
dumpContrastRatios( out );
|
||||
}
|
||||
|
||||
private void dumpActionMaps( PrintWriter out ) {
|
||||
@@ -829,6 +840,124 @@ public class UIDefaultsDump
|
||||
return new Color( newColor.getRGB(), true );
|
||||
}
|
||||
|
||||
private void dumpContrastRatios( PrintWriter out ) {
|
||||
out.printf( "%n%n#-------- Contrast Ratios --------%n%n" );
|
||||
out.println( "# WCAG 2 Contrast Requirements: minimum 4.5; enhanced 7.0" );
|
||||
out.println( "# https://webaim.org/articles/contrast/#sc143" );
|
||||
out.println();
|
||||
|
||||
HashMap<String, String> fg2bgMap = new HashMap<>();
|
||||
defaults.keySet().stream()
|
||||
.filter( key -> key instanceof String && ((String)key).endsWith( "ackground" ) )
|
||||
.map( key -> (String) key )
|
||||
.forEach( bgKey -> {
|
||||
String fgKey = bgKey.replace( "Background", "Foreground" ).replace( "background", "foreground" );
|
||||
fg2bgMap.put( fgKey, bgKey );
|
||||
} );
|
||||
|
||||
// special cases
|
||||
fg2bgMap.remove( "Button.disabledForeground" );
|
||||
fg2bgMap.put( "Button.disabledText", "Button.disabledBackground" );
|
||||
fg2bgMap.remove( "ToggleButton.disabledForeground" );
|
||||
fg2bgMap.put( "ToggleButton.disabledText", "ToggleButton.disabledBackground" );
|
||||
fg2bgMap.put( "CheckBox.foreground", "Panel.background" );
|
||||
fg2bgMap.put( "CheckBox.disabledText", "Panel.background" );
|
||||
fg2bgMap.put( "Label.foreground", "Panel.background" );
|
||||
fg2bgMap.put( "Label.disabledForeground", "Panel.background" );
|
||||
fg2bgMap.remove( "ProgressBar.foreground" );
|
||||
fg2bgMap.put( "ProgressBar.selectionForeground", "ProgressBar.foreground" );
|
||||
fg2bgMap.put( "ProgressBar.selectionBackground", "ProgressBar.background" );
|
||||
fg2bgMap.put( "RadioButton.foreground", "Panel.background" );
|
||||
fg2bgMap.put( "RadioButton.disabledText", "Panel.background" );
|
||||
fg2bgMap.remove( "ScrollBar.foreground" );
|
||||
fg2bgMap.remove( "ScrollBar.hoverButtonForeground" );
|
||||
fg2bgMap.remove( "ScrollBar.pressedButtonForeground" );
|
||||
fg2bgMap.remove( "ScrollPane.foreground" );
|
||||
fg2bgMap.remove( "Separator.foreground" );
|
||||
fg2bgMap.remove( "Slider.foreground" );
|
||||
fg2bgMap.remove( "SplitPane.foreground" );
|
||||
fg2bgMap.remove( "TextArea.disabledForeground" );
|
||||
fg2bgMap.put( "TextArea.inactiveForeground", "TextArea.disabledBackground" );
|
||||
fg2bgMap.remove( "TextPane.disabledForeground" );
|
||||
fg2bgMap.put( "TextPane.inactiveForeground", "TextPane.disabledBackground" );
|
||||
fg2bgMap.remove( "EditorPane.disabledForeground" );
|
||||
fg2bgMap.put( "EditorPane.inactiveForeground", "EditorPane.disabledBackground" );
|
||||
fg2bgMap.remove( "TextField.disabledForeground" );
|
||||
fg2bgMap.put( "TextField.inactiveForeground", "TextField.disabledBackground" );
|
||||
fg2bgMap.remove( "FormattedTextField.disabledForeground" );
|
||||
fg2bgMap.put( "FormattedTextField.inactiveForeground", "FormattedTextField.disabledBackground" );
|
||||
fg2bgMap.remove( "PasswordField.disabledForeground" );
|
||||
fg2bgMap.put( "PasswordField.inactiveForeground", "PasswordField.disabledBackground" );
|
||||
fg2bgMap.remove( "ToolBar.dockingForeground" );
|
||||
fg2bgMap.remove( "ToolBar.floatingForeground" );
|
||||
fg2bgMap.remove( "ToolBar.foreground" );
|
||||
fg2bgMap.remove( "ToolBar.hoverButtonGroupForeground" );
|
||||
fg2bgMap.remove( "Viewport.foreground" );
|
||||
|
||||
fg2bgMap.remove( "InternalFrame.closeHoverForeground" );
|
||||
fg2bgMap.remove( "InternalFrame.closePressedForeground" );
|
||||
fg2bgMap.remove( "TabbedPane.closeHoverForeground" );
|
||||
fg2bgMap.remove( "TabbedPane.closePressedForeground" );
|
||||
fg2bgMap.remove( "TitlePane.closeHoverForeground" );
|
||||
fg2bgMap.remove( "TitlePane.closePressedForeground" );
|
||||
|
||||
// out.println();
|
||||
// fg2bgMap.entrySet().stream()
|
||||
// .sorted( (e1, e2) -> e1.getKey().compareTo( e2.getKey() ) )
|
||||
// .forEach( e -> {
|
||||
// out.printf( "%-50s %s%n", e.getKey(), e.getValue() );
|
||||
// } );
|
||||
// out.println();
|
||||
|
||||
AtomicReference<String> lastSubkey = new AtomicReference<>();
|
||||
|
||||
fg2bgMap.entrySet().stream()
|
||||
.sorted( (e1, e2) -> {
|
||||
String key1 = e1.getKey();
|
||||
String key2 = e2.getKey();
|
||||
int dot1 = key1.lastIndexOf( '.' );
|
||||
int dot2 = key2.lastIndexOf( '.' );
|
||||
if( dot1 < 0 || dot2 < 0 )
|
||||
return key1.compareTo( key2 );
|
||||
int r = key1.substring( dot1 + 1 ).compareTo( key2.substring( dot2 + 1 ) );
|
||||
if( r != 0 )
|
||||
return r;
|
||||
return key1.substring( 0, dot1 ).compareTo( key2.substring( 0, dot2 ) );
|
||||
} )
|
||||
.forEach( e -> {
|
||||
String fgKey = e.getKey();
|
||||
String bgKey = e.getValue();
|
||||
Color background = defaults.getColor( bgKey );
|
||||
Color foreground = defaults.getColor( fgKey );
|
||||
if( background != null && foreground != null ) {
|
||||
float luma1 = ColorFunctions.luma( background );
|
||||
float luma2 = ColorFunctions.luma( foreground );
|
||||
float contrastRatio = (luma1 > luma2)
|
||||
? (luma1 + 0.05f) / (luma2 + 0.05f)
|
||||
: (luma2 + 0.05f) / (luma1 + 0.05f);
|
||||
String rateing =
|
||||
contrastRatio < 1.95f ? " !!!!!!" :
|
||||
contrastRatio < 2.95f ? " !!!!!" :
|
||||
contrastRatio < 3.95f ? " !!!!" :
|
||||
contrastRatio < 4.95f ? " !!!" :
|
||||
contrastRatio < 5.95f ? " !!" :
|
||||
contrastRatio < 6.95f ? " !" :
|
||||
"";
|
||||
|
||||
String subkey = fgKey.substring( fgKey.lastIndexOf( '.' ) + 1 );
|
||||
if( !subkey.equals( lastSubkey.get() ) ) {
|
||||
lastSubkey.set( subkey );
|
||||
out.println();
|
||||
out.println( "#-- " + subkey + " --" );
|
||||
}
|
||||
|
||||
out.printf( "%-50s #%06x #%06x %4.1f%s%n", fgKey,
|
||||
foreground.getRGB() & 0xffffff, background.getRGB() & 0xffffff,
|
||||
contrastRatio, rateing );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
//---- class MyBasicLookAndFeel -------------------------------------------
|
||||
|
||||
public static class MyBasicLookAndFeel
|
||||
|
||||
Reference in New Issue
Block a user