diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cc606f1..49500fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,9 @@ FlatLaf Change Log - Extras: `FlatSVGIcon` color filters now can access painting component to implement component state based color mappings. (issue #906) - Linux: Added `libflatlaf-linux-arm64.so` for Linux on ARM64. (issue #899) -- IntelliJ Themes: Updated to latest versions. +- IntelliJ Themes: + - Updated to latest versions and fixed various issues. + - Support customizing through properties files. (issue #824) #### Fixed bugs 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 dec465d1..803783fe 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java @@ -521,10 +521,10 @@ public abstract class FlatLaf // load defaults from properties List> lafClassesForDefaultsLoading = getLafClassesForDefaultsLoading(); - if( lafClassesForDefaultsLoading != null ) - UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, getAdditionalDefaults(), isDark(), defaults ); - else - UIDefaultsLoader.loadDefaultsFromProperties( getClass(), addons, getAdditionalDefaults(), isDark(), defaults ); + if( lafClassesForDefaultsLoading == null ) + lafClassesForDefaultsLoading = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() ); + UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, + this::applyAdditionalProperties, getAdditionalDefaults(), isDark(), defaults ); // setup default font after loading defaults from properties // to allow defining "defaultFont" in properties @@ -541,9 +541,6 @@ public abstract class FlatLaf // initialize text antialiasing putAATextInfo( defaults ); - // apply additional defaults (e.g. from IntelliJ themes) - applyAdditionalDefaults( defaults ); - // allow addons modifying UI defaults for( FlatDefaultsAddon addon : addons ) addon.afterDefaultsLoading( this, defaults ); @@ -564,7 +561,8 @@ public abstract class FlatLaf return defaults; } - void applyAdditionalDefaults( UIDefaults defaults ) { + // apply additional properties (e.g. from IntelliJ themes) + void applyAdditionalProperties( Properties properties ) { } protected List> getLafClassesForDefaultsLoading() { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/IntelliJTheme.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/IntelliJTheme.java index 5be0c5c0..d352d728 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/IntelliJTheme.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/IntelliJTheme.java @@ -16,7 +16,6 @@ package com.formdev.flatlaf; -import java.awt.Color; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -25,20 +24,16 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; -import java.util.Map.Entry; -import javax.swing.UIDefaults; -import javax.swing.plaf.ColorUIResource; import com.formdev.flatlaf.json.Json; import com.formdev.flatlaf.json.ParseException; -import com.formdev.flatlaf.util.ColorFunctions; import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.StringUtils; import com.formdev.flatlaf.util.SystemInfo; @@ -63,13 +58,11 @@ public class IntelliJTheme public final boolean dark; public final String author; - private final boolean isMaterialUILite; + private Map jsonColors; + private Map jsonUI; + private Map jsonIcons; - private Map colors; - private Map ui; - private Map icons; - - private Map namedColors = Collections.emptyMap(); + private Map namedColors = Collections.emptyMap(); /** * Loads a IntelliJ .theme.json file from the given input stream, @@ -84,7 +77,7 @@ public class IntelliJTheme try { return FlatLaf.setup( createLaf( in ) ); } catch( Exception ex ) { - LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load IntelliJ theme", ex ); + LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load IntelliJ theme", ex ); return false; } } @@ -138,94 +131,90 @@ public class IntelliJTheme dark = Boolean.parseBoolean( (String) json.get( "dark" ) ); author = (String) json.get( "author" ); - isMaterialUILite = author.equals( "Mallowigi" ); - - colors = (Map) json.get( "colors" ); - ui = (Map) json.get( "ui" ); - icons = (Map) json.get( "icons" ); + jsonColors = (Map) json.get( "colors" ); + jsonUI = (Map) json.get( "ui" ); + jsonIcons = (Map) json.get( "icons" ); } - private void applyProperties( UIDefaults defaults ) { - if( ui == null ) + private void applyProperties( Properties properties ) { + if( jsonUI == null ) return; - defaults.put( "Component.isIntelliJTheme", true ); + put( properties, "Component.isIntelliJTheme", "true" ); // enable button shadows - defaults.put( "Button.paintShadow", true ); - defaults.put( "Button.shadowWidth", dark ? 2 : 1 ); + put( properties, "Button.paintShadow", "true" ); + put( properties, "Button.shadowWidth", dark ? "2" : "1" ); - Map themeSpecificDefaults = removeThemeSpecificDefaults( defaults ); + Map themeSpecificProps = removeThemeSpecificProps( properties ); + Set jsonUIKeys = new HashSet<>(); - loadNamedColors( defaults ); + // Json node "colors" + loadNamedColors( properties, jsonUIKeys ); - // convert Json "ui" structure to UI defaults - ArrayList defaultsKeysCache = new ArrayList<>(); - Set uiKeys = new HashSet<>(); - for( Map.Entry e : ui.entrySet() ) - apply( e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys ); + // convert Json "ui" structure to UI properties + for( Map.Entry e : jsonUI.entrySet() ) + apply( e.getKey(), e.getValue(), properties, jsonUIKeys ); - applyColorPalette( defaults ); - applyCheckBoxColors( defaults ); + // set FlatLaf variables + copyIfSetInJson( properties, jsonUIKeys, "@background", "Panel.background", "*.background" ); + copyIfSetInJson( properties, jsonUIKeys, "@foreground", "CheckBox.foreground", "*.foreground" ); + copyIfSetInJson( properties, jsonUIKeys, "@accentBaseColor", + "ColorPalette.accent", // Material UI Lite, Hiberbee + "ColorPalette.accentColor", // Dracula, One Dark + "ProgressBar.foreground", + "*.selectionBackground" ); + copyIfSetInJson( properties, jsonUIKeys, "@accentUnderlineColor", "*.underlineColor", "TabbedPane.underlineColor" ); + copyIfSetInJson( properties, jsonUIKeys, "@selectionBackground", "*.selectionBackground" ); + copyIfSetInJson( properties, jsonUIKeys, "@selectionForeground", "*.selectionForeground" ); + copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveBackground", "*.selectionInactiveBackground" ); + copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveForeground", "*.selectionInactiveForeground" ); + + // Json node "icons/ColorPalette" + applyIconsColorPalette( properties ); + + // apply "CheckBox.icon." colors + applyCheckBoxColors( properties ); // copy values for( Map.Entry e : uiKeyCopying.entrySet() ) { - Object value = defaults.get( e.getValue() ); + Object value = properties.get( e.getValue() ); if( value != null ) - defaults.put( e.getKey(), value ); + put( properties, e.getKey(), value ); } // IDEA does not paint button background if disabled, but FlatLaf does - Object panelBackground = defaults.get( "Panel.background" ); - defaults.put( "Button.disabledBackground", panelBackground ); - defaults.put( "ToggleButton.disabledBackground", panelBackground ); + put( properties, "Button.disabledBackground", "@disabledBackground" ); + put( properties, "ToggleButton.disabledBackground", "@disabledBackground" ); - // fix Button borders - copyIfNotSet( defaults, "Button.focusedBorderColor", "Component.focusedBorderColor", uiKeys ); - defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) ); - defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) ); - - // IDEA uses an SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground - Object helpButtonBackground = defaults.get( "Button.startBackground" ); - Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" ); - if( helpButtonBackground == null ) - helpButtonBackground = defaults.get( "Button.background" ); - if( helpButtonBorderColor == null ) - helpButtonBorderColor = defaults.get( "Button.borderColor" ); - defaults.put( "HelpButton.background", helpButtonBackground ); - defaults.put( "HelpButton.borderColor", helpButtonBorderColor ); - defaults.put( "HelpButton.disabledBackground", panelBackground ); - defaults.put( "HelpButton.disabledBorderColor", defaults.get( "Button.disabledBorderColor" ) ); - defaults.put( "HelpButton.focusedBorderColor", defaults.get( "Button.focusedBorderColor" ) ); - defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) ); + // fix Button + fixStartEnd( properties, jsonUIKeys, "Button.startBackground", "Button.endBackground", "Button.background" ); + fixStartEnd( properties, jsonUIKeys, "Button.startBorderColor", "Button.endBorderColor", "Button.borderColor" ); + fixStartEnd( properties, jsonUIKeys, "Button.default.startBackground", "Button.default.endBackground", "Button.default.background" ); + fixStartEnd( properties, jsonUIKeys, "Button.default.startBorderColor", "Button.default.endBorderColor", "Button.default.borderColor" ); // IDEA uses TextField.background for editable ComboBox and Spinner - Object textFieldBackground = get( defaults, themeSpecificDefaults, "TextField.background" ); - defaults.put( "ComboBox.editableBackground", textFieldBackground ); - defaults.put( "Spinner.background", textFieldBackground ); - - // Spinner arrow button always has same colors as ComboBox arrow button - defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) ); - defaults.put( "Spinner.buttonArrowColor", defaults.get( "ComboBox.buttonArrowColor" ) ); - defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) ); + Object textFieldBackground = get( properties, themeSpecificProps, "TextField.background" ); + put( properties, "ComboBox.editableBackground", textFieldBackground ); + put( properties, "Spinner.background", textFieldBackground ); // some themes specify colors for TextField.background, but forget to specify it for other components // (probably because those components are not used in IntelliJ IDEA) - putAll( defaults, textFieldBackground, + putAll( properties, textFieldBackground, "EditorPane.background", "FormattedTextField.background", "PasswordField.background", "TextArea.background", "TextPane.background" ); - putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionBackground" ), + putAll( properties, get( properties, themeSpecificProps, "TextField.selectionBackground" ), "EditorPane.selectionBackground", "FormattedTextField.selectionBackground", "PasswordField.selectionBackground", "TextArea.selectionBackground", "TextPane.selectionBackground" ); - putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionForeground" ), + putAll( properties, get( properties, themeSpecificProps, "TextField.selectionForeground" ), "EditorPane.selectionForeground", "FormattedTextField.selectionForeground", "PasswordField.selectionForeground", @@ -235,7 +224,7 @@ public class IntelliJTheme // fix disabled and not-editable backgrounds for text components, combobox and spinner // (IntelliJ IDEA does not use those colors; instead it used background color of parent) - putAll( defaults, panelBackground, + putAll( properties, "@disabledBackground", "ComboBox.disabledBackground", "EditorPane.disabledBackground", "EditorPane.inactiveBackground", "FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground", @@ -246,132 +235,148 @@ public class IntelliJTheme "TextPane.disabledBackground", "TextPane.inactiveBackground" ); - // fix ToggleButton - if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) ) - defaults.put( "ToggleButton.startBackground", defaults.get( "Button.startBackground" ) ); - if( !uiKeys.contains( "ToggleButton.endBackground" ) && !uiKeys.contains( "*.endBackground" ) ) - defaults.put( "ToggleButton.endBackground", defaults.get( "Button.endBackground" ) ); - if( !uiKeys.contains( "ToggleButton.foreground" ) && uiKeys.contains( "Button.foreground" ) ) - defaults.put( "ToggleButton.foreground", defaults.get( "Button.foreground" ) ); - // fix DesktopPane background (use Panel.background and make it 5% darker/lighter) - Color desktopBackgroundBase = defaults.getColor( "Panel.background" ); - Color desktopBackground = ColorFunctions.applyFunctions( desktopBackgroundBase, - new ColorFunctions.HSLIncreaseDecrease( 2, dark, 5, false, true ) ); - defaults.put( "Desktop.background", new ColorUIResource( desktopBackground ) ); - - // fix List and Table background colors in Material UI Lite themes - if( isMaterialUILite ) { - defaults.put( "List.background", defaults.get( "Tree.background" ) ); - defaults.put( "Table.background", defaults.get( "Tree.background" ) ); - } + put( properties, "Desktop.background", dark ? "lighten($Panel.background,5%)" : "darken($Panel.background,5%)" ); // limit tree row height - int rowHeight = defaults.getInt( "Tree.rowHeight" ); + String rowHeightStr = (String) properties.get( "Tree.rowHeight" ); + int rowHeight = (rowHeightStr != null) ? Integer.parseInt( rowHeightStr ) : 0; if( rowHeight > 22 ) - defaults.put( "Tree.rowHeight", 22 ); + put( properties, "Tree.rowHeight", "22" ); - // get (and remove) theme specific wildcard replacements, which override all other defaults that end with same suffix - HashMap wildcards = new HashMap<>(); - Iterator> it = themeSpecificDefaults.entrySet().iterator(); + // get (and remove) theme specific wildcard replacements, which override all other properties that end with same suffix + HashMap wildcardProps = new HashMap<>(); + Iterator> it = themeSpecificProps.entrySet().iterator(); while( it.hasNext() ) { - Entry e = it.next(); - String key = (String) e.getKey(); + Map.Entry e = it.next(); + String key = e.getKey(); if( key.startsWith( "*." ) ) { - wildcards.put( key.substring( "*.".length() ), e.getValue() ); + wildcardProps.put( key, e.getValue() ); it.remove(); } } - // override UI defaults with theme specific wildcard replacements - if( !wildcards.isEmpty() ) { - for( Object key : defaults.keySet().toArray() ) { - int dot; - if( !(key instanceof String) || - (dot = ((String)key).lastIndexOf( '.' )) < 0 ) - continue; - - String wildcardKey = ((String)key).substring( dot + 1 ); - Object wildcardValue = wildcards.get( wildcardKey ); - if( wildcardValue != null ) - defaults.put( key, wildcardValue ); - } + // override properties with theme specific wildcard replacements + if( !wildcardProps.isEmpty() ) { + for( Map.Entry e : wildcardProps.entrySet() ) + applyWildcard( properties, e.getKey(), e.getValue() ); } - // apply theme specific UI defaults at the end to allow overwriting - for( Map.Entry e : themeSpecificDefaults.entrySet() ) { - Object key = e.getKey(); - Object value = e.getValue(); + // apply theme specific properties at the end to allow overwriting + for( Map.Entry e : themeSpecificProps.entrySet() ) { + String key = e.getKey(); + String value = e.getValue(); // append styles to existing styles - if( key instanceof String && ((String)key).startsWith( "[style]" ) ) { - Object oldValue = defaults.get( key ); + if( key.startsWith( "[style]" ) ) { + String oldValue = (String) properties.get( key ); if( oldValue != null ) value = oldValue + "; " + value; } - defaults.put( key, value ); + put( properties, key, value ); } // let Java release memory - colors = null; - ui = null; - icons = null; + jsonColors = null; + jsonUI = null; + jsonIcons = null; } - private Object get( UIDefaults defaults, Map themeSpecificDefaults, String key ) { - return themeSpecificDefaults.getOrDefault( key, defaults.get( key ) ); + private String get( Properties properties, Map themeSpecificProps, String key ) { + return themeSpecificProps.getOrDefault( key, (String) properties.get( key ) ); } - private void putAll( UIDefaults defaults, Object value, String... keys ) { + private void put( Properties properties, Object key, Object value ) { + if( value != null ) + properties.put( key, value ); + else + properties.remove( key ); + } + + private void putAll( Properties properties, Object value, String... keys ) { for( String key : keys ) - defaults.put( key, value ); + put( properties, key, value ); } - private Map removeThemeSpecificDefaults( UIDefaults defaults ) { - // search for theme specific UI defaults keys + private void copyIfSetInJson( Properties properties, Set jsonUIKeys, String destKey, String... srcKeys ) { + for( String srcKey : srcKeys ) { + if( jsonUIKeys.contains( srcKey ) ) { + Object value = properties.get( srcKey ); + if( value != null ) { + put( properties, destKey, value ); + break; + } + } + } + } + + private void fixStartEnd( Properties properties, Set jsonUIKeys, String startKey, String endKey, String key ) { + if( jsonUIKeys.contains( startKey ) && jsonUIKeys.contains( endKey ) ) + put( properties, key, "$" + startKey ); + } + + private Map removeThemeSpecificProps( Properties properties ) { + // search for theme specific properties keys ArrayList themeSpecificKeys = new ArrayList<>(); - for( Object key : defaults.keySet() ) { - if( key instanceof String && ((String)key).startsWith( "{" ) ) + for( Object key : properties.keySet() ) { + if( ((String)key).startsWith( "{" ) ) themeSpecificKeys.add( (String) key ); } - // remove theme specific UI defaults and remember only those for current theme - Map themeSpecificDefaults = new HashMap<>(); + // special prefixes (priority from highest to lowest) String currentThemePrefix = '{' + name.replace( ' ', '_' ) + '}'; String currentThemeAndAuthorPrefix = '{' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + '}'; String currentAuthorPrefix = "{author-" + author.replace( ' ', '_' ) + '}'; + String lightOrDarkPrefix = dark ? "{*-dark}" : "{*-light}"; String allThemesPrefix = "{*}"; - String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, allThemesPrefix }; + String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, lightOrDarkPrefix, allThemesPrefix }; + + // collect values for special prefixes in its own maps + @SuppressWarnings( "unchecked" ) + Map[] maps = new Map[prefixes.length]; + for( int i = 0; i < maps.length; i++ ) + maps[i] = new HashMap<>(); + + // remove theme specific properties and remember only those for current theme for( String key : themeSpecificKeys ) { - Object value = defaults.remove( key ); - for( String prefix : prefixes ) { + String value = (String) properties.remove( key ); + for( int i = 0; i < prefixes.length; i++ ) { + String prefix = prefixes[i]; if( key.startsWith( prefix ) ) { - themeSpecificDefaults.put( key.substring( prefix.length() ), value ); + maps[i].put( key.substring( prefix.length() ), value ); break; } } } - return themeSpecificDefaults; + // copy values into single map (from lowest to highest priority) + Map themeSpecificProps = new HashMap<>(); + for( int i = maps.length - 1; i >= 0; i-- ) + themeSpecificProps.putAll( maps[i] ); + return themeSpecificProps; } /** * http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#defining-named-colors */ - private void loadNamedColors( UIDefaults defaults ) { - if( colors == null ) + private void loadNamedColors( Properties properties, Set jsonUIKeys ) { + if( jsonColors == null ) return; namedColors = new HashMap<>(); - for( Map.Entry e : colors.entrySet() ) { + for( Map.Entry e : jsonColors.entrySet() ) { String value = e.getValue(); - ColorUIResource color = parseColor( value ); - if( color != null ) { + if( canParseColor( value ) ) { String key = e.getKey(); - namedColors.put( key, color ); - defaults.put( "ColorPalette." + key, color ); + namedColors.put( key, value ); + + String uiKey = "ColorPalette." + key; + put( properties, uiKey, value ); + + // this is only necessary for copyIfSetInJson() (used for accent color) + jsonUIKeys.add( uiKey ); } } } @@ -380,7 +385,7 @@ public class IntelliJTheme * http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#custom-ui-control-colors */ @SuppressWarnings( "unchecked" ) - private void apply( String key, Object value, UIDefaults defaults, ArrayList defaultsKeysCache, Set uiKeys ) { + private void apply( String key, Object value, Properties properties, Set jsonUIKeys ) { if( value instanceof Map ) { Map map = (Map)value; if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) { @@ -388,12 +393,12 @@ public class IntelliJTheme : SystemInfo.isMacOS ? "os.mac" : SystemInfo.isLinux ? "os.linux" : null; if( osKey != null && map.containsKey( osKey ) ) - apply( key, map.get( osKey ), defaults, defaultsKeysCache, uiKeys ); + apply( key, map.get( osKey ), properties, jsonUIKeys ); else if( map.containsKey( "os.default" ) ) - apply( key, map.get( "os.default" ), defaults, defaultsKeysCache, uiKeys ); + apply( key, map.get( "os.default" ), properties, jsonUIKeys ); } else { for( Map.Entry e : map.entrySet() ) - apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys ); + apply( key + '.' + e.getKey(), e.getValue(), properties, jsonUIKeys ); } } else { if( "".equals( value ) ) @@ -418,15 +423,15 @@ public class IntelliJTheme if( dot > 0 && uiKeyExcludes.contains( key.substring( 0, dot + 1 ) ) ) return; - if( uiKeyDoNotOverride.contains( key ) && uiKeys.contains( key ) ) + if( uiKeyDoNotOverride.contains( key ) && jsonUIKeys.contains( key ) ) return; - uiKeys.add( key ); + jsonUIKeys.add( key ); String valueStr = value.toString(); // map named colors - Object uiValue = namedColors.get( valueStr ); + String uiValue = namedColors.get( valueStr ); // parse value if( uiValue == null ) { @@ -445,47 +450,64 @@ public class IntelliJTheme // parse value try { - uiValue = UIDefaultsLoader.parseValue( key, valueStr, null ); + UIDefaultsLoader.parseValue( key, valueStr, null ); + uiValue = valueStr; } catch( RuntimeException ex ) { - UIDefaultsLoader.logParseError( key, valueStr, ex, false ); + UIDefaultsLoader.logParseError( key, valueStr, ex, true ); return; // ignore invalid value } } - if( key.startsWith( "*." ) ) { - // wildcard - String tail = key.substring( 1 ); + // wildcards + if( applyWildcard( properties, key, uiValue ) ) + return; - // because we can not iterate over the UI defaults keys while - // modifying UI defaults in the same loop, we have to copy the keys - if( defaultsKeysCache.size() != defaults.size() ) { - defaultsKeysCache.clear(); - Enumeration e = defaults.keys(); - while( e.hasMoreElements() ) - defaultsKeysCache.add( e.nextElement() ); - } - - // replace all values in UI defaults that match the wildcard key - for( Object k : defaultsKeysCache ) { - if( k.equals( "Desktop.background" ) || - k.equals( "DesktopIcon.background" ) || - k.equals( "TabbedPane.focusColor" ) ) - continue; - - if( k instanceof String ) { - // support replacing of mapped keys - // (e.g. set ComboBox.buttonEditableBackground to *.background - // because it is mapped from ComboBox.ArrowButton.background) - String km = uiKeyInverseMapping.getOrDefault( k, (String) k ); - if( km.endsWith( tail ) && !((String)k).startsWith( "CheckBox.icon." ) ) - defaults.put( k, uiValue ); - } - } - } else - defaults.put( key, uiValue ); + put( properties, key, uiValue ); } } + private boolean applyWildcard( Properties properties, String key, String value ) { + if( !key.startsWith( "*." ) ) + return false; + + String tail = key.substring( 1 ); + + // because we can not iterate over the properties keys while + // modifying properties in the same loop, we have to copy the keys + String[] keys = properties.keySet().toArray( new String[properties.size()] ); + + // replace all values in properties that match the wildcard key + for( String k : keys ) { + if( k.startsWith( "*" ) || + k.startsWith( "@" ) || + k.startsWith( "HelpButton." ) || + k.startsWith( "JX" ) || + k.startsWith( "Jide" ) || + k.startsWith( "ProgressBar.selection" ) || + k.startsWith( "TitlePane." ) || + k.startsWith( "ToggleButton.tab." ) || + k.equals( "Desktop.background" ) || + k.equals( "DesktopIcon.background" ) || + k.equals( "TabbedPane.focusColor" ) || + k.endsWith( ".hoverBackground" ) || + k.endsWith( ".pressedBackground" ) ) + continue; + + // support replacing of mapped keys + // (e.g. set ComboBox.buttonEditableBackground to *.background + // because it is mapped from ComboBox.ArrowButton.background) + String km = uiKeyInverseMapping.getOrDefault( k, k ); + if( km.endsWith( tail ) && !k.startsWith( "CheckBox.icon." ) ) + put( properties, k, value ); + } + + // Note: also add wildcards to properties and let UIDefaultsLoader + // process it on BasicLookAndFeel UI defaults + put( properties, key, value ); + + return true; + } + private String fixColorIfValid( String newColorStr, String colorStr ) { try { // check whether it is valid @@ -497,11 +519,11 @@ public class IntelliJTheme } } - private void applyColorPalette( UIDefaults defaults ) { - if( icons == null ) + private void applyIconsColorPalette( Properties properties ) { + if( jsonIcons == null ) return; - Object palette = icons.get( "ColorPalette" ); + Object palette = jsonIcons.get( "ColorPalette" ); if( !(palette instanceof Map) ) return; @@ -510,44 +532,48 @@ public class IntelliJTheme for( Map.Entry e : colorPalette.entrySet() ) { String key = e.getKey(); Object value = e.getValue(); - if( key.startsWith( "Checkbox." ) || !(value instanceof String) ) + if( key.startsWith( "Checkbox." ) || key.startsWith( "#" ) || !(value instanceof String) ) continue; if( dark ) key = StringUtils.removeTrailing( key, ".Dark" ); - ColorUIResource color = toColor( (String) value ); + String color = toColor( (String) value ); if( color != null ) - defaults.put( key, color ); + put( properties, key, color ); } } - private ColorUIResource toColor( String value ) { + private String toColor( String value ) { + if( value.startsWith( "##" ) ) + value = fixColorIfValid( value.substring( 1 ), value ); + // map named colors - ColorUIResource color = namedColors.get( value ); + String color = namedColors.get( value ); // parse color - return (color != null) ? color : parseColor( value ); + return (color != null) ? color : (canParseColor( value ) ? value : null); } - private ColorUIResource parseColor( String value ) { + private boolean canParseColor( String value ) { try { - return UIDefaultsLoader.parseColor( value ); + return UIDefaultsLoader.parseColor( value ) != null; } catch( IllegalArgumentException ex ) { - return null; + LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to parse color: '" + value + '\'', ex ); + return false; } } /** * Because IDEA uses SVGs for check boxes and radio buttons, the colors for * these two components are specified in "icons > ColorPalette". - * FlatLaf uses vector icons and expects colors for the two components in UI defaults. + * FlatLaf uses vector icons and expects colors for the two components in properties. */ - private void applyCheckBoxColors( UIDefaults defaults ) { - if( icons == null ) + private void applyCheckBoxColors( Properties properties ) { + if( jsonIcons == null ) return; - Object palette = icons.get( "ColorPalette" ); + Object palette = jsonIcons.get( "ColorPalette" ); if( !(palette instanceof Map) ) return; @@ -569,9 +595,9 @@ public class IntelliJTheme if( !dark && newKey.startsWith( checkBoxIconPrefix ) ) newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) ); - ColorUIResource color = toColor( (String) value ); + String color = toColor( (String) value ); if( color != null ) { - defaults.put( newKey, color ); + put( properties, newKey, color ); String key2 = checkboxDuplicateColors.get( key + ".Dark"); if( key2 != null ) { @@ -592,7 +618,7 @@ public class IntelliJTheme String newKey2 = checkboxKeyMapping.get( key2 ); if( newKey2 != null ) - defaults.put( newKey2, color ); + put( properties, newKey2, color ); } } @@ -603,13 +629,13 @@ public class IntelliJTheme // update hover, pressed and focused colors if( checkboxModified ) { // for non-filled checkbox/radiobutton used in dark themes - defaults.remove( "CheckBox.icon.focusWidth" ); - defaults.put( "CheckBox.icon.hoverBorderColor", defaults.get( "CheckBox.icon.focusedBorderColor" ) ); + properties.remove( "CheckBox.icon.focusWidth" ); + put( properties, "CheckBox.icon.hoverBorderColor", properties.get( "CheckBox.icon.focusedBorderColor" ) ); // for filled checkbox/radiobutton used in light themes - defaults.remove( "CheckBox.icon[filled].focusWidth" ); - defaults.put( "CheckBox.icon[filled].hoverBorderColor", defaults.get( "CheckBox.icon[filled].focusedBorderColor" ) ); - defaults.put( "CheckBox.icon[filled].focusedSelectedBackground", defaults.get( "CheckBox.icon[filled].selectedBackground" ) ); + properties.remove( "CheckBox.icon[filled].focusWidth" ); + put( properties, "CheckBox.icon[filled].hoverBorderColor", properties.get( "CheckBox.icon[filled].focusedBorderColor" ) ); + put( properties, "CheckBox.icon[filled].focusedSelectedBackground", properties.get( "CheckBox.icon[filled].selectedBackground" ) ); if( dark ) { // IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg, @@ -623,21 +649,14 @@ public class IntelliJTheme "CheckBox.icon[filled].focusedSelectedBorderColor", }; for( String key : focusedBorderColorKeys ) { - Color color = defaults.getColor( key ); - if( color != null ) { - defaults.put( key, new ColorUIResource( new Color( - (color.getRGB() & 0xffffff) | 0xa6000000, true ) ) ); - } + Object color = properties.get( key ); + if( color != null ) + put( properties, key, "fade(" + color + ", 65%)" ); } } } } - private void copyIfNotSet( UIDefaults defaults, String destKey, String srcKey, Set uiKeys ) { - if( !uiKeys.contains( destKey ) ) - defaults.put( destKey, defaults.get( srcKey ) ); - } - private static final Set uiKeyExcludes; private static final Set uiKeyDoNotOverride; /** Rename UI default keys (key --> value). */ @@ -653,26 +672,26 @@ public class IntelliJTheme uiKeyExcludes = new HashSet<>( Arrays.asList( "ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.", "AvailableMnemonic.", - "Badge.", "BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.", + "Badge.", "Banner.", "BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.", "BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.", - "Canvas.", "Code.", "CodeWithMe.", "CombinedDiff.", "ComboBoxButton.", "CompilationCharts.", - "CompletionPopup.", "ComplexPopup.", "Content.", "ContextHelp.", "CurrentMnemonic.", "Counter.", + "Canvas.", "CellEditor.", "Code.", "CodeWithMe.", "ColumnControlButton.", "CombinedDiff.", "ComboBoxButton.", + "CompilationCharts.", "CompletionPopup.", "ComplexPopup.", "Content.", "ContextHelp.", "CurrentMnemonic.", "Counter.", "Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "DisclosureButton.", "DragAndDrop.", "Editor.", "EditorGroupsTabs.", "EditorTabs.", - "FileColor.", "FlameGraph.", "Focus.", + "FileColor.", "FindPopup.", "FlameGraph.", "Focus.", "Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.", "HeaderColor.", "HelpTooltip.", "Hg.", - "IconBadge.", "InformationHint.", "InplaceRefactoringPopup.", + "IconBadge.", "InformationHint.", "InlineBanner.", "InplaceRefactoringPopup.", "Lesson.", "LineProfiler.", "Link.", "LiveIndicator.", - "MainMenu.", "MainToolbar.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.", + "MainMenu.", "MainToolbar.", "MainWindow.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.", "NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.", "OnePixelDivider.", "OptionButton.", "Outline.", - "ParameterInfo.", "Plugins.", "Profiler.", "ProgressIcon.", "PsiViewer.", - "ReviewList.", "RunWidget.", + "ParameterInfo.", "PresentationAssistant.", "Plugins.", "Profiler.", "ProgressIcon.", "PsiViewer.", + "Resizable.", "Review.", "ReviewList.", "RunToolbar.", "RunWidget.", "ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.", "SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.", - "StatusBar.", + "StatusBar.", "StripeToolbar.", "Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.", "TrialWidget.", "UIDesigner.", "UnattendedHostStatus.", "ValidationTooltip.", "VersionControl.", @@ -689,6 +708,9 @@ public class IntelliJTheme "TabbedPane.selectedForeground" ) ); + // Button + uiKeyMapping.put( "Button.minimumSize", "" ); // ignore (used in Material Theme UI Lite) + // ComboBox uiKeyMapping.put( "ComboBox.background", "" ); // ignore uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore @@ -697,8 +719,6 @@ public class IntelliJTheme uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" ); uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" ); uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" ); - uiKeyCopying.put( "ComboBox.buttonSeparatorColor", "Component.borderColor" ); - uiKeyCopying.put( "ComboBox.buttonDisabledSeparatorColor", "Component.disabledBorderColor" ); // Component uiKeyMapping.put( "Component.inactiveErrorFocusColor", "Component.error.borderColor" ); @@ -706,16 +726,16 @@ public class IntelliJTheme uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" ); uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" ); + // Label + uiKeyMapping.put( "Label.disabledForegroundColor", "" ); // ignore (used in Material Theme UI Lite) + // Link uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" ); // Menu uiKeyMapping.put( "Menu.border", "Menu.margin" ); uiKeyMapping.put( "MenuItem.border", "MenuItem.margin" ); - uiKeyCopying.put( "CheckBoxMenuItem.margin", "MenuItem.margin" ); - uiKeyCopying.put( "RadioButtonMenuItem.margin", "MenuItem.margin" ); uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" ); - uiKeyCopying.put( "MenuItem.underlineSelectionColor", "TabbedPane.underlineColor" ); // IDEA uses List.selectionBackground also for menu selection uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" ); @@ -723,13 +743,11 @@ public class IntelliJTheme uiKeyCopying.put( "CheckBoxMenuItem.selectionBackground", "List.selectionBackground" ); uiKeyCopying.put( "RadioButtonMenuItem.selectionBackground", "List.selectionBackground" ); - // ProgressBar + // ProgressBar: IDEA uses ProgressBar.trackColor and ProgressBar.progressColor uiKeyMapping.put( "ProgressBar.background", "" ); // ignore uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore uiKeyMapping.put( "ProgressBar.trackColor", "ProgressBar.background" ); uiKeyMapping.put( "ProgressBar.progressColor", "ProgressBar.foreground" ); - uiKeyCopying.put( "ProgressBar.selectionForeground", "ProgressBar.background" ); - uiKeyCopying.put( "ProgressBar.selectionBackground", "ProgressBar.foreground" ); // ScrollBar uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" ); @@ -739,34 +757,30 @@ public class IntelliJTheme uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" ); // Slider + uiKeyMapping.put( "Slider.buttonColor", "Slider.thumbColor" ); + uiKeyMapping.put( "Slider.buttonBorderColor", "" ); // ignore + uiKeyMapping.put( "Slider.thumb", "" ); // ignore (used in Material Theme UI Lite) + uiKeyMapping.put( "Slider.track", "" ); // ignore (used in Material Theme UI Lite) + uiKeyMapping.put( "Slider.trackDisabled", "" ); // ignore (used in Material Theme UI Lite) uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite) - uiKeyCopying.put( "Slider.trackValueColor", "ProgressBar.foreground" ); - uiKeyCopying.put( "Slider.thumbColor", "ProgressBar.foreground" ); - uiKeyCopying.put( "Slider.trackColor", "ProgressBar.background" ); - - // Spinner - uiKeyCopying.put( "Spinner.buttonSeparatorColor", "Component.borderColor" ); - uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" ); // TabbedPane uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" ); uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" ); uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" ); + uiKeyMapping.put( "TabbedPane.tabAreaInsets", "" ); // ignore (used in Material Theme UI Lite) + + // TableHeader + uiKeyMapping.put( "TableHeader.cellBorder", "" ); // ignore (used in Material Theme UI Lite) + uiKeyMapping.put( "TableHeader.height", "" ); // ignore (used in Material Theme UI Lite) // TitlePane - uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" ); uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" ); uiKeyMapping.put( "TitlePane.inactiveInfoForeground", "TitlePane.inactiveForeground" ); for( Map.Entry e : uiKeyMapping.entrySet() ) uiKeyInverseMapping.put( e.getValue(), e.getKey() ); - uiKeyCopying.put( "ToggleButton.tab.underlineColor", "TabbedPane.underlineColor" ); - uiKeyCopying.put( "ToggleButton.tab.disabledUnderlineColor", "TabbedPane.disabledUnderlineColor" ); - uiKeyCopying.put( "ToggleButton.tab.selectedBackground", "TabbedPane.selectedBackground" ); - uiKeyCopying.put( "ToggleButton.tab.hoverBackground", "TabbedPane.hoverColor" ); - uiKeyCopying.put( "ToggleButton.tab.focusBackground", "TabbedPane.focusColor" ); - checkboxKeyMapping.put( "Checkbox.Background.Default", "CheckBox.icon.background" ); checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" ); checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" ); @@ -819,17 +833,15 @@ public class IntelliJTheme } @Override - void applyAdditionalDefaults( UIDefaults defaults ) { - theme.applyProperties( defaults ); + void applyAdditionalProperties( Properties properties ) { + theme.applyProperties( properties ); } @Override protected ArrayList> getLafClassesForDefaultsLoading() { - ArrayList> lafClasses = new ArrayList<>(); - lafClasses.add( FlatLaf.class ); - lafClasses.add( theme.dark ? FlatDarkLaf.class : FlatLightLaf.class ); - lafClasses.add( theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class ); - lafClasses.add( ThemeLaf.class ); + ArrayList> lafClasses = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() ); + lafClasses.add( 1, theme.dark ? FlatDarkLaf.class : FlatLightLaf.class ); + lafClasses.add( 2, theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class ); return lafClasses; } } 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 4c3f42ea..6ab832cc 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java @@ -41,6 +41,7 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; +import java.util.function.Consumer; import java.util.function.Function; import javax.swing.Icon; import javax.swing.UIDefaults; @@ -85,15 +86,14 @@ class UIDefaultsLoader private static final String WILDCARD_PREFIX = "*."; static final String KEY_VARIABLES = "FlatLaf.internal.variables"; + static final String KEY_PROPERTIES = "FlatLaf.internal.properties"; private static int parseColorDepth; private static Map systemColorCache; private static final SoftCache fontCache = new SoftCache<>(); - static void loadDefaultsFromProperties( Class lookAndFeelClass, List addons, - Properties additionalDefaults, boolean dark, UIDefaults defaults ) - { + static ArrayList> getLafClassesForDefaultsLoading( Class lookAndFeelClass ) { // determine classes in class hierarchy in reverse order ArrayList> lafClasses = new ArrayList<>(); for( Class lafClass = lookAndFeelClass; @@ -102,12 +102,11 @@ class UIDefaultsLoader { lafClasses.add( 0, lafClass ); } - - loadDefaultsFromProperties( lafClasses, addons, additionalDefaults, dark, defaults ); + return lafClasses; } static void loadDefaultsFromProperties( List> lafClasses, List addons, - Properties additionalDefaults, boolean dark, UIDefaults defaults ) + Consumer intellijThemesHook, Properties additionalDefaults, boolean dark, UIDefaults defaults ) { try { // temporary cache system colors while loading defaults, @@ -142,6 +141,10 @@ class UIDefaultsLoader addonClassLoaders.add( addonClassLoader ); } + // apply IntelliJ themes properties + if( intellijThemesHook != null ) + intellijThemesHook.accept( properties ); + // load custom properties files (usually provided by applications) List customDefaultsSources = FlatLaf.getCustomDefaultsSources(); int size = (customDefaultsSources != null) ? customDefaultsSources.size() : 0; @@ -287,6 +290,15 @@ class UIDefaultsLoader // remember variables in defaults to allow using them in styles defaults.put( KEY_VARIABLES, variables ); + // remember properties (for testing) + if( FlatSystemProperties.getBoolean( KEY_PROPERTIES, false ) ) { + Properties properties2 = new Properties(); + properties2.putAll( properties ); + for( Map.Entry e : wildcards.entrySet() ) + properties2.put( WILDCARD_PREFIX + e.getKey(), e.getValue() ); + defaults.put( KEY_PROPERTIES, properties2 ); + } + // clear/disable system color cache systemColorCache = null; } catch( IOException ex ) { diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties index 07d6a181..331fe64c 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarculaLaf.properties @@ -61,7 +61,6 @@ Component.arrowType = triangle #---- ProgressBar ---- ProgressBar.foreground = darken(@foreground,10%) -ProgressBar.selectionForeground = @background #---- RadioButton ---- diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/IntelliJTheme$ThemeLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/IntelliJTheme$ThemeLaf.properties index 6ece7ce2..d10d034f 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/IntelliJTheme$ThemeLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/IntelliJTheme$ThemeLaf.properties @@ -21,27 +21,41 @@ # - https://www.formdev.com/flatlaf/properties-files/ # - https://www.formdev.com/flatlaf/how-to-customize/ # +# Properties in this file are applied in following order: +# 1. properties without '{...}' and without '[...]' prefix +# 2. properties specified in .theme.json file +# 3. properties starting with '{*}' +# 4. properties starting with '{*-light}' or '{*-dark}' +# 5. properties starting with '{author-}', +# where '' is replaced with "author" value from .theme.json file +# 6. properties starting with '{---}', +# where '' and '' are replaced with "name" and "author" values from .theme.json file +# 7. properties starting with '{}', +# where '' is replaced with "name" value from .theme.json file +# 8. properties with '[...]' prefix +# + #---- system colors ---- # fix (most) system colors because they are usually not set in .json files -desktop = lazy(TextField.background) -activeCaptionText = lazy(TextField.foreground) -inactiveCaptionText = lazy(TextField.foreground) -window = lazy(Panel.background) -windowBorder = lazy(TextField.foreground) -windowText = lazy(TextField.foreground) -menu = lazy(Menu.background) -menuText = lazy(Menu.foreground) -text = lazy(TextField.background) -textText = lazy(TextField.foreground) -textHighlight = lazy(TextField.selectionBackground) -textHighlightText = lazy(TextField.selectionForeground) -textInactiveText = lazy(TextField.inactiveForeground) -control = lazy(Panel.background) -controlText = lazy(TextField.foreground) -info = lazy(ToolTip.background) -infoText = lazy(ToolTip.foreground) +desktop = $TextField.background +activeCaptionText = $TextField.foreground +inactiveCaptionText = $TextField.foreground +window = $Panel.background +windowBorder = $TextField.foreground +windowText = $TextField.foreground +menu = $Menu.background +menuText = $Menu.foreground +text = $TextField.background +textText = $TextField.foreground +textHighlight = $TextField.selectionBackground +textHighlightText = $TextField.selectionForeground +textInactiveText = $TextField.inactiveForeground +control = $Panel.background +controlText = $TextField.foreground +info = $ToolTip.background +infoText = $ToolTip.foreground #---- variables ---- @@ -49,26 +63,13 @@ infoText = lazy(ToolTip.foreground) # make sure that accent color (set via FlatLaf.setSystemColorGetter()) is ignored @accentColor = null +# use same accent color for checkmark, slider, tab underline, etc. +@accentBase2Color = @accentBaseColor + # use fixed color because it is used in borders @cellFocusColor = #222 -#---- Button ---- - -Button.startBackground = $Button.background -Button.endBackground = $Button.background -Button.startBorderColor = $Button.borderColor -Button.endBorderColor = $Button.borderColor - -Button.default.startBackground = $Button.default.background -Button.default.endBackground = $Button.default.background -Button.default.startBorderColor = $Button.default.borderColor -Button.default.endBorderColor = $Button.default.borderColor - -Button.hoverBorderColor = null -Button.default.hoverBorderColor = null - - #---- CheckBoxMenuItem ---- # colors from intellij/checkmark.svg and darcula/checkmark.svg @@ -76,19 +77,19 @@ Button.default.hoverBorderColor = null [dark]CheckBoxMenuItem.icon.checkmarkColor=#fff9 -#---- Component ---- - -Component.accentColor = lazy(ProgressBar.foreground) - - -#---- HelpButton ---- - -HelpButton.hoverBorderColor = null - - #---- Slider ---- -Slider.focusedColor = fade($Component.focusColor,40%,derived) +# this "reverses" definition in FlatLightLaf/FlatDarkLaf.properties +Slider.trackValueColor = $Slider.thumbColor +Slider.thumbColor = @accentSliderColor + + +#---- Spinner ---- + +# Spinner arrow button always has same colors as ComboBox arrow button +Spinner.buttonBackground = $ComboBox.buttonEditableBackground +Spinner.buttonArrowColor = $ComboBox.buttonArrowColor +Spinner.buttonDisabledArrowColor = $ComboBox.buttonDisabledArrowColor #---- TabbedPane ---- @@ -100,10 +101,9 @@ Slider.focusedColor = fade($Component.focusColor,40%,derived) #---- ToggleButton ---- -ToggleButton.startBackground = $ToggleButton.background -ToggleButton.endBackground = $ToggleButton.background -[dark]ToggleButton.selectedBackground = lighten($ToggleButton.background,15%,derived) -[dark]ToggleButton.disabledSelectedBackground = lighten($ToggleButton.background,5%,derived) +{*}ToggleButton.background = $Button.background +{*-dark}ToggleButton.selectedBackground = lighten($ToggleButton.background,15%,derived) +{*-dark}ToggleButton.disabledSelectedBackground = lighten($ToggleButton.background,5%,derived) #---- theme specific ---- @@ -112,343 +112,434 @@ ToggleButton.endBackground = $ToggleButton.background @ijMenuCheckBackgroundL20 = lighten(@selectionBackground,20%,derived noAutoInverse) @ijMenuCheckBackgroundD10 = darken(@selectionBackground,10%,derived noAutoInverse) -@ijTextBackgroundL3 = lighten(Panel.background,3%,lazy) -@ijTextBackgroundL4 = lighten(Panel.background,4%,lazy) +@ijSeparatorLight = shade(@background,15%) +@ijSeparatorDark = tint(@background,25%) -{Arc_Theme}CheckBoxMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme}PopupMenu.foreground = lazy(MenuItem.foreground) -{Arc_Theme}RadioButtonMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme}ProgressBar.selectionBackground = #000 -{Arc_Theme}ProgressBar.selectionForeground = #fff -{Arc_Theme}List.selectionInactiveForeground = #fff -{Arc_Theme}Table.selectionInactiveForeground = #fff -{Arc_Theme}Tree.selectionInactiveForeground = #fff +@ijTextBackgroundL3 = lighten($Panel.background,3%) +@ijTextBackgroundL4 = lighten($Panel.background,4%) -{Arc_Theme_-_Orange}CheckBoxMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme_-_Orange}PopupMenu.foreground = lazy(MenuItem.foreground) -{Arc_Theme_-_Orange}RadioButtonMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme_-_Orange}ProgressBar.selectionBackground = #000 -{Arc_Theme_-_Orange}ProgressBar.selectionForeground = #fff -{Arc_Theme_-_Orange}List.selectionInactiveForeground = #fff -{Arc_Theme_-_Orange}Table.selectionInactiveForeground = #fff -{Arc_Theme_-_Orange}Tree.selectionInactiveForeground = #fff +{Arc_Theme}@selectionInactiveForeground = @selectionForeground +{Arc_Theme}CheckBoxMenuItem.foreground = $MenuItem.foreground +{Arc_Theme}PopupMenu.foreground = $MenuItem.foreground +{Arc_Theme}RadioButtonMenuItem.foreground = $MenuItem.foreground -{Arc_Theme_Dark}CheckBoxMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme_Dark}PopupMenu.foreground = lazy(MenuItem.foreground) -{Arc_Theme_Dark}RadioButtonMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme_Dark}ProgressBar.selectionBackground = #ddd -{Arc_Theme_Dark}ProgressBar.selectionForeground = #ddd -{Arc_Theme_Dark}ToolBar.separatorColor = lazy(Separator.foreground) +{Arc_Theme_-_Orange}@selectionInactiveForeground = @selectionForeground +{Arc_Theme_-_Orange}CheckBoxMenuItem.foreground = $MenuItem.foreground +{Arc_Theme_-_Orange}PopupMenu.foreground = $MenuItem.foreground +{Arc_Theme_-_Orange}RadioButtonMenuItem.foreground = $MenuItem.foreground -{Arc_Theme_Dark_-_Orange}CheckBoxMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme_Dark_-_Orange}PopupMenu.foreground = lazy(MenuItem.foreground) -{Arc_Theme_Dark_-_Orange}RadioButtonMenuItem.foreground = lazy(MenuItem.foreground) -{Arc_Theme_Dark_-_Orange}ProgressBar.selectionBackground = #ddd +{Arc_Theme_Dark}CheckBoxMenuItem.foreground = $MenuItem.foreground +{Arc_Theme_Dark}PopupMenu.foreground = $MenuItem.foreground +{Arc_Theme_Dark}RadioButtonMenuItem.foreground = $MenuItem.foreground +{Arc_Theme_Dark}ToolBar.background = @background + +{Arc_Theme_Dark_-_Orange}CheckBoxMenuItem.foreground = $MenuItem.foreground +{Arc_Theme_Dark_-_Orange}PopupMenu.foreground = $MenuItem.foreground {Arc_Theme_Dark_-_Orange}ProgressBar.selectionForeground = #fff -{Arc_Theme_Dark_-_Orange}ToolBar.separatorColor = lazy(Separator.foreground) +{Arc_Theme_Dark_-_Orange}RadioButtonMenuItem.foreground = $MenuItem.foreground +{Arc_Theme_Dark_-_Orange}ToolBar.background = @background -{Carbon}Table.selectionBackground = lazy(List.selectionBackground) -{Carbon}Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground) +{Carbon}Separator.foreground = @ijSeparatorDark +{Carbon}ToolBar.separatorColor = $Separator.foreground +{Carbon}Table.selectionBackground = $List.selectionBackground {Carbon}TextField.background = @ijTextBackgroundL4 -{Cobalt_2}Component.accentColor = lazy(Component.focusColor) -{Cobalt_2}CheckBox.icon.background = #002946 -{Cobalt_2}CheckBox.icon.checkmarkColor = #002946 +{Cobalt_2}@accentBaseColor = $ColorPalette.hue3 +{Cobalt_2}CheckBox.icon.background = @background {Cobalt_2}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 {Cobalt_2}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 {Cobalt_2}ComboBox.background = @ijTextBackgroundL3 -{Cobalt_2}ComboBox.buttonBackground = @ijTextBackgroundL3 +{Cobalt_2}Slider.thumbColor = $ProgressBar.foreground +{Cobalt_2}Slider.disabledTrackColor = $Separator.foreground {Cobalt_2}TextField.background = @ijTextBackgroundL3 -{Cobalt_2}Table.background = lazy(List.background) -{Cobalt_2}Tree.background = lazy(List.background) +{Cobalt_2}Table.background = $List.background +{Cobalt_2}Tree.background = $List.background +{Cyan_light}@disabledForeground = tint(@foreground,30%) +{Cyan_light}*.disabledText = @disabledForeground +{Cyan_light}*.disabledForeground = @disabledForeground +{Cyan_light}*.inactiveForeground = @disabledForeground +{Cyan_light}Button.background = @buttonBackground {Cyan_light}MenuItem.checkBackground = @ijMenuCheckBackgroundL20 {Cyan_light}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20 -{Dark_Flat_Theme}*.inactiveForeground = #808080 -{Dark_Flat_Theme}Component.accentColor = lazy(List.selectionBackground) +{Dark_Flat_Theme}@accentBaseColor = $TabbedPane.underlineColor +{Dark_Flat_Theme}@disabledForeground = #808080 +{Dark_Flat_Theme}*.disabledText = @disabledForeground +{Dark_Flat_Theme}*.disabledForeground = @disabledForeground +{Dark_Flat_Theme}*.inactiveForeground = @disabledForeground {Dark_Flat_Theme}TableHeader.background = #3B3B3B -{Dark_Flat_Theme}TextPane.foreground = lazy(TextField.foreground) -{Dark_Flat_Theme}CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground) -{Dark_Flat_Theme}List.selectionForeground = lazy(Tree.selectionForeground) -{Dark_Flat_Theme}RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground) -{Dark_Flat_Theme}Separator.foreground = lazy(ToolBar.separatorColor) +{Dark_Flat_Theme}CheckBoxMenuItem.selectionForeground = $MenuItem.selectionForeground +{Dark_Flat_Theme}ComboBox.background = $TextField.background +{Dark_Flat_Theme}ComboBox.buttonBackground = $ComboBox.background +{Dark_Flat_Theme}List.selectionForeground = $Tree.selectionForeground +{Dark_Flat_Theme}ProgressBar.selectionForeground = @foreground +{Dark_Flat_Theme}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground +{Dark_Flat_Theme}Separator.foreground = @ijSeparatorDark +{Dark_Flat_Theme}Slider.trackColor = $ProgressBar.background +{Dark_Flat_Theme}Slider.thumbColor = fade($ProgressBar.foreground,100%) +{Dark_Flat_Theme}TextPane.foreground = $TextField.foreground +{Dark_Flat_Theme}ToggleButton.foreground = $Button.foreground -{Dark_purple}Slider.focusedColor = fade($Component.focusColor,70%,derived) - -{Dracula---Zihan_Ma}Component.accentColor = lazy(Component.focusColor) -{Dracula---Zihan_Ma}ComboBox.selectionBackground = lazy(List.selectionBackground) +{Dracula---Zihan_Ma}CheckBox.icon.background = @background +{Dracula---Zihan_Ma}ComboBox.selectionBackground = $List.selectionBackground {Dracula---Zihan_Ma}ProgressBar.selectionBackground = #fff {Dracula---Zihan_Ma}ProgressBar.selectionForeground = #fff +{Dracula---Zihan_Ma}Slider.trackColor = $?ColorPalette.selectionBackground +{Dracula---Zihan_Ma}ToggleButton.foreground = $Button.foreground -{Gradianto_Dark_Fuchsia}*.selectionBackground = #8452a7 -{Gradianto_Dark_Fuchsia}*.selectionInactiveBackground = #562C6A {Gradianto_Dark_Fuchsia}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 {Gradianto_Dark_Fuchsia}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 {Gradianto_Dark_Fuchsia}TextField.background = @ijTextBackgroundL4 -{Gradianto_Dark_Fuchsia}Tree.background = lazy(List.background) -{Gradianto_Dark_Fuchsia}Separator.foreground = lazy(ScrollBar.track) -{Gradianto_Dark_Fuchsia}ToolBar.separatorColor = lazy(ScrollBar.track) -{Gradianto_Dark_Fuchsia}ProgressBar.background = lazy(ScrollBar.track) -{Gradianto_Dark_Fuchsia}Slider.trackColor = lazy(ScrollBar.track) +{Gradianto_Dark_Fuchsia}Tree.background = $List.background +{Gradianto_Dark_Fuchsia}Tree.selectionInactiveBackground = $List.selectionInactiveBackground +{Gradianto_Dark_Fuchsia}Separator.foreground = @ijSeparatorDark +{Gradianto_Dark_Fuchsia}ToolBar.separatorColor = $Separator.foreground +{Gradianto_Dark_Fuchsia}ProgressBar.background = $ScrollBar.track +{Gradianto_Dark_Fuchsia}Slider.trackColor = $ScrollBar.track +{Gradianto_Deep_Ocean}Separator.foreground = @ijSeparatorDark +{Gradianto_Deep_Ocean}ToolBar.separatorColor = $Separator.foreground {Gradianto_Deep_Ocean}TextField.background = @ijTextBackgroundL3 -{Gradianto_Deep_Ocean}Tree.background = lazy(List.background) +{Gradianto_Deep_Ocean}Tree.background = $List.background {Gradianto_Midnight_Blue}ScrollBar.thumb = #533B6B -{Gradianto_Midnight_Blue}Table.selectionForeground = lazy(List.selectionForeground) +{Gradianto_Midnight_Blue}Separator.foreground = @ijSeparatorDark +{Gradianto_Midnight_Blue}ToolBar.separatorColor = $Separator.foreground +{Gradianto_Midnight_Blue}Table.selectionForeground = $List.selectionForeground {Gradianto_Midnight_Blue}TextField.background = @ijTextBackgroundL4 -{Gradianto_Midnight_Blue}Tree.background = lazy(List.background) +{Gradianto_Midnight_Blue}Tree.background = $List.background -{Gradianto_Nature_Green}Table.selectionForeground = lazy(List.selectionForeground) +{Gradianto_Nature_Green}Separator.foreground = @ijSeparatorDark +{Gradianto_Nature_Green}ToolBar.separatorColor = $Separator.foreground +{Gradianto_Nature_Green}Table.selectionForeground = $List.selectionForeground {Gradianto_Nature_Green}TextField.background = @ijTextBackgroundL4 -{Gray}Separator.foreground = lazy(Slider.trackColor) -{Gray}ToolBar.separatorColor = lazy(Slider.trackColor) +{Gray}@disabledForeground = tint(@foreground,40%) +{Gray}*.disabledText = @disabledForeground +{Gray}*.disabledForeground = @disabledForeground +{Gray}*.inactiveForeground = @disabledForeground +{Gray}Button.background = @buttonBackground +{Gray}Separator.foreground = @ijSeparatorLight +{Gray}ToolBar.separatorColor = $Separator.foreground -{Gruvbox_Dark_Hard}Component.accentColor = lazy(TabbedPane.underlineColor) -{Gruvbox_Dark_Hard}ToggleButton.selectedBackground = $ToggleButton.selectedBackground -{Gruvbox_Dark_Hard}ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground +{Gruvbox_Dark_Hard}@accentBaseColor = #4B6EAF {Gruvbox_Dark_Hard}ComboBox.background = @ijTextBackgroundL3 -{Gruvbox_Dark_Hard}ComboBox.buttonBackground = @ijTextBackgroundL3 +{Gruvbox_Dark_Hard}ComboBox.buttonBackground = $ComboBox.background {Gruvbox_Dark_Hard}TextField.background = @ijTextBackgroundL3 -{Hiberbee_Dark}*.disabledForeground = #7F7E7D -{Hiberbee_Dark}*.disabledText = #7F7E7D -{Hiberbee_Dark}*.inactiveForeground = #7F7E7D -{Hiberbee_Dark}ProgressBar.background = lazy(Separator.foreground) -{Hiberbee_Dark}Slider.trackColor = lazy(Separator.foreground) -{Hiberbee_Dark}TabbedPane.focusColor = #5A5A5A -{Hiberbee_Dark}TabbedPane.selectedBackground = #434241 -{Hiberbee_Dark}TabbedPane.selectedForeground = #70D7FF -{Hiberbee_Dark}ToggleButton.selectedBackground = $ToggleButton.selectedBackground -{Hiberbee_Dark}ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground -{Hiberbee_Dark}Table.selectionInactiveBackground = lazy(List.selectionInactiveBackground) -{Hiberbee_Dark}Tree.selectionBackground = lazy(List.selectionBackground) -{Hiberbee_Dark}Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground) +{Hiberbee_Dark}@disabledForeground = $ColorPalette.light3 +{Hiberbee_Dark}*.disabledText = @disabledForeground +{Hiberbee_Dark}*.disabledForeground = @disabledForeground +{Hiberbee_Dark}*.inactiveForeground = @disabledForeground +{Hiberbee_Dark}List.selectionInactiveBackground = $Table.selectionInactiveBackground +{Hiberbee_Dark}ProgressBar.background = $Separator.foreground +{Hiberbee_Dark}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground +{Hiberbee_Dark}Slider.trackColor = $ColorPalette.light1 +{Hiberbee_Dark}Slider.trackColor = $ColorPalette.dark10 +{Hiberbee_Dark}Slider.thumbColor = @accentBaseColor +{Hiberbee_Dark}ToggleButton.foreground = $Button.foreground +{Hiberbee_Dark}ToolBar.background = @background -{High_Contrast}Component.accentColor = lazy(Component.focusColor) -{High_Contrast}Button.hoverBorderColor = #1AEBFF -{High_Contrast}HelpButton.hoverBorderColor = #1AEBFF -{High_Contrast}ToggleButton.selectedBackground = #fff -{High_Contrast}ToggleButton.selectedForeground = #000 -{High_Contrast}ToggleButton.disabledSelectedBackground = #444 -{High_Contrast}ToggleButton.toolbar.selectedBackground = #3333FF +{High_Contrast}@accentBaseColor = $TabbedPane.underlineColor +{High_Contrast}Slider.thumbBorderColor = $Slider.thumbColor +{High_Contrast}Slider.focusedThumbBorderColor = @background +{High_Contrast}Slider.focusedColor = $Component.focusColor +{High_Contrast}Slider.focusWidth = 2 +{High_Contrast}ToggleButton.selectedBackground = @selectionBackground +{High_Contrast}ToggleButton.selectedForeground = @selectionForeground +{High_Contrast}ToggleButton.disabledSelectedBackground = shade(@selectionBackground,50%) +{High_Contrast}ToggleButton.toolbar.selectedBackground = @selectionBackground {High_Contrast}[style]Button.inTextField = \ toolbar.hoverBackground: #444; \ toolbar.pressedBackground: #666; \ - toolbar.selectedBackground: #fff -{High_Contrast}[style]ToggleButton.inTextField = ${High_Contrast}[style]Button.inTextField + toolbar.selectedBackground: @selectionBackground -{Light_Flat}*.disabledForeground = #8C8C8C -{Light_Flat}*.inactiveForeground = #8C8C8C +{Light_Flat}@accentBaseColor = $TabbedPane.underlineColor +{Light_Flat}@accentFocusColor = lighten(@accentBaseColor,15%) +{Light_Flat}@disabledForeground = #808080 +{Light_Flat}*.disabledText = @disabledForeground +{Light_Flat}*.disabledForeground = @disabledForeground +{Light_Flat}*.inactiveForeground = @disabledForeground {Light_Flat}CheckBox.icon[filled].background = #fff {Light_Flat}CheckBox.icon[filled].checkmarkColor = #fff -{Light_Flat}Component.accentColor = lazy(TabbedPane.underlineColor) -{Light_Flat}ComboBox.background = lazy(ComboBox.editableBackground) -{Light_Flat}ComboBox.buttonBackground = lazy(ComboBox.editableBackground) -{Light_Flat}Separator.foreground = lazy(ToolBar.separatorColor) +{Light_Flat}ComboBox.background = $ComboBox.editableBackground +{Light_Flat}ComboBox.buttonBackground = $ComboBox.background +{Light_Flat}ProgressBar.selectionForeground = @foreground +{Light_Flat}Separator.foreground = @ijSeparatorLight {Light_Flat}TableHeader.background = #E5E5E9 -{Light_Flat}TextPane.foreground = lazy(TextField.foreground) -{Light_Flat}CheckBoxMenuItem.selectionForeground = lazy(MenuItem.selectionForeground) -{Light_Flat}RadioButtonMenuItem.selectionForeground = lazy(MenuItem.selectionForeground) +{Light_Flat}TextPane.foreground = $TextField.foreground +{Light_Flat}ToggleButton.foreground = $Button.foreground +{Light_Flat}CheckBoxMenuItem.selectionForeground = $MenuItem.selectionForeground +{Light_Flat}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground -{Monocai}Button.default.foreground = #2D2A2F +{Monocai}@accentUnderlineColor = @accentBaseColor +{Monocai}*.acceleratorForeground = @menuAcceleratorForeground +{Monocai}*.acceleratorSelectionForeground = @menuAcceleratorSelectionForeground +{Monocai}Button.default.foreground = @background {Monocai}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 -{Monocai}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 -@Monocai.acceleratorForeground = lazy(MenuItem.disabledForeground) -@Monocai.acceleratorSelectionForeground = lighten(MenuItem.disabledForeground,10%,lazy) -{Monocai}CheckBoxMenuItem.acceleratorForeground = @Monocai.acceleratorForeground -{Monocai}CheckBoxMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground -{Monocai}Menu.acceleratorForeground = @Monocai.acceleratorForeground -{Monocai}Menu.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground -{Monocai}MenuItem.acceleratorForeground = @Monocai.acceleratorForeground -{Monocai}MenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground -{Monocai}RadioButtonMenuItem.acceleratorForeground = @Monocai.acceleratorForeground -{Monocai}RadioButtonMenuItem.acceleratorSelectionForeground = @Monocai.acceleratorSelectionForeground +{Monocai}TabbedPane.underlineColor = @accentUnderlineColor {Monocai}TextField.background = @ijTextBackgroundL4 -@Monocai.selectionBackground = lazy(TextField.selectionBackground) +@Monocai.selectionBackground = $TextField.selectionBackground {Monocai}ComboBox.selectionBackground = @Monocai.selectionBackground {Monocai}List.selectionBackground = @Monocai.selectionBackground {Monocai}Table.selectionBackground = @Monocai.selectionBackground {Monocai}Tree.selectionBackground = @Monocai.selectionBackground -@Monocai.selectionInactiveBackground = lazy(MenuItem.selectionBackground) +@Monocai.selectionInactiveBackground = $MenuItem.selectionBackground {Monocai}List.selectionInactiveBackground = @Monocai.selectionInactiveBackground {Monocai}Table.selectionInactiveBackground = @Monocai.selectionInactiveBackground {Monocai}Tree.selectionInactiveBackground = @Monocai.selectionInactiveBackground -{Monokai_Pro---Subtheme}Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground) -{Monokai_Pro---Subtheme}Tree.selectionBackground = lazy(List.selectionBackground) -{Monokai_Pro---Subtheme}Separator.foreground = lazy(Slider.trackColor) -{Monokai_Pro---Subtheme}ToolBar.separatorColor = lazy(Slider.trackColor) +{Monokai_Pro---Subtheme}@disabledForeground = shade(@foreground,40%) +{Monokai_Pro---Subtheme}*.disabledText = @disabledForeground +{Monokai_Pro---Subtheme}*.disabledForeground = @disabledForeground +{Monokai_Pro---Subtheme}*.inactiveForeground = @disabledForeground +{Monokai_Pro---Subtheme}ProgressBar.selectionBackground = #fff +{Monokai_Pro---Subtheme}Table.selectionInactiveForeground = $List.selectionInactiveForeground +{Monokai_Pro---Subtheme}Tree.selectionBackground = $List.selectionBackground +{Monokai_Pro---Subtheme}ToggleButton.foreground = $Button.foreground +{Monokai_Pro---Subtheme}Separator.foreground = @ijSeparatorDark +{Monokai_Pro---Subtheme}ToolBar.separatorColor = $Separator.foreground +{Monokai_Pro---Subtheme}ToolBar.background = @background -{Nord}*.inactiveForeground = #616E88 +{Nord}@disabledForeground = #616E88 +{Nord}*.disabledText = @disabledForeground +{Nord}*.disabledForeground = @disabledForeground +{Nord}*.inactiveForeground = @disabledForeground {Nord}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 {Nord}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 -{Nord}List.selectionBackground = lazy(Tree.selectionBackground) -{Nord}List.selectionForeground = lazy(Tree.selectionForeground) -{Nord}Table.selectionBackground = lazy(Tree.selectionBackground) -{Nord}Table.selectionForeground = lazy(Tree.selectionForeground) -{Nord}TextField.selectionBackground = lazy(Tree.selectionBackground) -{Nord}TextField.selectionForeground = lazy(Tree.selectionForeground) -{Nord}Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground) +{Nord}RadioButtonMenuItem.selectionBackground = $MenuItem.selectionBackground +{Nord}ProgressBar.selectionBackground = @foreground +{Nord}ProgressBar.selectionForeground = @background +{Nord}List.selectionBackground = $Tree.selectionBackground +{Nord}List.selectionForeground = $Tree.selectionForeground +{Nord}Table.selectionBackground = $Tree.selectionBackground +{Nord}Table.selectionForeground = $Tree.selectionForeground +{Nord}TextField.selectionBackground = $Tree.selectionBackground +{Nord}TextField.selectionForeground = $Tree.selectionForeground +{Nord}Tree.selectionInactiveForeground = $List.selectionInactiveForeground {NotReallyMDTheme}*.selectionInactiveBackground = #21384E -{NotReallyMDTheme}ToolBar.separatorColor = lazy(Separator.foreground) +{NotReallyMDTheme}ToolBar.separatorColor = $Separator.foreground -{One_Dark}List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground) {One_Dark}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 {One_Dark}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 -{One_Dark}ProgressBar.background = lazy(Separator.foreground) -{One_Dark}Slider.trackColor = lazy(Separator.foreground) -{One_Dark}Slider.focusedColor = fade(#568af2,40%) -{One_Dark}Table.background = lazy(Tree.background) -{One_Dark}Table.selectionBackground = lazy(Tree.selectionBackground) -{One_Dark}TextField.selectionBackground = lazy(List.selectionBackground) -{One_Dark}Tree.selectionForeground = lazy(List.selectionForeground) +{One_Dark}ProgressBar.background = $Separator.foreground +{One_Dark}ProgressBar.selectionForeground = #fff +{One_Dark}Table.background = $Tree.background +{One_Dark}Table.selectionBackground = $Tree.selectionBackground +{One_Dark}TextField.selectionBackground = $List.selectionBackground +{One_Dark}Tree.selectionForeground = $List.selectionForeground -{Solarized_Dark---4lex4}*.inactiveForeground = #657B83 -{Solarized_Dark---4lex4}Component.accentColor = lazy(TabbedPane.underlineColor) -{Solarized_Dark---4lex4}ComboBox.background = lazy(ComboBox.editableBackground) -{Solarized_Dark---4lex4}ComboBox.buttonBackground = lazy(ComboBox.editableBackground) -{Solarized_Dark---4lex4}Slider.focusedColor = fade($Component.focusColor,80%,derived) -{Solarized_Dark---4lex4}ToolBar.separatorColor = lazy(Separator.foreground) +{Solarized_Dark---4lex4}@accentBaseColor = $TabbedPane.underlineColor +{Solarized_Dark---4lex4}*.acceleratorForeground = @menuAcceleratorForeground +{Solarized_Dark---4lex4}ComboBox.background = $ComboBox.editableBackground +{Solarized_Dark---4lex4}ComboBox.buttonBackground = $ComboBox.editableBackground +{Solarized_Dark---4lex4}Slider.disabledTrackColor = $ColorPalette.colorSeparator -{Solarized_Light---4lex4}*.inactiveForeground = #839496 -{Solarized_Light---4lex4}Button.default.hoverBackground = darken($Button.default.background,3%,derived) -{Solarized_Light---4lex4}Component.accentColor = lazy(TabbedPane.underlineColor) +{Solarized_Light---4lex4}@accentBaseColor = $TabbedPane.underlineColor +{Solarized_Light---4lex4}Slider.thumbColor = $ProgressBar.foreground +{Solarized_Light---4lex4}Slider.disabledTrackColor = $ColorPalette.colorSeparator {Spacegray}ComboBox.background = @ijTextBackgroundL4 -{Spacegray}ComboBox.buttonBackground = @ijTextBackgroundL4 +{Spacegray}ComboBox.buttonBackground = $ComboBox.background {Spacegray}TextField.background = @ijTextBackgroundL4 -{Spacegray}TextField.selectionBackground = lazy(Tree.selectionBackground) -{Spacegray}TextField.selectionForeground = lazy(Tree.selectionForeground) -{vuesion-theme}*.disabledForeground = #8C8C8C -{vuesion-theme}*.disabledText = #8C8C8C -{vuesion-theme}*.inactiveForeground = #8C8C8C -{vuesion-theme}Component.accentColor = lazy(Button.default.endBackground) +{vuesion-theme}@accentBaseColor = $TabbedPane.underlineColor +{vuesion-theme}@disabledForeground = #8C8C8C +{vuesion-theme}*.disabledText = @disabledForeground +{vuesion-theme}*.disabledForeground = @disabledForeground +{vuesion-theme}*.inactiveForeground = @disabledForeground {vuesion-theme}MenuItem.checkBackground = @ijMenuCheckBackgroundL10 {vuesion-theme}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10 -{vuesion-theme}Slider.trackValueColor = #ececee -{vuesion-theme}Slider.trackColor = #303a45 +{vuesion-theme}ProgressBar.background = #303a45 +{vuesion-theme}ProgressBar.foreground = #ececee {vuesion-theme}Slider.thumbColor = #ececee -{vuesion-theme}Slider.focusedColor = fade(#ececee,20%) +{vuesion-theme}Slider.focusedColor = fade($Slider.thumbColor,20%) {vuesion-theme}ComboBox.background = @ijTextBackgroundL4 -{vuesion-theme}ComboBox.buttonBackground = @ijTextBackgroundL4 +{vuesion-theme}ComboBox.buttonBackground = $ComboBox.background {vuesion-theme}TextField.background = @ijTextBackgroundL4 {vuesion-theme}TextField.selectionBackground = lighten(#303A45,15%) +{Xcode-Dark}@accentBaseColor = $List.selectionBackground {Xcode-Dark}TextField.background = @ijTextBackgroundL4 # Material Theme UI Lite -[light]{author-Mallowigi}MenuItem.checkBackground = @ijMenuCheckBackgroundD10 -[light]{author-Mallowigi}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundD10 -[dark]{author-Mallowigi}MenuItem.checkBackground = @ijMenuCheckBackgroundL20 -[dark]{author-Mallowigi}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20 +{author-Mallowigi}[light]controlHighlight = lighten($controlShadow,8%) +{author-Mallowigi}[light]controlLtHighlight = lighten($controlShadow,15%) +{author-Mallowigi}[light]controlDkShadow = darken($controlShadow,15%) +{author-Mallowigi}[dark]controlHighlight = darken($controlShadow,10%) +{author-Mallowigi}[dark]controlLtHighlight = darken($controlShadow,15%) +{author-Mallowigi}[dark]controlDkShadow = lighten($controlShadow,10%) -{author-Mallowigi}Tree.selectionInactiveBackground = lazy(List.selectionInactiveBackground) +{author-Mallowigi}Button.hoverBorderColor = $Button.focusedBorderColor +{author-Mallowigi}HelpButton.hoverBorderColor = $Button.focusedBorderColor -{Arc_Dark}ComboBox.selectionBackground = lazy(List.selectionBackground) -{Arc_Dark}Table.selectionBackground = lazy(List.selectionBackground) +{author-Mallowigi}[light]ToggleButton.selectedForeground = #000 +{author-Mallowigi}[dark]ToggleButton.selectedForeground = #fff -{Atom_One_Dark}Separator.foreground = lazy(Slider.trackColor) -{Atom_One_Dark}ToolBar.separatorColor = lazy(Slider.trackColor) +{author-Mallowigi}[light]MenuItem.checkBackground = @ijMenuCheckBackgroundD10 +{author-Mallowigi}[light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundD10 +{author-Mallowigi}[dark]MenuItem.checkBackground = @ijMenuCheckBackgroundL20 +{author-Mallowigi}[dark]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20 -{Atom_One_Light}List.selectionBackground = lazy(Table.selectionBackground) -{Atom_One_Light}Tree.selectionBackground = lazy(Table.selectionBackground) -{Atom_One_Light}TabbedPane.contentAreaColor = lazy(Separator.foreground) +{author-Mallowigi}[light]Separator.foreground = @ijSeparatorLight +{author-Mallowigi}[dark]Separator.foreground = @ijSeparatorDark +{author-Mallowigi}ProgressBar.selectionBackground = @foreground +{author-Mallowigi}TabbedPane.selectedBackground = mix(@background,$ColorPalette.table,60%) +{author-Mallowigi}ToolBar.separatorColor = $Separator.foreground +{author-Mallowigi}Button.foreground = @foreground +{author-Mallowigi}Tree.foreground = @foreground + + +{Arc_Dark}ComboBox.selectionBackground = $List.selectionBackground +{Arc_Dark}ProgressBar.selectionBackground = #fff +{Arc_Dark}ProgressBar.selectionForeground = #fff +{Arc_Dark}Table.selectionBackground = $List.selectionBackground +{Arc_Dark}Tree.selectionInactiveBackground = $List.selectionInactiveBackground + +{Atom_One_Dark}ProgressBar.selectionBackground = #fff +{Atom_One_Dark}ProgressBar.selectionForeground = #fff +{Atom_One_Dark}List.selectionBackground = $Table.selectionBackground +{Atom_One_Dark}Tree.selectionBackground = $Table.selectionBackground +{Atom_One_Dark}List.selectionInactiveBackground = $Tree.selectionInactiveBackground +{Atom_One_Dark}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground + +{Atom_One_Light}@disabledForeground = shade($ColorPalette.dis,20%) +{Atom_One_Light}*.disabledText = @disabledForeground +{Atom_One_Light}*.disabledForeground = @disabledForeground +{Atom_One_Light}*.inactiveForeground = @disabledForeground +{Atom_One_Light}TabbedPane.contentAreaColor = $Separator.foreground -{Dracula---Mallowigi}*.selectionBackground = #44475A -{Dracula---Mallowigi}List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground) {Dracula---Mallowigi}ProgressBar.selectionBackground = #fff {Dracula---Mallowigi}ProgressBar.selectionForeground = #fff -{Dracula---Mallowigi}RadioButtonMenuItem.selectionForeground = lazy(CheckBoxMenuItem.selectionForeground) -{Dracula---Mallowigi}Table.selectionForeground = lazy(List.selectionForeground) -{Dracula---Mallowigi}Separator.foreground = lazy(Slider.trackColor) -{Dracula---Mallowigi}ToolBar.separatorColor = lazy(Slider.trackColor) +{Dracula---Mallowigi}List.selectionBackground = $Table.selectionBackground +{Dracula---Mallowigi}Tree.selectionBackground = $Table.selectionBackground +{Dracula---Mallowigi}List.selectionInactiveBackground = $Tree.selectionInactiveBackground +{Dracula---Mallowigi}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground {GitHub}ProgressBar.selectionBackground = #222 {GitHub}ProgressBar.selectionForeground = #222 {GitHub}TextField.background = @ijTextBackgroundL3 -{GitHub}List.selectionBackground = lazy(Table.selectionBackground) -{GitHub}Tree.selectionBackground = lazy(Table.selectionBackground) +{GitHub}List.selectionBackground = $Table.selectionBackground +{GitHub}Tree.selectionBackground = $Table.selectionBackground +{GitHub}List.selectionInactiveBackground = $Tree.selectionInactiveBackground +{GitHub}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground -{GitHub_Dark}ComboBox.selectionBackground = lazy(Tree.selectionBackground) -{GitHub_Dark}Table.selectionBackground = lazy(Tree.selectionBackground) -{GitHub_Dark}Separator.foreground = lazy(Slider.trackColor) -{GitHub_Dark}ToolBar.separatorColor = lazy(Slider.trackColor) +{GitHub_Dark}ComboBox.selectionBackground = $Tree.selectionBackground +{GitHub_Dark}ProgressBar.selectionForeground = #fff +{GitHub_Dark}Slider.trackColor = lighten(#2b3036,5%) +{GitHub_Dark}Table.selectionBackground = $Tree.selectionBackground +{GitHub_Dark}Tree.selectionInactiveBackground = $Table.selectionInactiveBackground -{Light_Owl}CheckBoxMenuItem.selectionForeground = lazy(CheckBoxMenuItem.foreground) -{Light_Owl}ComboBox.selectionForeground = lazy(ComboBox.foreground) -{Light_Owl}List.selectionInactiveForeground = lazy(List.foreground) -{Light_Owl}Menu.selectionForeground = lazy(Menu.foreground) -{Light_Owl}MenuBar.selectionForeground = lazy(MenuBar.foreground) -{Light_Owl}MenuItem.selectionForeground = lazy(MenuItem.foreground) -{Light_Owl}ProgressBar.selectionBackground = #111 -{Light_Owl}ProgressBar.selectionForeground = #fff -{Light_Owl}Spinner.selectionForeground = lazy(Spinner.foreground) -{Light_Owl}Table.selectionForeground = lazy(Table.foreground) -{Light_Owl}TextField.selectionForeground = lazy(TextField.foreground) +{Light_Owl}@disabledForeground = shade($ColorPalette.dis,10%) +{Light_Owl}*.disabledText = @disabledForeground +{Light_Owl}*.disabledForeground = @disabledForeground +{Light_Owl}*.inactiveForeground = @disabledForeground +{Light_Owl}CheckBoxMenuItem.selectionForeground = $CheckBoxMenuItem.foreground +{Light_Owl}ComboBox.selectionForeground = $ComboBox.foreground +{Light_Owl}List.selectionInactiveForeground = $Table.selectionInactiveForeground +{Light_Owl}Menu.selectionForeground = $Menu.foreground +{Light_Owl}MenuBar.selectionForeground = $MenuBar.foreground +{Light_Owl}MenuItem.selectionForeground = $MenuItem.foreground +{Light_Owl}Table.selectionForeground = $List.selectionForeground +{Light_Owl}TextField.selectionForeground = $TextField.foreground {Light_Owl}TextField.background = @ijTextBackgroundL3 -{Light_Owl}List.selectionBackground = lazy(Table.selectionBackground) -{Light_Owl}Tree.selectionBackground = lazy(Table.selectionBackground) +{Light_Owl}List.selectionBackground = $Table.selectionBackground +{Light_Owl}Tree.selectionBackground = $Table.selectionBackground +{Light_Owl}List.selectionInactiveBackground = $Tree.selectionInactiveBackground +{Light_Owl}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground -{Material_Darker}*.selectionBackground = lighten(#2D2D2D,15%) -{Material_Darker}Separator.foreground = lazy(Slider.trackColor) -{Material_Darker}ToolBar.separatorColor = lazy(Slider.trackColor) +{Material_Darker}@disabledForeground = tint($ColorPalette.dis,30%) +{Material_Darker}*.disabledText = @disabledForeground +{Material_Darker}*.disabledForeground = @disabledForeground +{Material_Darker}*.inactiveForeground = @disabledForeground +{Material_Darker}*.selectionBackground = lighten($ColorPalette.tree,15%) +{Material_Darker}ProgressBar.selectionForeground = #fff +{Material_Darker}Tree.selectionInactiveBackground = $List.selectionInactiveBackground -{Material_Deep_Ocean}*.selectionBackground = lighten(#222533,15%) -{Material_Deep_Ocean}Separator.foreground = lazy(Slider.trackColor) -{Material_Deep_Ocean}ToolBar.separatorColor = lazy(Slider.trackColor) +{Material_Deep_Ocean}@disabledForeground = tint($ColorPalette.dis,10%) +{Material_Deep_Ocean}*.disabledText = @disabledForeground +{Material_Deep_Ocean}*.disabledForeground = @disabledForeground +{Material_Deep_Ocean}*.inactiveForeground = @disabledForeground +{Material_Deep_Ocean}*.selectionBackground = lighten($ColorPalette.tree,15%) +{Material_Deep_Ocean}ProgressBar.selectionBackground = #fff +{Material_Deep_Ocean}Slider.trackColor = lighten(#1A1C25,5%) +{Material_Deep_Ocean}Tree.selectionInactiveBackground = $List.selectionInactiveBackground -{Material_Lighter}List.selectionInactiveForeground = lazy(Tree.selectionInactiveForeground) +{Material_Lighter}@disabledForeground = shade($ColorPalette.dis,30%) +{Material_Lighter}*.disabledText = @disabledForeground +{Material_Lighter}*.disabledForeground = @disabledForeground +{Material_Lighter}*.inactiveForeground = @disabledForeground +{Material_Lighter}ComboBox.selectionBackground = $List.selectionBackground +{Material_Lighter}List.selectionForeground = $Table.selectionForeground +{Material_Lighter}List.selectionInactiveForeground = $Table.selectionInactiveForeground {Material_Lighter}ProgressBar.selectionBackground = #222 -{Material_Lighter}ProgressBar.selectionForeground = #fff -{Material_Lighter}ComboBox.selectionBackground = lazy(List.selectionBackground) -{Material_Lighter}Table.selectionBackground = lazy(List.selectionBackground) -{Material_Lighter}List.selectionForeground = lazy(Table.selectionForeground) -{Material_Lighter}RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground) -{Material_Lighter}Tree.selectionForeground = lazy(Table.selectionForeground) +{Material_Lighter}RadioButtonMenuItem.selectionForeground = $Table.selectionForeground +{Material_Lighter}Table.selectionBackground = $List.selectionBackground +{Material_Lighter}Tree.selectionForeground = $Table.selectionForeground +{Material_Lighter}Tree.selectionInactiveBackground = $List.selectionInactiveBackground +{Material_Oceanic}@disabledForeground = tint($ColorPalette.dis,30%) +{Material_Oceanic}*.disabledText = @disabledForeground +{Material_Oceanic}*.disabledForeground = @disabledForeground +{Material_Oceanic}*.inactiveForeground = @disabledForeground {Material_Oceanic}ProgressBar.selectionBackground = #ddd {Material_Oceanic}ProgressBar.selectionForeground = #ddd -{Material_Oceanic}Separator.foreground = lazy(Slider.trackColor) -{Material_Oceanic}ToolBar.separatorColor = lazy(Slider.trackColor) +{Material_Oceanic}List.selectionBackground = $Table.selectionBackground +{Material_Oceanic}Tree.selectionBackground = $Table.selectionBackground +{Material_Oceanic}List.selectionInactiveBackground = $Tree.selectionInactiveBackground +{Material_Oceanic}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground +{Material_Palenight}@disabledForeground = tint($ColorPalette.dis,20%) +{Material_Palenight}*.disabledText = @disabledForeground +{Material_Palenight}*.disabledForeground = @disabledForeground +{Material_Palenight}*.inactiveForeground = @disabledForeground {Material_Palenight}ProgressBar.selectionBackground = #ddd {Material_Palenight}ProgressBar.selectionForeground = #ddd -{Material_Palenight}List.selectionBackground = lazy(Table.selectionBackground) -{Material_Palenight}Tree.selectionBackground = lazy(Table.selectionBackground) -{Material_Palenight}Separator.foreground = lazy(Slider.trackColor) -{Material_Palenight}ToolBar.separatorColor = lazy(Slider.trackColor) +{Material_Palenight}List.selectionBackground = $Table.selectionBackground +{Material_Palenight}Tree.selectionBackground = $Table.selectionBackground +{Material_Palenight}List.selectionInactiveBackground = $Tree.selectionInactiveBackground +{Material_Palenight}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground -{Monokai_Pro---Mallowigi}List.selectionForeground = lazy(Table.selectionForeground) -{Monokai_Pro---Mallowigi}RadioButtonMenuItem.selectionForeground = lazy(Table.selectionForeground) -{Monokai_Pro---Mallowigi}Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground) -{Monokai_Pro---Mallowigi}Tree.selectionForeground = lazy(Table.selectionForeground) -{Monokai_Pro---Mallowigi}Tree.selectionInactiveForeground = lazy(List.selectionInactiveForeground) -{Monokai_Pro---Mallowigi}Separator.foreground = lazy(Slider.trackColor) -{Monokai_Pro---Mallowigi}ToolBar.separatorColor = lazy(Slider.trackColor) +{Monokai_Pro---Mallowigi}@disabledForeground = tint($ColorPalette.dis,20%) +{Monokai_Pro---Mallowigi}*.disabledText = @disabledForeground +{Monokai_Pro---Mallowigi}*.disabledForeground = @disabledForeground +{Monokai_Pro---Mallowigi}*.inactiveForeground = @disabledForeground +{Monokai_Pro---Mallowigi}RadioButtonMenuItem.selectionForeground = $MenuItem.selectionForeground +{Monokai_Pro---Mallowigi}List.selectionForeground = $Table.selectionForeground +{Monokai_Pro---Mallowigi}Tree.selectionForeground = $Table.selectionForeground +{Monokai_Pro---Mallowigi}List.selectionInactiveForeground = $Table.selectionInactiveForeground +{Monokai_Pro---Mallowigi}List.selectionBackground = $Table.selectionBackground +{Monokai_Pro---Mallowigi}Tree.selectionBackground = $Table.selectionBackground +{Monokai_Pro---Mallowigi}List.selectionInactiveBackground = $Tree.selectionInactiveBackground +{Monokai_Pro---Mallowigi}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground -{Moonlight}ComboBox.selectionBackground = lazy(List.selectionBackground) -{Moonlight}Table.selectionBackground = lazy(List.selectionBackground) -{Moonlight}Separator.foreground = lazy(Slider.trackColor) -{Moonlight}ToolBar.separatorColor = lazy(Slider.trackColor) - -{Night_Owl}ProgressBar.selectionBackground = #ddd -{Night_Owl}ProgressBar.selectionForeground = #ddd +{Moonlight}ComboBox.selectionBackground = $List.selectionBackground +{Moonlight}ProgressBar.selectionForeground = #000 +{Moonlight}Table.selectionBackground = $List.selectionBackground +{Moonlight}Tree.selectionInactiveBackground = $List.selectionInactiveBackground +{Solarized_Dark---Mallowigi}@disabledForeground = tint($ColorPalette.dis,20%) +{Solarized_Dark---Mallowigi}*.disabledForeground = @disabledForeground +{Solarized_Dark---Mallowigi}*.inactiveForeground = @disabledForeground +{Solarized_Dark---Mallowigi}*.disabledText = @disabledForeground {Solarized_Dark---Mallowigi}ProgressBar.selectionBackground = #ccc {Solarized_Dark---Mallowigi}ProgressBar.selectionForeground = #ccc -{Solarized_Dark---Mallowigi}Separator.foreground = lazy(Slider.trackColor) -{Solarized_Dark---Mallowigi}ToolBar.separatorColor = lazy(Slider.trackColor) +{Solarized_Dark---Mallowigi}Slider.trackColor = lighten(@background,10%) +{Solarized_Dark---Mallowigi}Table.selectionBackground = $List.selectionBackground +{Solarized_Dark---Mallowigi}Tree.selectionInactiveBackground = $List.selectionInactiveBackground +{Solarized_Light---Mallowigi}@disabledForeground = tint(@foreground,30%) +{Solarized_Light---Mallowigi}*.disabledForeground = @disabledForeground +{Solarized_Light---Mallowigi}*.inactiveForeground = @disabledForeground +{Solarized_Light---Mallowigi}*.disabledText = @disabledForeground {Solarized_Light---Mallowigi}ProgressBar.selectionBackground = #222 -{Solarized_Light---Mallowigi}ProgressBar.selectionForeground = #fff -{Solarized_Light---Mallowigi}ComboBox.selectionBackground = lazy(List.selectionBackground) -{Solarized_Light---Mallowigi}Table.selectionBackground = lazy(List.selectionBackground) -{Solarized_Light---Mallowigi}Separator.foreground = lazy(Slider.trackColor) -{Solarized_Light---Mallowigi}ToolBar.separatorColor = lazy(Slider.trackColor) +{Solarized_Light---Mallowigi}ComboBox.selectionBackground = $List.selectionBackground +{Solarized_Light---Mallowigi}Slider.disabledTrackColor = lighten($Slider.trackColor,5%) +{Solarized_Light---Mallowigi}Table.selectionBackground = $List.selectionBackground +{Solarized_Light---Mallowigi}Tree.selectionInactiveBackground = $List.selectionInactiveBackground +{Solarized_Light---Mallowigi}Button.toolbar.selectedBackground = darken($@background,15%) +{Solarized_Light---Mallowigi}ToggleButton.toolbar.selectedBackground = $Button.toolbar.selectedBackground diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java index 3bbd0ccf..22349eed 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoPrefs.java @@ -52,6 +52,8 @@ public class DemoPrefs } public static void setupLaf( String[] args ) { +// com.formdev.flatlaf.demo.intellijthemes.IJThemesDump.install(); + // set look and feel try { if( args.length > 0 ) diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesDump.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesDump.java new file mode 100644 index 00000000..bfe25480 --- /dev/null +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesDump.java @@ -0,0 +1,118 @@ +/* + * Copyright 2025 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.demo.intellijthemes; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; +import javax.swing.LookAndFeel; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.IntelliJTheme; +import com.formdev.flatlaf.util.LoggingFacade; + +/** + * @author Karl Tauber + */ +public class IJThemesDump +{ + // same as UIDefaultsLoader.KEY_PROPERTIES + private static final String KEY_PROPERTIES = "FlatLaf.internal.properties"; + + public static void enablePropertiesRecording() { + System.setProperty( KEY_PROPERTIES, "true" ); + } + + public static void install() { + enablePropertiesRecording(); + + UIManager.addPropertyChangeListener( e -> { + if( "lookAndFeel".equals( e.getPropertyName() ) ) { + LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); + if( lookAndFeel instanceof IntelliJTheme.ThemeLaf ) { + IntelliJTheme theme = (lookAndFeel.getClass() == IntelliJTheme.ThemeLaf.class) + ? ((IntelliJTheme.ThemeLaf)lookAndFeel).getTheme() + : null; + String name = (theme != null) ? theme.name : lookAndFeel.getClass().getSimpleName(); + File dir = new File( "dumps/properties" ); + dumpProperties( dir, name, UIManager.getLookAndFeelDefaults() ); + } + } + } ); + } + + public static void dumpProperties( File dir, String name, UIDefaults defaults ) { + String content = dumpPropertiesToString( defaults ); + if( content == null ) + return; + + // write to file + File file = new File( dir, name + ".properties" ); + file.getParentFile().mkdirs(); + try( Writer fileWriter = new OutputStreamWriter( + new FileOutputStream( file ), StandardCharsets.UTF_8 ) ) + { + fileWriter.write( content ); + } catch( IOException ex ) { + LoggingFacade.INSTANCE.logSevere( null, ex ); + } + } + + public static String dumpPropertiesToString( UIDefaults defaults ) { + Properties properties = (Properties) defaults.get( KEY_PROPERTIES ); + if( properties == null ) + return null; + + // dump to string + StringWriter stringWriter = new StringWriter( 100000 ); + PrintWriter out = new PrintWriter( stringWriter ); + out.printf( "@baseTheme = %s%n", FlatLaf.isLafDark() ? "dark" : "light" ); + AtomicReference lastPrefix = new AtomicReference<>(); + properties.entrySet().stream() + .sorted( (e1, e2) -> ((String)e1.getKey()).compareTo( (String) e2.getKey() ) ) + .forEach( e -> { + String key = (String) e.getKey(); + String value = (String) e.getValue(); + String prefix = keyPrefix( key ); + if( !prefix.equals( lastPrefix.get() ) ) { + lastPrefix.set( prefix ); + out.printf( "%n%n#---- %s ----%n%n", prefix ); + } + + out.printf( "%-50s = %s%n", key, value.replace( ";", "; \\\n\t" ) ); + } ); + + return stringWriter.toString().replace( "\r", "" ); + } + + private static String keyPrefix( String key ) { + int dotIndex = key.indexOf( '.' ); + return (dotIndex > 0) + ? key.substring( 0, dotIndex ) + : key.endsWith( "UI" ) + ? key.substring( 0, key.length() - 2 ) + : ""; + } +} diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java index 5c8d716c..0524ce9a 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/intellijthemes/IJThemesPanel.java @@ -276,20 +276,21 @@ public class IJThemesPanel return; EventQueue.invokeLater( () -> { - setTheme( themeInfo ); + setTheme( themeInfo, false ); } ); } - private void setTheme( IJThemeInfo themeInfo ) { + private void setTheme( IJThemeInfo themeInfo, boolean reload ) { if( themeInfo == null ) return; // change look and feel if( themeInfo.lafClassName != null ) { - if( themeInfo.lafClassName.equals( UIManager.getLookAndFeel().getClass().getName() ) ) + if( !reload && themeInfo.lafClassName.equals( UIManager.getLookAndFeel().getClass().getName() ) ) return; - FlatAnimatedLafChange.showSnapshot(); + if( !reload ) + FlatAnimatedLafChange.showSnapshot(); try { UIManager.setLookAndFeel( themeInfo.lafClassName ); @@ -298,7 +299,8 @@ public class IJThemesPanel showInformationDialog( "Failed to create '" + themeInfo.lafClassName + "'.", ex ); } } else if( themeInfo.themeFile != null ) { - FlatAnimatedLafChange.showSnapshot(); + if( !reload ) + FlatAnimatedLafChange.showSnapshot(); try { if( themeInfo.themeFile.getName().endsWith( ".properties" ) ) @@ -320,7 +322,9 @@ public class IJThemesPanel // update all components FlatLaf.updateUI(); - FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + if( !reload ) + FlatAnimatedLafChange.hideSnapshotWithAnimation(); } private void browsePlugin() { @@ -386,8 +390,8 @@ public class IJThemesPanel // use invokeLater() because KEY_LAF_THEME_FILE is updated after this event EventQueue.invokeLater( () -> { selectedCurrentLookAndFeel(); + lastLafChangeTime = System.currentTimeMillis(); } ); - lastLafChangeTime = System.currentTimeMillis(); } } @@ -435,7 +439,7 @@ public class IJThemesPanel } if( reload ) - setTheme( themesList.getSelectedValue() ); + setTheme( themesList.getSelectedValue(), true ); } } } diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt index 66b6a9df..d2a2bca5 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarculaLaf_1.8.0.txt @@ -76,7 +76,7 @@ + ProgressBar.foreground #c4c4c4 HSL 0 0 77 javax.swing.plaf.ColorUIResource [UI] - ProgressBar.selectionForeground #eeeeee HSL 0 0 93 javax.swing.plaf.ColorUIResource [UI] -+ ProgressBar.selectionForeground #3c3f41 HSL 204 4 25 javax.swing.plaf.ColorUIResource [UI] ++ ProgressBar.selectionForeground #1e2021 HSL 200 5 12 javax.swing.plaf.ColorUIResource [UI] #---- RadioButton ---- @@ -121,4 +121,4 @@ + contrast ratio: ProgressBar.foreground #c4c4c4 #3c3f41 6.1 ! - contrast ratio: ProgressBar.selectionForeground #eeeeee #4c87c8 3.2 !!!! -+ contrast ratio: ProgressBar.selectionForeground #3c3f41 #c4c4c4 6.1 ! ++ contrast ratio: ProgressBar.selectionForeground #1e2021 #c4c4c4 9.4 diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsDump.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsDump.java index e723e7f1..61fcba20 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsDump.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/uidefaults/UIDefaultsDump.java @@ -60,6 +60,7 @@ import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicLookAndFeel; import javax.swing.table.JTableHeader; import com.formdev.flatlaf.*; +import com.formdev.flatlaf.demo.intellijthemes.IJThemesDump; import com.formdev.flatlaf.intellijthemes.FlatAllIJThemes; import com.formdev.flatlaf.testing.FlatTestLaf; import com.formdev.flatlaf.themes.*; @@ -155,6 +156,8 @@ public class UIDefaultsDump private static void dumpIntelliJThemes( File dir ) { dir = new File( dir, "intellijthemes" ); + IJThemesDump.enablePropertiesRecording(); + for( LookAndFeelInfo info : FlatAllIJThemes.INFOS ) { String lafClassName = info.getClassName(); String relativeLafClassName = StringUtils.removeLeading( lafClassName, "com.formdev.flatlaf.intellijthemes." ); @@ -192,6 +195,15 @@ public class UIDefaultsDump dump( dir, "_InputMap", lookAndFeel, defaults, key -> key.contains( "InputMap" ), false ); dumpActionMaps( dir, "_ActionMap", lookAndFeel, defaults ); } + + if( lookAndFeel instanceof IntelliJTheme.ThemeLaf ) { + File cdir = new File( dir.getPath().replace( "intellijthemes", "intellijthemes-colors" ) ); + dumpColorsToProperties( cdir, lookAndFeel, defaults ); + + // dump as .properties + File pdir = new File( dir.getPath().replace( "intellijthemes", "intellijthemes-properties" ) ); + IJThemesDump.dumpProperties( pdir, lookAndFeel.getClass().getSimpleName(), defaults ); + } } private static void dump( File dir, String nameSuffix, @@ -231,8 +243,8 @@ public class UIDefaultsDump if( origFile != null ) { try { Map defaults1 = parse( new InputStreamReader( - new FileInputStream( origFile ), StandardCharsets.UTF_8 ) ); - Map defaults2 = parse( new StringReader( stringWriter.toString() ) ); + new FileInputStream( origFile ), StandardCharsets.UTF_8 ), false ); + Map defaults2 = parse( new StringReader( stringWriter.toString() ), false ); content = diff( defaults1, defaults2 ); } catch( Exception ex ) { @@ -280,6 +292,45 @@ public class UIDefaultsDump } } + private static void dumpColorsToProperties( File dir, LookAndFeel lookAndFeel, UIDefaults defaults ) { + // dump to string + StringWriter stringWriter = new StringWriter( 100000 ); + new UIDefaultsDump( lookAndFeel, defaults ).dumpColorsAsProperties( new PrintWriter( stringWriter ) ); + + String name = lookAndFeel instanceof MyBasicLookAndFeel + ? BasicLookAndFeel.class.getSimpleName() + : lookAndFeel.getClass().getSimpleName(); + File file = new File( dir, name + ".properties" ); + + // build and append differences + if( file.exists() ) { + try { + Map defaults1 = parse( new InputStreamReader( + new FileInputStream( file ), StandardCharsets.UTF_8 ), true ); + Map defaults2 = parse( new StringReader( stringWriter.toString() ), true ); + + String diff = diff( defaults1, defaults2 ); + if( !diff.isEmpty() ) { + stringWriter.write( "\n\n\n\n#==== Differences ==============================================================\n\n" ); + stringWriter.write( diff ); + } + } catch( Exception ex ) { + ex.printStackTrace(); + return; + } + } + + // write to file + file.getParentFile().mkdirs(); + try( Writer fileWriter = new OutputStreamWriter( + new FileOutputStream( file ), StandardCharsets.UTF_8 ) ) + { + fileWriter.write( stringWriter.toString().replace( "\r", "" ) ); + } catch( IOException ex ) { + ex.printStackTrace(); + } + } + private static String diff( Map defaults1, Map defaults2 ) { TreeSet keys = new TreeSet<>(); keys.addAll( defaults1.keySet() ); @@ -355,7 +406,7 @@ public class UIDefaultsDump buf.append( '\n' ); } - private static Map parse( Reader in ) throws IOException { + private static Map parse( Reader in, boolean ignoreDiffs ) throws IOException { Map defaults = new LinkedHashMap<>(); try( BufferedReader reader = new BufferedReader( in ) ) { String lastKey = null; @@ -371,6 +422,9 @@ public class UIDefaultsDump continue; } + if( ignoreDiffs && (trimmedLine.startsWith( "- " ) || trimmedLine.startsWith( "+ " )) ) + continue; + if( Character.isWhitespace( line.charAt( 0 ) ) ) { String value = defaults.get( lastKey ); value += '\n' + line; @@ -443,6 +497,30 @@ public class UIDefaultsDump dumpContrastRatios( out ); } + private void dumpColorsAsProperties( PrintWriter out ) { + defaults.keySet().stream() + .sorted( (key1, key2) -> { + return String.valueOf( key1 ).compareTo( String.valueOf( key2 ) ); + } ) + .forEach( key -> { + Color color = defaults.getColor( key ); + if( color == null ) + return; + + String strKey = String.valueOf( key ); + String prefix = keyPrefix( strKey ); + if( !prefix.equals( lastPrefix ) ) { + lastPrefix = prefix; + out.printf( "%n%n#---- %s ----%n%n", prefix ); + } + + out.printf( "%-50s = #%06x", strKey, color.getRGB() & 0xffffff ); + if( color.getAlpha() != 255 ) + out.printf( "%02x", (color.getRGB() >> 24) & 0xff ); + out.println(); + } ); + } + private void dumpActionMaps( PrintWriter out ) { dumpHeader( out );