mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-11 14:37:13 -06:00
Merge main into system-file-chooser
This commit is contained in:
@@ -220,6 +220,7 @@ public interface FlatClientProperties
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #OUTLINE_ERROR},
|
||||
* {@link #OUTLINE_WARNING},
|
||||
* {@link #OUTLINE_SUCCESS},
|
||||
* any color (type {@link java.awt.Color}) or
|
||||
* an array of two colors (type {@link java.awt.Color}[2]) where the first color
|
||||
* is for focused state and the second for unfocused state
|
||||
@@ -240,6 +241,14 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String OUTLINE_WARNING = "warning";
|
||||
|
||||
/**
|
||||
* Paint the component border in another color (usually greenish) to indicate a success.
|
||||
*
|
||||
* @see #OUTLINE
|
||||
* @since 3.6
|
||||
*/
|
||||
String OUTLINE_SUCCESS = "success";
|
||||
|
||||
/**
|
||||
* Specifies a callback that is invoked to check whether a component is permanent focus owner.
|
||||
* Used to paint focus indicators.
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -44,6 +45,7 @@ import java.util.MissingResourceException;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
@@ -100,6 +102,8 @@ public abstract class FlatLaf
|
||||
private static Map<String, String> globalExtraDefaults;
|
||||
private Map<String, String> extraDefaults;
|
||||
private static Function<String, Color> systemColorGetter;
|
||||
private static Set<String> uiKeyPlatformPrefixes;
|
||||
private static Set<String> uiKeySpecialPrefixes;
|
||||
|
||||
private String desktopPropertyName;
|
||||
private String desktopPropertyName2;
|
||||
@@ -111,6 +115,7 @@ public abstract class FlatLaf
|
||||
private PopupFactory oldPopupFactory;
|
||||
private MnemonicHandler mnemonicHandler;
|
||||
private boolean subMenuUsabilityHelperInstalled;
|
||||
private LinuxPopupMenuCanceler linuxPopupMenuCanceler;
|
||||
|
||||
private Consumer<UIDefaults> postInitialization;
|
||||
private List<Function<Object, Object>> uiDefaultsGetters;
|
||||
@@ -305,6 +310,10 @@ public abstract class FlatLaf
|
||||
// install submenu usability helper
|
||||
subMenuUsabilityHelperInstalled = SubMenuUsabilityHelper.install();
|
||||
|
||||
// install Linux popup menu canceler
|
||||
if( SystemInfo.isLinux )
|
||||
linuxPopupMenuCanceler = new LinuxPopupMenuCanceler();
|
||||
|
||||
// listen to desktop property changes to update UI if system font or scaling changes
|
||||
if( SystemInfo.isWindows ) {
|
||||
// Windows 10 allows increasing font size independent of scaling:
|
||||
@@ -397,6 +406,12 @@ public abstract class FlatLaf
|
||||
subMenuUsabilityHelperInstalled = false;
|
||||
}
|
||||
|
||||
// uninstall Linux popup menu canceler
|
||||
if( linuxPopupMenuCanceler != null ) {
|
||||
linuxPopupMenuCanceler.uninstall();
|
||||
linuxPopupMenuCanceler = null;
|
||||
}
|
||||
|
||||
// restore default link color
|
||||
new HTMLEditorKit().getStyleSheet().addRule( "a, address { color: blue; }" );
|
||||
postInitialization = null;
|
||||
@@ -510,10 +525,10 @@ public abstract class FlatLaf
|
||||
|
||||
// load defaults from properties
|
||||
List<Class<?>> 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
|
||||
@@ -530,9 +545,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 );
|
||||
@@ -542,6 +554,9 @@ public abstract class FlatLaf
|
||||
return UIScale.getUserScaleFactor();
|
||||
} );
|
||||
|
||||
// add lazy UI delegate class loading (if necessary)
|
||||
addLazyUIdelegateClassLoading( defaults );
|
||||
|
||||
if( postInitialization != null ) {
|
||||
postInitialization.accept( defaults );
|
||||
postInitialization = null;
|
||||
@@ -550,7 +565,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<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
@@ -739,6 +755,53 @@ public abstract class FlatLaf
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle UI delegate classes if running in special application where multiple class loaders are involved.
|
||||
* E.g. in Eclipse plugin or in LibreOffice extension.
|
||||
* <p>
|
||||
* Problem: Swing runs in Java's system classloader and FlatLaf is loaded in plugin classloader.
|
||||
* When Swing tries to load UI delegate class in {@link UIDefaults#getUIClass(String, ClassLoader)},
|
||||
* invoked from {@link UIDefaults#getUI(JComponent)}, it uses the component's classloader,
|
||||
* which is Java's system classloader for core Swing components,
|
||||
* and can not find FlatLaf UI delegates.
|
||||
* <p>
|
||||
* Solution: Add lazy values for UI delegate class names.
|
||||
* Those lazy values use FlatLaf classloader to load UI delegate class.
|
||||
* This is similar to what {@link UIDefaults#getUIClass(String, ClassLoader)} does.
|
||||
* <p>
|
||||
* Not using {@code defaults.put( "ClassLoader", FlatLaf.class.getClassLoader() )},
|
||||
* which would work for FlatLaf UI delegates, but it would break custom
|
||||
* UI delegates used in other classloaders.
|
||||
*/
|
||||
private static void addLazyUIdelegateClassLoading( UIDefaults defaults ) {
|
||||
if( FlatLaf.class.getClassLoader() == ClassLoader.getSystemClassLoader() )
|
||||
return; // not necessary
|
||||
|
||||
Map<String, LazyValue> map = new HashMap<>();
|
||||
for( Map.Entry<Object, Object> e : defaults.entrySet() ) {
|
||||
Object key = e.getKey();
|
||||
Object value = e.getValue();
|
||||
if( key instanceof String && ((String)key).endsWith( "UI" ) &&
|
||||
value instanceof String && !defaults.containsKey( value ) )
|
||||
{
|
||||
String className = (String) value;
|
||||
map.put( className, (LazyValue) t -> {
|
||||
try {
|
||||
Class<?> uiClass = FlatLaf.class.getClassLoader().loadClass( className );
|
||||
if( ComponentUI.class.isAssignableFrom( uiClass ) )
|
||||
return uiClass;
|
||||
} catch( ClassNotFoundException ex ) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// let UIDefaults.getUIClass() try to load UI delegate class
|
||||
return null;
|
||||
} );
|
||||
}
|
||||
}
|
||||
defaults.putAll( map );
|
||||
}
|
||||
|
||||
private void putAATextInfo( UIDefaults defaults ) {
|
||||
if ( SystemInfo.isMacOS && SystemInfo.isJetBrainsJVM ) {
|
||||
// The awt.font.desktophints property suggests sub-pixel anti-aliasing
|
||||
@@ -1063,6 +1126,92 @@ public abstract class FlatLaf
|
||||
FlatLaf.systemColorGetter = systemColorGetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns UI key prefix, used in FlatLaf properties files, for light or dark themes.
|
||||
* Return value is either {@code [light]} or {@code [dark]}.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public static String getUIKeyLightOrDarkPrefix( boolean dark ) {
|
||||
return dark ? "[dark]" : "[light]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns set of UI key prefixes, used in FlatLaf properties files, for current platform.
|
||||
* If UI keys in properties files start with a prefix (e.g. {@code [someprefix]Button.background}),
|
||||
* then they are only used if that prefix is contained in this set
|
||||
* (or is one of {@code [light]} or {@code [dark]} depending on current theme).
|
||||
* <p>
|
||||
* By default, the set contains one or more of following prefixes:
|
||||
* <ul>
|
||||
* <li>{@code [win]} on Windows
|
||||
* <li>{@code [mac]} on macOS
|
||||
* <li>{@code [linux]} on Linux
|
||||
* <li>{@code [unknown]} on other platforms
|
||||
* <li>{@code [gnome]} on Linux with GNOME desktop environment
|
||||
* <li>{@code [kde]} on Linux with KDE desktop environment
|
||||
* <li>on Linux, the value of the environment variable {@code XDG_CURRENT_DESKTOP},
|
||||
* split at colons and converted to lower case (e.g. if value of {@code XDG_CURRENT_DESKTOP}
|
||||
* is {@code ubuntu:GNOME}, then {@code [ubuntu]} and {@code [gnome]})
|
||||
* </ul>
|
||||
* <p>
|
||||
* You can add own prefixes to the set.
|
||||
* The prefixes must start with '[' and end with ']' characters, otherwise they will be ignored.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public static Set<String> getUIKeyPlatformPrefixes() {
|
||||
if( uiKeyPlatformPrefixes == null ) {
|
||||
uiKeyPlatformPrefixes = new HashSet<>();
|
||||
uiKeyPlatformPrefixes.add(
|
||||
SystemInfo.isWindows ? "[win]" :
|
||||
SystemInfo.isMacOS ? "[mac]" :
|
||||
SystemInfo.isLinux ? "[linux]" : "[unknown]" );
|
||||
|
||||
// Linux
|
||||
if( SystemInfo.isLinux ) {
|
||||
if( SystemInfo.isGNOME )
|
||||
uiKeyPlatformPrefixes.add( "[gnome]" );
|
||||
else if( SystemInfo.isKDE )
|
||||
uiKeyPlatformPrefixes.add( "[kde]" );
|
||||
|
||||
// add values from XDG_CURRENT_DESKTOP for other desktops
|
||||
String desktop = System.getenv( "XDG_CURRENT_DESKTOP" );
|
||||
if( desktop != null ) {
|
||||
// XDG_CURRENT_DESKTOP is a colon-separated list of strings
|
||||
// https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html#key-onlyshowin
|
||||
// e.g. "ubuntu:GNOME" on Ubuntu 24.10 or "GNOME-Classic:GNOME" on CentOS 7
|
||||
for( String desk : StringUtils.split( desktop.toLowerCase( Locale.ENGLISH ), ':', true, true ) )
|
||||
uiKeyPlatformPrefixes.add( '[' + desk + ']' );
|
||||
}
|
||||
}
|
||||
}
|
||||
return uiKeyPlatformPrefixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns set of special UI key prefixes, used in FlatLaf properties files.
|
||||
* Unlike other prefixes, properties with special prefixes are preserved.
|
||||
* You can access them using `UIManager`. E.g. `UIManager.get( "[someSpecialPrefix]someKey" )`.
|
||||
* <p>
|
||||
* By default, the set contains following special prefixes:
|
||||
* <ul>
|
||||
* <li>{@code [style]}
|
||||
* </ul>
|
||||
* <p>
|
||||
* You can add own prefixes to the set.
|
||||
* The prefixes must start with '[' and end with ']' characters, otherwise they will be ignored.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public static Set<String> getUIKeySpecialPrefixes() {
|
||||
if( uiKeySpecialPrefixes == null ) {
|
||||
uiKeySpecialPrefixes = new HashSet<>();
|
||||
uiKeySpecialPrefixes.add( "[style]" );
|
||||
}
|
||||
return uiKeySpecialPrefixes;
|
||||
}
|
||||
|
||||
private static void reSetLookAndFeel() {
|
||||
EventQueue.invokeLater( () -> {
|
||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||
|
||||
@@ -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<String, String> jsonColors;
|
||||
private Map<String, Object> jsonUI;
|
||||
private Map<String, Object> jsonIcons;
|
||||
|
||||
private Map<String, String> colors;
|
||||
private Map<String, Object> ui;
|
||||
private Map<String, Object> icons;
|
||||
|
||||
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
||||
private Map<String, String> 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<String, String>) json.get( "colors" );
|
||||
ui = (Map<String, Object>) json.get( "ui" );
|
||||
icons = (Map<String, Object>) json.get( "icons" );
|
||||
jsonColors = (Map<String, String>) json.get( "colors" );
|
||||
jsonUI = (Map<String, Object>) json.get( "ui" );
|
||||
jsonIcons = (Map<String, Object>) 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<Object, Object> themeSpecificDefaults = removeThemeSpecificDefaults( defaults );
|
||||
Map<String, String> themeSpecificProps = removeThemeSpecificProps( properties );
|
||||
Set<String> jsonUIKeys = new HashSet<>();
|
||||
|
||||
loadNamedColors( defaults );
|
||||
// Json node "colors"
|
||||
loadNamedColors( properties, jsonUIKeys );
|
||||
|
||||
// convert Json "ui" structure to UI defaults
|
||||
ArrayList<Object> defaultsKeysCache = new ArrayList<>();
|
||||
Set<String> uiKeys = new HashSet<>();
|
||||
for( Map.Entry<String, Object> e : ui.entrySet() )
|
||||
apply( e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
||||
// convert Json "ui" structure to UI properties
|
||||
for( Map.Entry<String, Object> 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<String, String> 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<String, Object> wildcards = new HashMap<>();
|
||||
Iterator<Entry<Object, Object>> it = themeSpecificDefaults.entrySet().iterator();
|
||||
// get (and remove) theme specific wildcard replacements, which override all other properties that end with same suffix
|
||||
HashMap<String, String> wildcardProps = new HashMap<>();
|
||||
Iterator<Map.Entry<String, String>> it = themeSpecificProps.entrySet().iterator();
|
||||
while( it.hasNext() ) {
|
||||
Entry<Object, Object> e = it.next();
|
||||
String key = (String) e.getKey();
|
||||
Map.Entry<String, String> 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<String, String> e : wildcardProps.entrySet() )
|
||||
applyWildcard( properties, e.getKey(), e.getValue() );
|
||||
}
|
||||
|
||||
// apply theme specific UI defaults at the end to allow overwriting
|
||||
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
||||
Object key = e.getKey();
|
||||
Object value = e.getValue();
|
||||
// apply theme specific properties at the end to allow overwriting
|
||||
for( Map.Entry<String, String> 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<Object, Object> themeSpecificDefaults, String key ) {
|
||||
return themeSpecificDefaults.getOrDefault( key, defaults.get( key ) );
|
||||
private String get( Properties properties, Map<String, String> 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<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||
// search for theme specific UI defaults keys
|
||||
private void copyIfSetInJson( Properties properties, Set<String> 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<String> jsonUIKeys, String startKey, String endKey, String key ) {
|
||||
if( jsonUIKeys.contains( startKey ) && jsonUIKeys.contains( endKey ) )
|
||||
put( properties, key, "$" + startKey );
|
||||
}
|
||||
|
||||
private Map<String, String> removeThemeSpecificProps( Properties properties ) {
|
||||
// search for theme specific properties keys
|
||||
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && ((String)key).startsWith( "[" ) && !((String)key).startsWith( "[style]" ) )
|
||||
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<Object, Object> themeSpecificDefaults = new HashMap<>();
|
||||
String currentThemePrefix = '[' + name.replace( ' ', '_' ) + ']';
|
||||
String currentThemeAndAuthorPrefix = '[' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + ']';
|
||||
String currentAuthorPrefix = "[author-" + author.replace( ' ', '_' ) + ']';
|
||||
String allThemesPrefix = "[*]";
|
||||
String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, allThemesPrefix };
|
||||
// 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, lightOrDarkPrefix, allThemesPrefix };
|
||||
|
||||
// collect values for special prefixes in its own maps
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Map<String, String>[] 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<String, String> 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<String> jsonUIKeys ) {
|
||||
if( jsonColors == null )
|
||||
return;
|
||||
|
||||
namedColors = new HashMap<>();
|
||||
|
||||
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
||||
for( Map.Entry<String, String> 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<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
||||
private void apply( String key, Object value, Properties properties, Set<String> jsonUIKeys ) {
|
||||
if( value instanceof Map ) {
|
||||
Map<String, Object> map = (Map<String, Object>)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<String, Object> 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<Object> 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<String, Object> 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<String> uiKeys ) {
|
||||
if( !uiKeys.contains( destKey ) )
|
||||
defaults.put( destKey, defaults.get( srcKey ) );
|
||||
}
|
||||
|
||||
private static final Set<String> uiKeyExcludes;
|
||||
private static final Set<String> uiKeyDoNotOverride;
|
||||
/** Rename UI default keys (key --> value). */
|
||||
@@ -653,26 +672,27 @@ public class IntelliJTheme
|
||||
uiKeyExcludes = new HashSet<>( Arrays.asList(
|
||||
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
|
||||
"AvailableMnemonic.",
|
||||
"BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
||||
"Badge.", "Banner.", "BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
||||
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
|
||||
"Canvas.", "CodeWithMe.", "ComboBoxButton.", "CompletionPopup.", "ComplexPopup.", "Content.",
|
||||
"CurrentMnemonic.", "Counter.",
|
||||
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "DragAndDrop.",
|
||||
"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.",
|
||||
"Lesson.", "Link.", "LiveIndicator.",
|
||||
"MainMenu.", "MainToolbar.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
||||
"IconBadge.", "InformationHint.", "InlineBanner.", "InplaceRefactoringPopup.",
|
||||
"Lesson.", "LineProfiler.", "Link.", "LiveIndicator.",
|
||||
"MainMenu.", "MainToolbar.", "MainWindow.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
||||
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
|
||||
"OnePixelDivider.", "OptionButton.", "Outline.",
|
||||
"ParameterInfo.", "Plugins.", "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.",
|
||||
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.",
|
||||
"StatusBar.", "StripeToolbar.",
|
||||
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.", "TrialWidget.",
|
||||
"UIDesigner.", "UnattendedHostStatus.",
|
||||
"ValidationTooltip.", "VersionControl.",
|
||||
"WelcomeScreen.",
|
||||
@@ -688,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
|
||||
@@ -696,14 +719,17 @@ 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" );
|
||||
uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" );
|
||||
uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" );
|
||||
uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" );
|
||||
uiKeyMapping.put( "Component.inactiveSuccessFocusColor", "Component.success.borderColor" );
|
||||
uiKeyMapping.put( "Component.successFocusColor", "Component.success.focusedBorderColor" );
|
||||
|
||||
// Label
|
||||
uiKeyMapping.put( "Label.disabledForegroundColor", "" ); // ignore (used in Material Theme UI Lite)
|
||||
|
||||
// Link
|
||||
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
|
||||
@@ -711,10 +737,7 @@ public class IntelliJTheme
|
||||
// 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" );
|
||||
@@ -722,13 +745,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" );
|
||||
@@ -738,34 +759,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<String, String> 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" );
|
||||
@@ -818,17 +835,15 @@ public class IntelliJTheme
|
||||
}
|
||||
|
||||
@Override
|
||||
void applyAdditionalDefaults( UIDefaults defaults ) {
|
||||
theme.applyProperties( defaults );
|
||||
void applyAdditionalProperties( Properties properties ) {
|
||||
theme.applyProperties( properties );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
ArrayList<Class<?>> 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<Class<?>> lafClasses = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() );
|
||||
lafClasses.add( 1, theme.dark ? FlatDarkLaf.class : FlatLightLaf.class );
|
||||
lafClasses.add( 2, theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
|
||||
return lafClasses;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
/**
|
||||
* Cancels (hides) popup menus on Linux.
|
||||
* <p>
|
||||
* On Linux, popups are not hidden under following conditions, which results in
|
||||
* misplaced popups:
|
||||
* <ul>
|
||||
* <li>window moved or resized
|
||||
* <li>window maximized or restored
|
||||
* <li>window iconified
|
||||
* <li>window deactivated (e.g. activated other application)
|
||||
* </ul>
|
||||
*
|
||||
* On Windows and macOS, popups are automatically hidden.
|
||||
* <p>
|
||||
* The implementation is similar to what's done in
|
||||
* {@code javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber},
|
||||
* but only hides popup in some conditions.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class LinuxPopupMenuCanceler
|
||||
extends WindowAdapter
|
||||
implements ChangeListener, ComponentListener
|
||||
{
|
||||
private MenuElement[] lastPathSelectedPath;
|
||||
private Window window;
|
||||
|
||||
LinuxPopupMenuCanceler() {
|
||||
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
|
||||
msm.addChangeListener( this );
|
||||
|
||||
lastPathSelectedPath = msm.getSelectedPath();
|
||||
if( lastPathSelectedPath.length > 0 )
|
||||
addWindowListeners( lastPathSelectedPath[0] );
|
||||
}
|
||||
|
||||
void uninstall() {
|
||||
MenuSelectionManager.defaultManager().removeChangeListener( this );
|
||||
}
|
||||
|
||||
private void addWindowListeners( MenuElement selected ) {
|
||||
// see BasicPopupMenuUI.MouseGrabber.grabWindow()
|
||||
Component invoker = selected.getComponent();
|
||||
if( invoker instanceof JPopupMenu )
|
||||
invoker = ((JPopupMenu)invoker).getInvoker();
|
||||
window = (invoker instanceof Window)
|
||||
? (Window) invoker
|
||||
: SwingUtilities.windowForComponent( invoker );
|
||||
|
||||
if( window != null ) {
|
||||
window.addWindowListener( this );
|
||||
window.addComponentListener( this );
|
||||
}
|
||||
}
|
||||
|
||||
private void removeWindowListeners() {
|
||||
if( window != null ) {
|
||||
window.removeWindowListener( this );
|
||||
window.removeComponentListener( this );
|
||||
window = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelPopupMenu() {
|
||||
try {
|
||||
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
|
||||
MenuElement[] selectedPath = msm.getSelectedPath();
|
||||
for( MenuElement e : selectedPath ) {
|
||||
if( e instanceof JPopupMenu )
|
||||
((JPopupMenu)e).putClientProperty( "JPopupMenu.firePopupMenuCanceled", true );
|
||||
}
|
||||
msm.clearSelectedPath();
|
||||
} catch( RuntimeException ex ) {
|
||||
removeWindowListeners();
|
||||
throw ex;
|
||||
} catch( Error ex ) {
|
||||
removeWindowListeners();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
//---- ChangeListener ----
|
||||
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e ) {
|
||||
MenuElement[] selectedPath = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||
|
||||
if( selectedPath.length == 0 )
|
||||
removeWindowListeners();
|
||||
else if( lastPathSelectedPath.length == 0 )
|
||||
addWindowListeners( selectedPath[0] );
|
||||
|
||||
lastPathSelectedPath = selectedPath;
|
||||
}
|
||||
|
||||
//---- WindowListener ----
|
||||
|
||||
@Override
|
||||
public void windowIconified( WindowEvent e ) {
|
||||
cancelPopupMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated( WindowEvent e ) {
|
||||
cancelPopupMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosing( WindowEvent e ) {
|
||||
cancelPopupMenu();
|
||||
}
|
||||
|
||||
//---- ComponentListener ----
|
||||
|
||||
@Override
|
||||
public void componentResized( ComponentEvent e ) {
|
||||
cancelPopupMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved( ComponentEvent e ) {
|
||||
cancelPopupMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentShown( ComponentEvent e ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden( ComponentEvent e ) {
|
||||
cancelPopupMenu();
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,8 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.UIDefaults;
|
||||
@@ -61,7 +63,6 @@ import com.formdev.flatlaf.util.HSLColor;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.SoftCache;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -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<String, ColorUIResource> systemColorCache;
|
||||
private static final SoftCache<String, Object> fontCache = new SoftCache<>();
|
||||
|
||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
{
|
||||
static ArrayList<Class<?>> getLafClassesForDefaultsLoading( Class<?> lookAndFeelClass ) {
|
||||
// determine classes in class hierarchy in reverse order
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
for( Class<?> lafClass = lookAndFeelClass;
|
||||
@@ -102,20 +102,54 @@ class UIDefaultsLoader
|
||||
{
|
||||
lafClasses.add( 0, lafClass );
|
||||
}
|
||||
return lafClasses;
|
||||
}
|
||||
|
||||
loadDefaultsFromProperties( lafClasses, addons, additionalDefaults, dark, defaults );
|
||||
static Properties newUIProperties( boolean dark ) {
|
||||
// UI key prefixes
|
||||
String lightOrDarkPrefix = FlatLaf.getUIKeyLightOrDarkPrefix( dark );
|
||||
Set<String> platformPrefixes = FlatLaf.getUIKeyPlatformPrefixes();
|
||||
Set<String> specialPrefixes = FlatLaf.getUIKeySpecialPrefixes();
|
||||
|
||||
return new Properties() {
|
||||
@Override
|
||||
public synchronized Object put( Object k, Object value ) {
|
||||
// process key prefixes (while loading properties files)
|
||||
String key = (String) k;
|
||||
while( key.startsWith( "[" ) ) {
|
||||
int closeIndex = key.indexOf( ']' );
|
||||
if( closeIndex < 0 )
|
||||
return null; // ignore property with invalid prefix
|
||||
|
||||
String prefix = key.substring( 0, closeIndex + 1 );
|
||||
|
||||
if( specialPrefixes.contains( prefix ) )
|
||||
break; // keep special prefix
|
||||
|
||||
if( !lightOrDarkPrefix.equals( prefix ) && !platformPrefixes.contains( prefix ) )
|
||||
return null; // ignore property
|
||||
|
||||
// prefix is known and enabled --> remove prefix
|
||||
key = key.substring( closeIndex + 1 );
|
||||
}
|
||||
|
||||
return super.put( key, value );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
Consumer<Properties> intellijThemesHook, Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
{
|
||||
try {
|
||||
// temporary cache system colors while loading defaults,
|
||||
// which avoids that system color getter is invoked multiple times
|
||||
systemColorCache = (FlatLaf.getSystemColorGetter() != null) ? new HashMap<>() : null;
|
||||
|
||||
// all properties files will be loaded into this map
|
||||
Properties properties = newUIProperties( dark );
|
||||
|
||||
// load core properties files
|
||||
Properties properties = new Properties();
|
||||
for( Class<?> lafClass : lafClasses ) {
|
||||
String propertiesName = '/' + lafClass.getName().replace( '.', '/' ) + ".properties";
|
||||
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
|
||||
@@ -142,6 +176,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<Object> customDefaultsSources = FlatLaf.getCustomDefaultsSources();
|
||||
int size = (customDefaultsSources != null) ? customDefaultsSources.size() : 0;
|
||||
@@ -198,41 +236,6 @@ class UIDefaultsLoader
|
||||
if( additionalDefaults != null )
|
||||
properties.putAll( additionalDefaults );
|
||||
|
||||
// collect all platform specific keys (but do not modify properties)
|
||||
ArrayList<String> platformSpecificKeys = new ArrayList<>();
|
||||
for( Object okey : properties.keySet() ) {
|
||||
String key = (String) okey;
|
||||
if( key.startsWith( "[" ) &&
|
||||
(key.startsWith( "[win]" ) ||
|
||||
key.startsWith( "[mac]" ) ||
|
||||
key.startsWith( "[linux]" ) ||
|
||||
key.startsWith( "[light]" ) ||
|
||||
key.startsWith( "[dark]" )) )
|
||||
platformSpecificKeys.add( key );
|
||||
}
|
||||
|
||||
// remove platform specific properties and re-add only properties
|
||||
// for current platform, but with platform prefix removed
|
||||
if( !platformSpecificKeys.isEmpty() ) {
|
||||
// handle light/dark specific properties
|
||||
String lightOrDarkPrefix = dark ? "[dark]" : "[light]";
|
||||
for( String key : platformSpecificKeys ) {
|
||||
if( key.startsWith( lightOrDarkPrefix ) )
|
||||
properties.put( key.substring( lightOrDarkPrefix.length() ), properties.remove( key ) );
|
||||
}
|
||||
|
||||
// handle platform specific properties
|
||||
String platformPrefix =
|
||||
SystemInfo.isWindows ? "[win]" :
|
||||
SystemInfo.isMacOS ? "[mac]" :
|
||||
SystemInfo.isLinux ? "[linux]" : "[unknown]";
|
||||
for( String key : platformSpecificKeys ) {
|
||||
Object value = properties.remove( key );
|
||||
if( key.startsWith( platformPrefix ) )
|
||||
properties.put( key.substring( platformPrefix.length() ), value );
|
||||
}
|
||||
}
|
||||
|
||||
// get (and remove) wildcard replacements, which override all other defaults that end with same suffix
|
||||
HashMap<String, String> wildcards = new HashMap<>();
|
||||
Iterator<Entry<Object, Object>> it = properties.entrySet().iterator();
|
||||
@@ -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<String, String> 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 ) {
|
||||
@@ -830,6 +842,7 @@ class UIDefaultsLoader
|
||||
try {
|
||||
switch( function ) {
|
||||
case "if": return parseColorIf( value, params, resolver );
|
||||
case "lazy": return parseColorLazy( value, params, resolver );
|
||||
case "systemColor": return parseColorSystemColor( value, params, resolver );
|
||||
case "rgb": return parseColorRgbOrRgba( false, params, resolver );
|
||||
case "rgba": return parseColorRgbOrRgba( true, params, resolver );
|
||||
@@ -877,6 +890,32 @@ class UIDefaultsLoader
|
||||
return parseColorOrFunction( resolver.apply( ifValue ), resolver );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: lazy(uiKey)
|
||||
* <p>
|
||||
* This "lazy" function is only used if the "lazy" is passed as parameter to another
|
||||
* color function. Otherwise, the general "lazy" function is used.
|
||||
* <p>
|
||||
* Note: The color is resolved immediately, not lazy, because it is passed as parameter to another color function.
|
||||
* So e.g. {@code darken(lazy(List.background), 10%)} is the same as {@code darken($List.background, 10%)}.
|
||||
* <p>
|
||||
* Only useful if a property is defined as lazy and that property is used
|
||||
* in another property's color function. E.g.
|
||||
*
|
||||
* <pre>{@code
|
||||
* someProperty = lazy(List.background)
|
||||
* anotherProperty = darken($someProperty, 10%)
|
||||
* }</pre>
|
||||
*/
|
||||
private static Object parseColorLazy( String value, List<String> params, Function<String, String> resolver )
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if( params.size() != 1 )
|
||||
throw newMissingParametersException( value );
|
||||
|
||||
return parseColorOrFunction( resolver.apply( PROPERTY_PREFIX + params.get( 0 ) ), resolver );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: systemColor(name[,defaultValue])
|
||||
* - name: system color name
|
||||
@@ -974,7 +1013,7 @@ class UIDefaultsLoader
|
||||
* fadein(color,amount[,options]) or fadeout(color,amount[,options])
|
||||
* - color: a color (e.g. #f00) or a color function
|
||||
* - amount: percentage 0-100%
|
||||
* - options: [relative] [autoInverse] [noAutoInverse] [lazy] [derived]
|
||||
* - options: [relative] [autoInverse] [noAutoInverse] [derived] [lazy]
|
||||
*/
|
||||
private static Object parseColorHSLIncreaseDecrease( int hslIndex, boolean increase,
|
||||
List<String> params, Function<String, String> resolver )
|
||||
@@ -984,15 +1023,15 @@ class UIDefaultsLoader
|
||||
int amount = parsePercentage( params.get( 1 ) );
|
||||
boolean relative = false;
|
||||
boolean autoInverse = false;
|
||||
boolean lazy = false;
|
||||
boolean derived = false;
|
||||
boolean lazy = false;
|
||||
|
||||
if( params.size() > 2 ) {
|
||||
String options = params.get( 2 );
|
||||
relative = options.contains( "relative" );
|
||||
autoInverse = options.contains( "autoInverse" );
|
||||
lazy = options.contains( "lazy" );
|
||||
derived = options.contains( "derived" );
|
||||
lazy = options.contains( "lazy" );
|
||||
|
||||
// use autoInverse by default for derived colors, except if noAutoInverse is set
|
||||
if( derived && !options.contains( "noAutoInverse" ) )
|
||||
@@ -1003,14 +1042,8 @@ class UIDefaultsLoader
|
||||
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease(
|
||||
hslIndex, increase, amount, relative, autoInverse );
|
||||
|
||||
if( lazy ) {
|
||||
return (LazyValue) t -> {
|
||||
Object color = lazyUIManagerGet( colorStr );
|
||||
return (color instanceof Color)
|
||||
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
||||
: null;
|
||||
};
|
||||
}
|
||||
if( lazy )
|
||||
return newLazyColorFunction( colorStr, function );
|
||||
|
||||
// parse base color, apply function and create derived color
|
||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||
@@ -1039,14 +1072,8 @@ class UIDefaultsLoader
|
||||
// create function
|
||||
ColorFunction function = new ColorFunctions.Fade( amount );
|
||||
|
||||
if( lazy ) {
|
||||
return (LazyValue) t -> {
|
||||
Object color = lazyUIManagerGet( colorStr );
|
||||
return (color instanceof Color)
|
||||
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
||||
: null;
|
||||
};
|
||||
}
|
||||
if( lazy )
|
||||
return newLazyColorFunction( colorStr, function );
|
||||
|
||||
// parse base color, apply function and create derived color
|
||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||
@@ -1056,7 +1083,7 @@ class UIDefaultsLoader
|
||||
* Syntax: spin(color,angle[,options])
|
||||
* - color: a color (e.g. #f00) or a color function
|
||||
* - angle: number of degrees to rotate
|
||||
* - options: [derived]
|
||||
* - options: [derived] [lazy]
|
||||
*/
|
||||
private static Object parseColorSpin( List<String> params, Function<String, String> resolver )
|
||||
throws IllegalArgumentException
|
||||
@@ -1064,15 +1091,20 @@ class UIDefaultsLoader
|
||||
String colorStr = params.get( 0 );
|
||||
int amount = parseInteger( params.get( 1 ) );
|
||||
boolean derived = false;
|
||||
boolean lazy = false;
|
||||
|
||||
if( params.size() > 2 ) {
|
||||
String options = params.get( 2 );
|
||||
derived = options.contains( "derived" );
|
||||
lazy = options.contains( "lazy" );
|
||||
}
|
||||
|
||||
// create function
|
||||
ColorFunction function = new ColorFunctions.HSLIncreaseDecrease( 0, true, amount, false, false );
|
||||
|
||||
if( lazy )
|
||||
return newLazyColorFunction( colorStr, function );
|
||||
|
||||
// parse base color, apply function and create derived color
|
||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||
}
|
||||
@@ -1084,7 +1116,7 @@ class UIDefaultsLoader
|
||||
* changeAlpha(color,value[,options])
|
||||
* - color: a color (e.g. #f00) or a color function
|
||||
* - value: for hue: number of degrees; otherwise: percentage 0-100%
|
||||
* - options: [derived]
|
||||
* - options: [derived] [lazy]
|
||||
*/
|
||||
private static Object parseColorChange( int hslIndex,
|
||||
List<String> params, Function<String, String> resolver )
|
||||
@@ -1095,27 +1127,33 @@ class UIDefaultsLoader
|
||||
? parseInteger( params.get( 1 ) )
|
||||
: parsePercentage( params.get( 1 ) );
|
||||
boolean derived = false;
|
||||
boolean lazy = false;
|
||||
|
||||
if( params.size() > 2 ) {
|
||||
String options = params.get( 2 );
|
||||
derived = options.contains( "derived" );
|
||||
lazy = options.contains( "lazy" );
|
||||
}
|
||||
|
||||
// create function
|
||||
ColorFunction function = new ColorFunctions.HSLChange( hslIndex, value );
|
||||
|
||||
if( lazy )
|
||||
return newLazyColorFunction( colorStr, function );
|
||||
|
||||
// parse base color, apply function and create derived color
|
||||
return parseFunctionBaseColor( colorStr, function, derived, resolver );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: mix(color1,color2[,weight]) or
|
||||
* tint(color[,weight]) or
|
||||
* shade(color[,weight])
|
||||
* Syntax: mix(color1,color2[,weight][,options]) or
|
||||
* tint(color[,weight][,options]) or
|
||||
* shade(color[,weight][,options])
|
||||
* - color1: a color (e.g. #f00) or a color function
|
||||
* - color2: a color (e.g. #f00) or a color function
|
||||
* - weight: the weight (in range 0-100%) to mix the two colors
|
||||
* larger weight uses more of first color, smaller weight more of second color
|
||||
* - options: [derived] [lazy]
|
||||
*/
|
||||
private static Object parseColorMix( String color1Str, List<String> params, Function<String, String> resolver )
|
||||
throws IllegalArgumentException
|
||||
@@ -1124,18 +1162,36 @@ class UIDefaultsLoader
|
||||
if( color1Str == null )
|
||||
color1Str = params.get( i++ );
|
||||
String color2Str = params.get( i++ );
|
||||
int weight = (params.size() > i) ? parsePercentage( params.get( i ) ) : 50;
|
||||
int weight = 50;
|
||||
boolean derived = false;
|
||||
boolean lazy = false;
|
||||
|
||||
if( params.size() > i ) {
|
||||
String weightStr = params.get( i );
|
||||
if( !weightStr.isEmpty() && Character.isDigit( weightStr.charAt( 0 ) ) ) {
|
||||
weight = parsePercentage( weightStr );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if( params.size() > i ) {
|
||||
String options = params.get( i );
|
||||
derived = options.contains( "derived" );
|
||||
lazy = options.contains( "lazy" );
|
||||
}
|
||||
|
||||
// parse second color
|
||||
ColorUIResource color2 = (ColorUIResource) parseColorOrFunction( resolver.apply( color2Str ), resolver );
|
||||
if( color2 == null )
|
||||
ColorUIResource color1 = (ColorUIResource) parseColorOrFunction( resolver.apply( color1Str ), resolver );
|
||||
if( color1 == null )
|
||||
return null;
|
||||
|
||||
// create function
|
||||
ColorFunction function = new ColorFunctions.Mix( color2, weight );
|
||||
ColorFunction function = new ColorFunctions.Mix2( color1, weight );
|
||||
|
||||
if( lazy )
|
||||
return newLazyColorFunction( color2Str, function );
|
||||
|
||||
// parse first color, apply function and create mixed color
|
||||
return parseFunctionBaseColor( color1Str, function, false, resolver );
|
||||
return parseFunctionBaseColor( color2Str, function, derived, resolver );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1229,6 +1285,15 @@ class UIDefaultsLoader
|
||||
return new ColorUIResource( newColor );
|
||||
}
|
||||
|
||||
private static LazyValue newLazyColorFunction( String uiKey, ColorFunction function ) {
|
||||
return (LazyValue) t -> {
|
||||
Object color = lazyUIManagerGet( uiKey );
|
||||
return (color instanceof Color)
|
||||
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
|
||||
*/
|
||||
|
||||
@@ -18,44 +18,95 @@ package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Window;
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatTitlePane;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Base class for window icons.
|
||||
*
|
||||
* @uiDefault TitlePane.buttonSize Dimension
|
||||
* @uiDefault TitlePane.buttonInsets Insets optional
|
||||
* @uiDefault TitlePane.buttonArc int optional
|
||||
* @uiDefault TitlePane.buttonSymbolHeight int
|
||||
* @uiDefault TitlePane.buttonHoverBackground Color
|
||||
* @uiDefault TitlePane.buttonPressedBackground Color
|
||||
* @uiDefault TitlePane.buttonBackground Color optional
|
||||
* @uiDefault TitlePane.buttonForeground Color optional
|
||||
* @uiDefault TitlePane.buttonInactiveBackground Color optional
|
||||
* @uiDefault TitlePane.buttonInactiveForeground Color optional
|
||||
* @uiDefault TitlePane.buttonHoverBackground Color optional
|
||||
* @uiDefault TitlePane.buttonHoverForeground Color optional
|
||||
* @uiDefault TitlePane.buttonPressedBackground Color optional
|
||||
* @uiDefault TitlePane.buttonPressedForeground Color optional
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public abstract class FlatWindowAbstractIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private final int symbolHeight;
|
||||
private final Color hoverBackground;
|
||||
private final Color pressedBackground;
|
||||
/** @since 3.6 */ protected final Insets insets;
|
||||
/** @since 3.6 */ protected final int arc;
|
||||
/** @since 3.6 */ protected final int symbolHeight;
|
||||
|
||||
/** @since 3.6 */ protected final Color background;
|
||||
/** @since 3.6 */ protected final Color foreground;
|
||||
/** @since 3.6 */ protected final Color inactiveBackground;
|
||||
/** @since 3.6 */ protected final Color inactiveForeground;
|
||||
protected final Color hoverBackground;
|
||||
/** @since 3.6 */ protected final Color hoverForeground;
|
||||
protected final Color pressedBackground;
|
||||
/** @since 3.6 */ protected final Color pressedForeground;
|
||||
|
||||
/** @since 3.2 */
|
||||
protected FlatWindowAbstractIcon( String windowStyle ) {
|
||||
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ) );
|
||||
this( windowStyle, null, null, null, null, null, null, null, null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
protected FlatWindowAbstractIcon( Dimension size, int symbolHeight, Color hoverBackground, Color pressedBackground ) {
|
||||
/** @since 3.6 */
|
||||
protected FlatWindowAbstractIcon( String windowStyle,
|
||||
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
|
||||
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
|
||||
{
|
||||
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||
FlatUIUtils.getSubUIInsets( "TitlePane.buttonInsets", windowStyle ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonArc", windowStyle, 0 ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||
(background != null) ? background : FlatUIUtils.getSubUIColor( "TitlePane.buttonBackground", windowStyle ),
|
||||
(foreground != null) ? foreground : FlatUIUtils.getSubUIColor( "TitlePane.buttonForeground", windowStyle ),
|
||||
(inactiveBackground != null) ? inactiveBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveBackground", windowStyle ),
|
||||
(inactiveForeground != null) ? inactiveForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveForeground", windowStyle ),
|
||||
(hoverBackground != null) ? hoverBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
||||
(hoverForeground != null) ? hoverForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverForeground", windowStyle ),
|
||||
(pressedBackground != null) ? pressedBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ),
|
||||
(pressedForeground != null) ? pressedForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedForeground", windowStyle ) );
|
||||
}
|
||||
|
||||
/** @since 3.6 */
|
||||
protected FlatWindowAbstractIcon( Dimension size, Insets insets, int arc, int symbolHeight,
|
||||
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
|
||||
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
|
||||
{
|
||||
super( size.width, size.height, null );
|
||||
this.insets = (insets != null) ? insets : new Insets( 0, 0, 0, 0 );
|
||||
this.arc = arc;
|
||||
this.symbolHeight = symbolHeight;
|
||||
|
||||
this.background = background;
|
||||
this.foreground = foreground;
|
||||
this.inactiveBackground = inactiveBackground;
|
||||
this.inactiveForeground = inactiveForeground;
|
||||
this.hoverBackground = hoverBackground;
|
||||
this.hoverForeground = hoverForeground;
|
||||
this.pressedBackground = pressedBackground;
|
||||
this.pressedForeground = pressedForeground;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,26 +120,39 @@ public abstract class FlatWindowAbstractIcon
|
||||
/** @since 3.5.2 */
|
||||
@Override
|
||||
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
|
||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
||||
Color bg = null;
|
||||
if( background != null || inactiveBackground != null ) {
|
||||
Window window = SwingUtilities.windowForComponent( c );
|
||||
bg = (window == null || window.isActive()) ? background : inactiveBackground;
|
||||
}
|
||||
|
||||
Color background = FlatButtonUI.buttonStateColor( c, bg, null, null, hoverBackground, pressedBackground );
|
||||
if( background != null ) {
|
||||
// disable antialiasing for background rectangle painting to avoid blurry edges when scaled (e.g. at 125% or 175%)
|
||||
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
||||
Insets insets = UIScale.scale( this.insets );
|
||||
float arc = UIScale.scale( (float) this.arc );
|
||||
|
||||
// fill background of whole component
|
||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
// derive color from title pane background
|
||||
if( background instanceof DerivedColor ) {
|
||||
Container titlePane = SwingUtilities.getAncestorOfClass( FlatTitlePane.class, c );
|
||||
Component baseComp = (titlePane != null) ? titlePane : c;
|
||||
background = FlatUIUtils.deriveColor( background, baseComp.getBackground() );
|
||||
}
|
||||
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
|
||||
g.setColor( background );
|
||||
FlatUIUtils.paintComponentBackground( g, insets.left, insets.top,
|
||||
c.getWidth() - insets.left - insets.right,
|
||||
c.getHeight() - insets.top - insets.bottom,
|
||||
0, arc );
|
||||
}
|
||||
}
|
||||
|
||||
protected Color getForeground( Component c ) {
|
||||
return c.getForeground();
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
protected int getSymbolHeight() {
|
||||
return symbolHeight;
|
||||
Color fg = null;
|
||||
if( foreground != null || inactiveForeground != null ) {
|
||||
Window window = SwingUtilities.windowForComponent( c );
|
||||
fg = (window == null || window.isActive()) ? foreground : inactiveForeground;
|
||||
}
|
||||
return FlatButtonUI.buttonStateColor( c, (fg != null) ? fg : c.getForeground(),
|
||||
null, null, hoverForeground, pressedForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,53 +17,54 @@
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "close" icon for windows (frames and dialogs).
|
||||
*
|
||||
* @uiDefault TitlePane.closeHoverBackground Color
|
||||
* @uiDefault TitlePane.closePressedBackground Color
|
||||
* @uiDefault TitlePane.closeHoverForeground Color
|
||||
* @uiDefault TitlePane.closePressedForeground Color
|
||||
* @uiDefault TitlePane.closeBackground Color optional
|
||||
* @uiDefault TitlePane.closeForeground Color optional
|
||||
* @uiDefault TitlePane.closeInactiveBackground Color optional
|
||||
* @uiDefault TitlePane.closeInactiveForeground Color optional
|
||||
* @uiDefault TitlePane.closeHoverBackground Color optional
|
||||
* @uiDefault TitlePane.closeHoverForeground Color optional
|
||||
* @uiDefault TitlePane.closePressedBackground Color optional
|
||||
* @uiDefault TitlePane.closePressedForeground Color optional
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatWindowCloseIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
private final Color hoverForeground;
|
||||
private final Color pressedForeground;
|
||||
|
||||
public FlatWindowCloseIcon() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowCloseIcon( String windowStyle ) {
|
||||
super( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||
super( windowStyle,
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeForeground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveForeground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ) );
|
||||
|
||||
hoverForeground = FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle );
|
||||
pressedForeground = FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle );
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int iwh = (int) (symbolHeight * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int ix2 = ix + iwh - 1;
|
||||
int iy2 = iy + iwh - 1;
|
||||
float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
|
||||
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||
path.moveTo( ix, iy );
|
||||
@@ -73,9 +74,4 @@ public class FlatWindowCloseIcon
|
||||
g.setStroke( new BasicStroke( thickness ) );
|
||||
g.draw( path );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Color getForeground( Component c ) {
|
||||
return FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class FlatWindowIconifyIcon
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iw = (int) (getSymbolHeight() * scaleFactor);
|
||||
int iw = (int) (symbolHeight * scaleFactor);
|
||||
int ih = Math.max( (int) scaleFactor, 1 );
|
||||
int ix = x + ((width - iw) / 2);
|
||||
int iy = y + ((height - ih) / 2);
|
||||
|
||||
@@ -39,10 +39,11 @@ public class FlatWindowMaximizeIcon
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int iwh = (int) (symbolHeight * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
|
||||
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
|
||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||
|
||||
g.fill( SystemInfo.isWindows_11_orLater
|
||||
|
||||
@@ -42,14 +42,15 @@ public class FlatWindowRestoreIcon
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int iwh = (int) (symbolHeight * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
float thickness = Math.max( SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor, 1 );
|
||||
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
|
||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
||||
|
||||
int rwh = (int) ((getSymbolHeight() - 2) * scaleFactor);
|
||||
int rwh = (int) ((symbolHeight - 2) * scaleFactor);
|
||||
int ro2 = iwh - rwh;
|
||||
|
||||
// upper-right rectangle
|
||||
|
||||
@@ -59,6 +59,8 @@ import com.formdev.flatlaf.util.DerivedColor;
|
||||
* @uiDefault Component.error.focusedBorderColor Color
|
||||
* @uiDefault Component.warning.borderColor Color
|
||||
* @uiDefault Component.warning.focusedBorderColor Color
|
||||
* @uiDefault Component.success.borderColor Color
|
||||
* @uiDefault Component.success.focusedBorderColor Color
|
||||
* @uiDefault Component.custom.borderColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
@@ -81,6 +83,8 @@ public class FlatBorder
|
||||
@Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
||||
@Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
||||
@Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
||||
/** @since 3.6 */ @Styleable(dot=true) protected Color successBorderColor = UIManager.getColor( "Component.success.borderColor" );
|
||||
/** @since 3.6 */ @Styleable(dot=true) protected Color successFocusedBorderColor = UIManager.getColor( "Component.success.focusedBorderColor" );
|
||||
@Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
||||
|
||||
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||
@@ -168,6 +172,9 @@ public class FlatBorder
|
||||
|
||||
case FlatClientProperties.OUTLINE_WARNING:
|
||||
return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor;
|
||||
|
||||
case FlatClientProperties.OUTLINE_SUCCESS:
|
||||
return isFocused( c ) ? successFocusedBorderColor : successBorderColor;
|
||||
}
|
||||
} else if( outline instanceof Color ) {
|
||||
Color color = (Color) outline;
|
||||
|
||||
@@ -280,8 +280,6 @@ public class FlatButtonUI
|
||||
|
||||
LookAndFeel.installProperty( b, "opaque", false );
|
||||
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
|
||||
|
||||
MigLayoutVisualPadding.install( b );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -291,10 +289,23 @@ public class FlatButtonUI
|
||||
oldStyleValues = null;
|
||||
borderShared = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( b );
|
||||
defaults_initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners( AbstractButton b ) {
|
||||
super.installListeners( b );
|
||||
|
||||
MigLayoutVisualPadding.install( b );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners( AbstractButton b ) {
|
||||
super.uninstallListeners( b );
|
||||
|
||||
MigLayoutVisualPadding.uninstall( b );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BasicButtonListener createButtonListener( AbstractButton b ) {
|
||||
return new FlatButtonListener( b );
|
||||
|
||||
@@ -225,6 +225,8 @@ public class FlatComboBoxUI
|
||||
}
|
||||
};
|
||||
comboBox.addMouseListener( hoverListener );
|
||||
|
||||
MigLayoutVisualPadding.install( comboBox );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -233,6 +235,8 @@ public class FlatComboBoxUI
|
||||
|
||||
comboBox.removeMouseListener( hoverListener );
|
||||
hoverListener = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( comboBox );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -274,8 +278,6 @@ public class FlatComboBoxUI
|
||||
comboBox.setMaximumRowCount( maximumRowCount );
|
||||
|
||||
paddingBorder = new CellPaddingBorder( padding );
|
||||
|
||||
MigLayoutVisualPadding.install( comboBox );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -304,8 +306,6 @@ public class FlatComboBoxUI
|
||||
|
||||
oldStyleValues = null;
|
||||
borderShared = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( comboBox );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -74,7 +74,7 @@ public class FlatDropShadowBorder
|
||||
|
||||
this.shadowColor = shadowColor;
|
||||
this.shadowInsets = shadowInsets;
|
||||
this.shadowOpacity = shadowOpacity;
|
||||
this.shadowOpacity = Math.min( Math.max( shadowOpacity, 0f ), 1f );
|
||||
|
||||
shadowSize = maxInset( shadowInsets );
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ class FlatNativeLibrary
|
||||
|
||||
String classifier;
|
||||
String ext;
|
||||
boolean unknownArch = false;
|
||||
if( SystemInfo.isWindows_10_orLater && (SystemInfo.isX86 || SystemInfo.isX86_64 || SystemInfo.isAARCH64) ) {
|
||||
// Windows: requires Windows 10/11 (x86, x86_64 or aarch64)
|
||||
|
||||
@@ -90,11 +91,14 @@ class FlatNativeLibrary
|
||||
classifier = SystemInfo.isAARCH64 ? "macos-arm64" : "macos-x86_64";
|
||||
ext = "dylib";
|
||||
|
||||
} else if( SystemInfo.isLinux && (SystemInfo.isX86_64 || SystemInfo.isAARCH64)) {
|
||||
// Linux: requires x86_64 or aarch64
|
||||
} else if( SystemInfo.isLinux ) {
|
||||
// Linux: x86_64 or aarch64 (but also supports unknown architectures)
|
||||
|
||||
classifier = SystemInfo.isAARCH64 ? "linux-arm64" : "linux-x86_64";
|
||||
classifier = SystemInfo.isAARCH64 ? "linux-arm64"
|
||||
: (SystemInfo.isX86_64 ? "linux-x86_64"
|
||||
: "linux-" + sanitize( System.getProperty( "os.arch" ) ));
|
||||
ext = "so";
|
||||
unknownArch = !SystemInfo.isX86_64 && !SystemInfo.isAARCH64;
|
||||
|
||||
// Load libjawt.so (part of JRE) explicitly because it is not found
|
||||
// in all Java versions/distributions.
|
||||
@@ -106,7 +110,7 @@ class FlatNativeLibrary
|
||||
return; // no native library available for current OS or CPU architecture
|
||||
|
||||
// load native library
|
||||
NativeLibrary nativeLibrary = createNativeLibrary( classifier, ext );
|
||||
NativeLibrary nativeLibrary = createNativeLibrary( classifier, ext, unknownArch );
|
||||
if( !nativeLibrary.isLoaded() )
|
||||
return;
|
||||
|
||||
@@ -128,7 +132,7 @@ class FlatNativeLibrary
|
||||
FlatNativeLibrary.nativeLibrary = nativeLibrary;
|
||||
}
|
||||
|
||||
private static NativeLibrary createNativeLibrary( String classifier, String ext ) {
|
||||
private static NativeLibrary createNativeLibrary( String classifier, String ext, boolean unknownArch ) {
|
||||
String libraryName = "flatlaf-" + classifier;
|
||||
|
||||
// load from "java.library.path" or from path specified in system property "flatlaf.nativeLibraryPath"
|
||||
@@ -139,9 +143,11 @@ class FlatNativeLibrary
|
||||
if( library.isLoaded() )
|
||||
return library;
|
||||
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '" + System.mapLibraryName( libraryName )
|
||||
+ "' not found in java.library.path '" + System.getProperty( "java.library.path" )
|
||||
+ "'. Using extracted native library instead.", null );
|
||||
if( !unknownArch ) {
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '" + System.mapLibraryName( libraryName )
|
||||
+ "' not found in java.library.path '" + System.getProperty( "java.library.path" )
|
||||
+ "'. Using extracted native library instead.", null );
|
||||
}
|
||||
} else {
|
||||
// try standard library naming scheme
|
||||
// (same as in flatlaf.jar in package 'com/formdev/flatlaf/natives')
|
||||
@@ -160,11 +166,13 @@ class FlatNativeLibrary
|
||||
return new NativeLibrary( libraryFile2, true );
|
||||
}
|
||||
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '"
|
||||
+ libraryFile.getName()
|
||||
+ (libraryName2 != null ? ("' or '" + libraryName2) : "")
|
||||
+ "' not found in '" + libraryFile.getParentFile().getAbsolutePath()
|
||||
+ "'. Using extracted native library instead.", null );
|
||||
if( !unknownArch ) {
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Native library '"
|
||||
+ libraryFile.getName()
|
||||
+ (libraryName2 != null ? ("' or '" + libraryName2) : "")
|
||||
+ "' not found in '" + libraryFile.getParentFile().getAbsolutePath()
|
||||
+ "'. Using extracted native library instead.", null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +183,7 @@ class FlatNativeLibrary
|
||||
return new NativeLibrary( libraryFile, true );
|
||||
|
||||
// load from FlatLaf jar (extract native library to temp folder)
|
||||
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, true );
|
||||
return new NativeLibrary( "com/formdev/flatlaf/natives/" + libraryName, null, !unknownArch );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,6 +281,13 @@ class FlatNativeLibrary
|
||||
+ '-' + classifier + '.' + ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow only 'a'-'z', 'A'-'Z', '0'-'9', '_' and '-' in filenames.
|
||||
*/
|
||||
private static String sanitize( String s ) {
|
||||
return s.replaceAll( "[^a-zA-Z0-9_-]", "_" );
|
||||
}
|
||||
|
||||
private static void loadJAWT() {
|
||||
try {
|
||||
System.loadLibrary( "jawt" );
|
||||
|
||||
@@ -53,8 +53,17 @@ public class FlatNativeLinuxLibrary
|
||||
//---- X Window System ----------------------------------------------------
|
||||
|
||||
// direction for _NET_WM_MOVERESIZE message
|
||||
// see https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html
|
||||
static final int MOVE = 8;
|
||||
// see https://specifications.freedesktop.org/wm-spec/latest/ar01s04.html
|
||||
static final int
|
||||
SIZE_TOPLEFT = 0,
|
||||
SIZE_TOP = 1,
|
||||
SIZE_TOPRIGHT = 2,
|
||||
SIZE_RIGHT = 3,
|
||||
SIZE_BOTTOMRIGHT = 4,
|
||||
SIZE_BOTTOM = 5,
|
||||
SIZE_BOTTOMLEFT = 6,
|
||||
SIZE_LEFT = 7,
|
||||
MOVE = 8;
|
||||
|
||||
private static Boolean isXWindowSystem;
|
||||
|
||||
|
||||
@@ -709,6 +709,7 @@ public class FlatPopupFactory
|
||||
|
||||
private class DropShadowPopup
|
||||
extends NonFlashingPopup
|
||||
implements ComponentListener
|
||||
{
|
||||
// light weight
|
||||
private JComponent lightComp;
|
||||
@@ -768,7 +769,7 @@ public class FlatPopupFactory
|
||||
}
|
||||
|
||||
// Windows 11: reset corner preference on reused heavy weight popups
|
||||
if( isWindows11BorderSupported() ) {
|
||||
if( SystemInfo.isWindows_11_orLater && FlatNativeWindowsLibrary.isLoaded() ) {
|
||||
resetWindows11Border( popupWindow );
|
||||
if( dropShadowWindow != null )
|
||||
resetWindows11Border( dropShadowWindow );
|
||||
@@ -838,10 +839,18 @@ public class FlatPopupFactory
|
||||
if( insets.left != 0 || insets.top != 0 )
|
||||
lightComp.setLocation( lightComp.getX() - insets.left, lightComp.getY() - insets.top );
|
||||
}
|
||||
|
||||
if( popupWindow != null ) {
|
||||
removeAllPopupWindowComponentListeners();
|
||||
popupWindow.addComponentListener( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void hideImpl() {
|
||||
if( popupWindow != null )
|
||||
removeAllPopupWindowComponentListeners();
|
||||
|
||||
if( dropShadowDelegate != null ) {
|
||||
dropShadowDelegate.hide();
|
||||
dropShadowDelegate = null;
|
||||
@@ -941,23 +950,55 @@ public class FlatPopupFactory
|
||||
|
||||
@Override
|
||||
void reset( Component contents, int ownerX, int ownerY ) {
|
||||
if( popupWindow != null )
|
||||
removeAllPopupWindowComponentListeners();
|
||||
|
||||
super.reset( contents, ownerX, ownerY );
|
||||
|
||||
if( dropShadowWindow != null ) {
|
||||
// set preferred size of drop shadow panel
|
||||
Dimension prefSize = popupWindow.getPreferredSize();
|
||||
Insets insets = dropShadowPanel2.getInsets();
|
||||
int w = prefSize.width + insets.left + insets.right;
|
||||
int h = prefSize.height + insets.top + insets.bottom;
|
||||
dropShadowPanel2.setPreferredSize( new Dimension( w, h ) );
|
||||
dropShadowPanel2.invalidate();
|
||||
dropShadowWindow.pack();
|
||||
updateDropShadowWindowBounds();
|
||||
}
|
||||
|
||||
// update drop shadow popup window location
|
||||
int x = popupWindow.getX() - insets.left;
|
||||
int y = popupWindow.getY() - insets.top;
|
||||
dropShadowWindow.setLocation( x, y );
|
||||
private void updateDropShadowWindowBounds() {
|
||||
if( dropShadowWindow == null )
|
||||
return;
|
||||
|
||||
// calculate size of drop shadow window
|
||||
Dimension size = popupWindow.getSize();
|
||||
Insets insets = dropShadowPanel2.getInsets();
|
||||
int w = size.width + insets.left + insets.right;
|
||||
int h = size.height + insets.top + insets.bottom;
|
||||
|
||||
// update drop shadow popup window bounds
|
||||
int x = popupWindow.getX() - insets.left;
|
||||
int y = popupWindow.getY() - insets.top;
|
||||
dropShadowWindow.setBounds( x, y, w, h );
|
||||
dropShadowWindow.validate();
|
||||
}
|
||||
|
||||
private void removeAllPopupWindowComponentListeners() {
|
||||
// make sure that there is no old component listener
|
||||
// necessary because this class is cloned if reusing popup windows
|
||||
for( ComponentListener l : popupWindow.getComponentListeners() ) {
|
||||
if( l instanceof DropShadowPopup )
|
||||
popupWindow.removeComponentListener( l );
|
||||
}
|
||||
}
|
||||
|
||||
//---- interface ComponentListener ----
|
||||
|
||||
@Override
|
||||
public void componentResized( ComponentEvent e ) {
|
||||
if( e.getSource() == popupWindow )
|
||||
updateDropShadowWindowBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved( ComponentEvent e ) {
|
||||
if( e.getSource() == popupWindow )
|
||||
updateDropShadowWindowBounds();
|
||||
}
|
||||
|
||||
@Override public void componentShown( ComponentEvent e ) {}
|
||||
@Override public void componentHidden( ComponentEvent e ) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.awt.Window;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
@@ -485,8 +486,12 @@ public class FlatRootPaneUI
|
||||
break;
|
||||
|
||||
case "ancestor":
|
||||
if( e.getNewValue() instanceof Window )
|
||||
if( e.getNewValue() instanceof Window ) {
|
||||
if( titlePane != null && !Objects.equals( titlePane.windowStyle, FlatTitlePane.getWindowStyle( rootPane ) ) )
|
||||
setTitlePane( createTitlePane() );
|
||||
|
||||
macClearBackgroundForTranslucentWindow( rootPane );
|
||||
}
|
||||
|
||||
macUninstallWindowBackgroundListener( rootPane );
|
||||
macInstallWindowBackgroundListener( rootPane );
|
||||
@@ -684,7 +689,7 @@ public class FlatRootPaneUI
|
||||
* Window border used for non-native window decorations.
|
||||
*/
|
||||
public static class FlatWindowBorder
|
||||
extends BorderUIResource.EmptyBorderUIResource
|
||||
extends FlatEmptyBorder
|
||||
{
|
||||
protected final Color activeBorderColor = UIManager.getColor( "RootPane.activeBorderColor" );
|
||||
protected final Color inactiveBorderColor = UIManager.getColor( "RootPane.inactiveBorderColor" );
|
||||
@@ -717,7 +722,10 @@ public class FlatRootPaneUI
|
||||
}
|
||||
|
||||
private void paintImpl( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
g.drawRect( x, y, width - 1, height - 1 );
|
||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||
float lineWidth = (float) (UIScale.scale( 1f ) * scaleFactor);
|
||||
g.fill( FlatUIUtils.createRectangle( x, y, width, height, lineWidth ) );
|
||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||
}
|
||||
|
||||
protected boolean isWindowMaximized( Component c ) {
|
||||
|
||||
@@ -140,8 +140,6 @@ public class FlatSpinnerUI
|
||||
buttonHoverArrowColor = UIManager.getColor( "Spinner.buttonHoverArrowColor" );
|
||||
buttonPressedArrowColor = UIManager.getColor( "Spinner.buttonPressedArrowColor" );
|
||||
padding = UIManager.getInsets( "Spinner.padding" );
|
||||
|
||||
MigLayoutVisualPadding.install( spinner );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -162,8 +160,6 @@ public class FlatSpinnerUI
|
||||
|
||||
oldStyleValues = null;
|
||||
borderShared = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( spinner );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -173,6 +169,8 @@ public class FlatSpinnerUI
|
||||
addEditorFocusListener( spinner.getEditor() );
|
||||
spinner.addFocusListener( getHandler() );
|
||||
spinner.addPropertyChangeListener( getHandler() );
|
||||
|
||||
MigLayoutVisualPadding.install( spinner );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -184,6 +182,8 @@ public class FlatSpinnerUI
|
||||
spinner.removePropertyChangeListener( getHandler() );
|
||||
|
||||
handler = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( spinner );
|
||||
}
|
||||
|
||||
private Handler getHandler() {
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* Support for styling components in CSS syntax.
|
||||
@@ -325,22 +324,24 @@ public class FlatStylingSupport
|
||||
return null;
|
||||
|
||||
Map<String, Object> oldValues = new HashMap<>();
|
||||
outer:
|
||||
for( Map.Entry<String, Object> e : style.entrySet() ) {
|
||||
String key = e.getKey();
|
||||
Object newValue = e.getValue();
|
||||
|
||||
// handle key prefix
|
||||
if( key.startsWith( "[" ) ) {
|
||||
if( (SystemInfo.isWindows && key.startsWith( "[win]" )) ||
|
||||
(SystemInfo.isMacOS && key.startsWith( "[mac]" )) ||
|
||||
(SystemInfo.isLinux && key.startsWith( "[linux]" )) ||
|
||||
(key.startsWith( "[light]" ) && !FlatLaf.isLafDark()) ||
|
||||
(key.startsWith( "[dark]" ) && FlatLaf.isLafDark()) )
|
||||
{
|
||||
// prefix is known and enabled --> remove prefix
|
||||
key = key.substring( key.indexOf( ']' ) + 1 );
|
||||
} else
|
||||
continue;
|
||||
while( key.startsWith( "[" ) ) {
|
||||
int closeIndex = key.indexOf( ']' );
|
||||
if( closeIndex < 0 )
|
||||
continue outer;
|
||||
|
||||
String prefix = key.substring( 0, closeIndex + 1 );
|
||||
String lightOrDarkPrefix = FlatLaf.getUIKeyLightOrDarkPrefix( FlatLaf.isLafDark() );
|
||||
if( !lightOrDarkPrefix.equals( prefix ) && !FlatLaf.getUIKeyPlatformPrefixes().contains( prefix ) )
|
||||
continue outer;
|
||||
|
||||
// prefix is known and enabled --> remove prefix
|
||||
key = key.substring( closeIndex + 1 );
|
||||
}
|
||||
|
||||
Object oldValue = applyProperty.apply( key, newValue );
|
||||
|
||||
@@ -174,8 +174,6 @@ public class FlatTextFieldUI
|
||||
defaultMargin = UIManager.getInsets( prefix + ".margin" );
|
||||
|
||||
LookAndFeel.installProperty( getComponent(), "opaque", false );
|
||||
|
||||
MigLayoutVisualPadding.install( getComponent() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,8 +191,6 @@ public class FlatTextFieldUI
|
||||
|
||||
oldStyleValues = null;
|
||||
borderShared = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( getComponent() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -204,6 +200,8 @@ public class FlatTextFieldUI
|
||||
// necessary to update focus border and background
|
||||
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
|
||||
getComponent().addFocusListener( focusListener );
|
||||
|
||||
MigLayoutVisualPadding.install( getComponent() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,6 +215,8 @@ public class FlatTextFieldUI
|
||||
getComponent().getDocument().removeDocumentListener( documentListener );
|
||||
documentListener = null;
|
||||
}
|
||||
|
||||
MigLayoutVisualPadding.uninstall( getComponent() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
@@ -90,13 +89,16 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TitlePane.iconSize Dimension
|
||||
* @uiDefault TitlePane.iconMargins Insets
|
||||
* @uiDefault TitlePane.titleMargins Insets
|
||||
* @uiDefault TitlePane.menuBarEmbedded boolean
|
||||
* @uiDefault TitlePane.titleMinimumWidth int
|
||||
* @uiDefault TitlePane.buttonMinimumWidth int
|
||||
* @uiDefault TitlePane.buttonMaximizedHeight int
|
||||
* @uiDefault TitlePane.buttonsGap int
|
||||
* @uiDefault TitlePane.buttonsMargins Insets
|
||||
* @uiDefault TitlePane.buttonsFillVertically boolean
|
||||
* @uiDefault TitlePane.centerTitle boolean
|
||||
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
|
||||
* @uiDefault TitlePane.showIconBesideTitle boolean
|
||||
* @uiDefault TitlePane.menuBarEmbedded boolean
|
||||
* @uiDefault TitlePane.menuBarTitleGap int
|
||||
* @uiDefault TitlePane.menuBarTitleMinimumGap int
|
||||
* @uiDefault TitlePane.closeIcon Icon
|
||||
@@ -124,9 +126,14 @@ public class FlatTitlePane
|
||||
/** @since 2.5 */ protected final boolean showIconInDialogs;
|
||||
/** @since 2 */ protected final int noIconLeftGap;
|
||||
protected final Dimension iconSize;
|
||||
/** @since 3.6 */ protected final Insets iconMargins;
|
||||
/** @since 3.6 */ protected final Insets titleMargins;
|
||||
/** @since 2.4 */ protected final int titleMinimumWidth;
|
||||
/** @since 2.4 */ protected final int buttonMinimumWidth;
|
||||
protected final int buttonMaximizedHeight;
|
||||
/** @since 3.6 */ protected final int buttonsGap;
|
||||
/** @since 3.6 */ protected final Insets buttonsMargins;
|
||||
/** @since 3.6 */ protected final boolean buttonsFillVertically;
|
||||
protected final boolean centerTitle;
|
||||
protected final boolean centerTitleIfMenuBarEmbedded;
|
||||
/** @since 2.4 */ protected final boolean showIconBesideTitle;
|
||||
@@ -146,6 +153,9 @@ public class FlatTitlePane
|
||||
protected JButton restoreButton;
|
||||
protected JButton closeButton;
|
||||
|
||||
private JComponent iconifyMaximizeGapComp;
|
||||
private JComponent maximizeCloseGapComp;
|
||||
|
||||
protected Window window;
|
||||
|
||||
private final Handler handler;
|
||||
@@ -180,9 +190,7 @@ public class FlatTitlePane
|
||||
public FlatTitlePane( JRootPane rootPane ) {
|
||||
this.rootPane = rootPane;
|
||||
|
||||
Window w = SwingUtilities.getWindowAncestor( rootPane );
|
||||
String defaultWindowStyle = (w != null && w.getType() == Window.Type.UTILITY) ? WINDOW_STYLE_SMALL : null;
|
||||
windowStyle = clientProperty( rootPane, WINDOW_STYLE, defaultWindowStyle, String.class );
|
||||
windowStyle = getWindowStyle( rootPane );
|
||||
|
||||
titleFont = FlatUIUtils.getSubUIFont( "TitlePane.font", windowStyle );
|
||||
activeBackground = FlatUIUtils.getSubUIColor( "TitlePane.background", windowStyle );
|
||||
@@ -197,9 +205,14 @@ public class FlatTitlePane
|
||||
showIconInDialogs = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconInDialogs", windowStyle, true );
|
||||
noIconLeftGap = FlatUIUtils.getSubUIInt( "TitlePane.noIconLeftGap", windowStyle, 8 );
|
||||
iconSize = FlatUIUtils.getSubUIDimension( "TitlePane.iconSize", windowStyle );
|
||||
iconMargins = FlatUIUtils.getSubUIInsets( "TitlePane.iconMargins", windowStyle );
|
||||
titleMargins = FlatUIUtils.getSubUIInsets( "TitlePane.titleMargins", windowStyle );
|
||||
titleMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.titleMinimumWidth", windowStyle, 60 );
|
||||
buttonMinimumWidth = FlatUIUtils.getSubUIInt( "TitlePane.buttonMinimumWidth", windowStyle, 30 );
|
||||
buttonMaximizedHeight = FlatUIUtils.getSubUIInt( "TitlePane.buttonMaximizedHeight", windowStyle, 0 );
|
||||
buttonsGap = FlatUIUtils.getSubUIInt( "TitlePane.buttonsGap", windowStyle, 0 );
|
||||
buttonsMargins = FlatUIUtils.getSubUIInsets( "TitlePane.buttonsMargins", windowStyle );
|
||||
buttonsFillVertically = FlatUIUtils.getSubUIBoolean( "TitlePane.buttonsFillVertically", windowStyle, true );
|
||||
centerTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitle", windowStyle, false );
|
||||
centerTitleIfMenuBarEmbedded = FlatUIUtils.getSubUIBoolean( "TitlePane.centerTitleIfMenuBarEmbedded", windowStyle, true );
|
||||
showIconBesideTitle = FlatUIUtils.getSubUIBoolean( "TitlePane.showIconBesideTitle", windowStyle, false );
|
||||
@@ -229,6 +242,12 @@ public class FlatTitlePane
|
||||
applyComponentOrientation( rootPane.getComponentOrientation() );
|
||||
}
|
||||
|
||||
static String getWindowStyle( JRootPane rootPane ) {
|
||||
Window w = SwingUtilities.getWindowAncestor( rootPane );
|
||||
String defaultWindowStyle = (w != null && w.getType() == Window.Type.UTILITY) ? WINDOW_STYLE_SMALL : null;
|
||||
return clientProperty( rootPane, WINDOW_STYLE, defaultWindowStyle, String.class );
|
||||
}
|
||||
|
||||
protected FlatTitlePaneBorder createTitlePaneBorder() {
|
||||
return new FlatTitlePaneBorder();
|
||||
}
|
||||
@@ -246,8 +265,8 @@ public class FlatTitlePane
|
||||
setUI( new FlatTitleLabelUI() );
|
||||
}
|
||||
};
|
||||
iconLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.iconMargins", windowStyle ) ) );
|
||||
titleLabel.setBorder( new FlatEmptyBorder( FlatUIUtils.getSubUIInsets( "TitlePane.titleMargins", windowStyle ) ) );
|
||||
iconLabel.setBorder( new FlatEmptyBorder( iconMargins ) );
|
||||
titleLabel.setBorder( new FlatEmptyBorder( titleMargins ) );
|
||||
|
||||
leftPanel.setLayout( new BoxLayout( leftPanel, BoxLayout.LINE_AXIS ) );
|
||||
leftPanel.setOpaque( false );
|
||||
@@ -350,10 +369,15 @@ public class FlatTitlePane
|
||||
restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() );
|
||||
closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() );
|
||||
|
||||
iconifyMaximizeGapComp = createButtonsGapComp();
|
||||
maximizeCloseGapComp = createButtonsGapComp();
|
||||
|
||||
// initially hide buttons that are only supported in frames
|
||||
iconifyButton.setVisible( false );
|
||||
maximizeButton.setVisible( false );
|
||||
restoreButton.setVisible( false );
|
||||
iconifyMaximizeGapComp.setVisible( false );
|
||||
maximizeCloseGapComp.setVisible( false );
|
||||
|
||||
buttonPanel = new JPanel() {
|
||||
@Override
|
||||
@@ -365,12 +389,13 @@ public class FlatTitlePane
|
||||
|
||||
if( buttonMaximizedHeight > 0 && isWindowMaximized() && !hasVisibleEmbeddedMenuBar( rootPane.getJMenuBar() ) ) {
|
||||
// make title pane height smaller when frame is maximized
|
||||
size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight ) ) );
|
||||
size = new Dimension( size.width, Math.min( size.height, UIScale.scale( buttonMaximizedHeight + buttonsMargins.top + buttonsMargins.bottom ) ) );
|
||||
}
|
||||
return size;
|
||||
}
|
||||
};
|
||||
buttonPanel.setOpaque( false );
|
||||
buttonPanel.setBorder( FlatUIUtils.nonUIResource( new FlatEmptyBorder( buttonsMargins ) ) );
|
||||
buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS ) );
|
||||
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
||||
// JRootPane.FRAME works only for frames (and not for dialogs)
|
||||
@@ -379,8 +404,10 @@ public class FlatTitlePane
|
||||
// later in frameStateChanged(), which is invoked from addNotify()
|
||||
|
||||
buttonPanel.add( iconifyButton );
|
||||
buttonPanel.add( iconifyMaximizeGapComp );
|
||||
buttonPanel.add( maximizeButton );
|
||||
buttonPanel.add( restoreButton );
|
||||
buttonPanel.add( maximizeCloseGapComp );
|
||||
}
|
||||
buttonPanel.add( closeButton );
|
||||
|
||||
@@ -397,13 +424,17 @@ public class FlatTitlePane
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
// allow the button to shrink if space is rare
|
||||
return new Dimension( UIScale.scale( buttonMinimumWidth ), super.getMinimumSize().height );
|
||||
return new Dimension(
|
||||
Math.min( UIScale.scale( buttonMinimumWidth ), super.getPreferredSize().width ),
|
||||
super.getMinimumSize().height );
|
||||
}
|
||||
@Override
|
||||
public Dimension getMaximumSize() {
|
||||
// allow the button to fill whole button area height
|
||||
// see also BasicMenuUI.getMaximumSize()
|
||||
return new Dimension( super.getMaximumSize().width, Short.MAX_VALUE );
|
||||
return buttonsFillVertically
|
||||
? new Dimension( super.getMaximumSize().width, Short.MAX_VALUE )
|
||||
: super.getMaximumSize();
|
||||
}
|
||||
};
|
||||
button.setFocusable( false );
|
||||
@@ -414,6 +445,14 @@ public class FlatTitlePane
|
||||
return button;
|
||||
}
|
||||
|
||||
private JComponent createButtonsGapComp() {
|
||||
JComponent gapComp = new JPanel();
|
||||
gapComp.setOpaque( false );
|
||||
gapComp.setMinimumSize( new Dimension( 0, 0 ) );
|
||||
gapComp.setPreferredSize( new Dimension( UIScale.scale( buttonsGap ), 0 ) );
|
||||
return gapComp;
|
||||
}
|
||||
|
||||
protected void activeChanged( boolean active ) {
|
||||
Color background = clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null );
|
||||
Color foreground = clientPropertyColor( rootPane, TITLE_BAR_FOREGROUND, null );
|
||||
@@ -435,6 +474,9 @@ public class FlatTitlePane
|
||||
closeButton.setForeground( foreground );
|
||||
|
||||
// this is necessary because hover/pressed colors are derived from background color
|
||||
// (since FlatWindowAbstractIcon now invokes FlatTitlePane.getBackground()
|
||||
// to get base color, this is no longer necessary, but keep it for compatibility;
|
||||
// e.g. for custom window icons)
|
||||
iconifyButton.setBackground( background );
|
||||
maximizeButton.setBackground( background );
|
||||
restoreButton.setBackground( background );
|
||||
@@ -494,6 +536,13 @@ public class FlatTitlePane
|
||||
maximizeButton.setVisible( false );
|
||||
restoreButton.setVisible( false );
|
||||
}
|
||||
|
||||
boolean iconifyVisible = iconifyButton.isVisible();
|
||||
boolean maximizeVisible = maximizeButton.isVisible();
|
||||
boolean restoreVisible = restoreButton.isVisible();
|
||||
boolean closeVisible = closeButton.isVisible();
|
||||
iconifyMaximizeGapComp.setVisible( iconifyVisible && (maximizeVisible || restoreVisible || closeVisible) );
|
||||
maximizeCloseGapComp.setVisible( closeVisible && (maximizeVisible || restoreVisible) );
|
||||
}
|
||||
|
||||
protected void updateIcon() {
|
||||
@@ -747,12 +796,17 @@ public class FlatTitlePane
|
||||
if( isFullWindowContent() )
|
||||
return;
|
||||
|
||||
g.setColor( getBackground() );
|
||||
g.fillRect( 0, 0, getWidth(), getHeight() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
// not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime
|
||||
g.setColor( (UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||
return (UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||
clientPropertyColor( rootPane, TITLE_BAR_BACKGROUND, null ) == null)
|
||||
? FlatUIUtils.getParentBackground( this )
|
||||
: getBackground() );
|
||||
g.fillRect( 0, 0, getWidth(), getHeight() );
|
||||
: super.getBackground();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1094,6 +1148,7 @@ public class FlatTitlePane
|
||||
if( !c.isDisplayable() || !c.isVisible() || !contains( c, x, y ) || c == mouseLayer )
|
||||
return true; // continue checking with next component
|
||||
|
||||
// check enabled component that has mouse listeners
|
||||
if( c.isEnabled() &&
|
||||
(c.getMouseListeners().length > 0 ||
|
||||
c.getMouseMotionListeners().length > 0) )
|
||||
@@ -1417,22 +1472,9 @@ debug*/
|
||||
|
||||
private Point dragOffset;
|
||||
private boolean linuxNativeMove;
|
||||
private long lastSingleClickWhen;
|
||||
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e ) {
|
||||
// on Linux, when using native library, the mouse clicked event
|
||||
// is usually not sent and maximize/restore is done in mouse pressed event
|
||||
// this check is here for the case that a mouse clicked event comes through for some reason
|
||||
if( linuxNativeMove && SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||
// see comment in mousePressed()
|
||||
if( lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() ) {
|
||||
lastSingleClickWhen = 0;
|
||||
maximizeOrRestore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) ) {
|
||||
if( SwingUtilities.getDeepestComponentAt( FlatTitlePane.this, e.getX(), e.getY() ) == iconLabel ) {
|
||||
// double-click on icon closes window
|
||||
@@ -1463,42 +1505,6 @@ debug*/
|
||||
|
||||
dragOffset = SwingUtilities.convertPoint( mouseLayer, e.getPoint(), window );
|
||||
linuxNativeMove = false;
|
||||
|
||||
// on Linux, move or maximize/restore window
|
||||
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||
// The fired Java mouse events, when doing a double-click and the first click
|
||||
// sends a _NET_WM_MOVERESIZE message, are different for various Linux distributions:
|
||||
// CentOS 7 (GNOME 3.28.2, X11): PRESSED(clickCount=1) PRESSED(clickCount=2) RELEASED(clickCount=2)
|
||||
// Ubuntu 20.04 (GNOME 3.36.1, X11): PRESSED(clickCount=1) PRESSED(clickCount=2) RELEASED(clickCount=2)
|
||||
// Ubuntu 22.04 (GNOME 42.2, Wayland): PRESSED(clickCount=1) RELEASED(clickCount=1) CLICKED(clickCount=1)
|
||||
// Kubuntu 22.04 (KDE 5.24.4, X11): PRESSED(clickCount=1) PRESSED(clickCount=1) RELEASED(clickCount=1)
|
||||
|
||||
// double-click is not always recognized in Java when using _NET_WM_MOVERESIZE message
|
||||
int clickCount = e.getClickCount();
|
||||
if( clickCount == 1 && lastSingleClickWhen != 0 && (e.getWhen() - lastSingleClickWhen) <= getMultiClickInterval() )
|
||||
clickCount = 2;
|
||||
|
||||
switch( clickCount ) {
|
||||
case 1:
|
||||
// move window via _NET_WM_MOVERESIZE message
|
||||
e.consume();
|
||||
linuxNativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
|
||||
lastSingleClickWhen = e.getWhen();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// maximize/restore on double-click
|
||||
// also done here because no mouse clicked event is sent when using _NET_WM_MOVERESIZE message
|
||||
lastSingleClickWhen = 0;
|
||||
maximizeOrRestore();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getMultiClickInterval() {
|
||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "awt.multiClickInterval" );
|
||||
return (value instanceof Integer) ? (Integer) value : 500;
|
||||
}
|
||||
|
||||
@Override public void mouseReleased( MouseEvent e ) {}
|
||||
@@ -1521,6 +1527,13 @@ debug*/
|
||||
if( hasNativeCustomDecoration() )
|
||||
return; // do nothing if having native window border
|
||||
|
||||
// on Linux, move window using window manager
|
||||
if( SystemInfo.isLinux && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||
linuxNativeMove = FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, FlatNativeLinuxLibrary.MOVE );
|
||||
if( linuxNativeMove )
|
||||
return;
|
||||
}
|
||||
|
||||
// restore window if it is maximized
|
||||
if( window instanceof Frame ) {
|
||||
Frame frame = (Frame) window;
|
||||
|
||||
@@ -41,7 +41,6 @@ import java.util.function.Supplier;
|
||||
import javax.swing.DesktopManager;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -60,8 +59,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public abstract class FlatWindowResizer
|
||||
implements PropertyChangeListener, ComponentListener
|
||||
{
|
||||
protected final static Integer WINDOW_RESIZER_LAYER = JLayeredPane.DRAG_LAYER + 1;
|
||||
|
||||
protected final JComponent resizeComp;
|
||||
|
||||
protected final int borderDragThickness = FlatUIUtils.getUIInt( "RootPane.borderDragThickness", 5 );
|
||||
@@ -82,12 +79,12 @@ public abstract class FlatWindowResizer
|
||||
leftDragComp = createDragBorderComponent( NW_RESIZE_CURSOR, W_RESIZE_CURSOR, SW_RESIZE_CURSOR );
|
||||
rightDragComp = createDragBorderComponent( NE_RESIZE_CURSOR, E_RESIZE_CURSOR, SE_RESIZE_CURSOR );
|
||||
|
||||
Container cont = (resizeComp instanceof JRootPane) ? ((JRootPane)resizeComp).getLayeredPane() : resizeComp;
|
||||
Object cons = (cont instanceof JLayeredPane) ? WINDOW_RESIZER_LAYER : null;
|
||||
cont.add( topDragComp, cons, 0 );
|
||||
cont.add( bottomDragComp, cons, 1 );
|
||||
cont.add( leftDragComp, cons, 2 );
|
||||
cont.add( rightDragComp, cons, 3 );
|
||||
// for rootpanes, add after glasspane
|
||||
int insertIndex = (resizeComp instanceof JRootPane) ? 1 : 0;
|
||||
resizeComp.add( topDragComp, insertIndex++ );
|
||||
resizeComp.add( bottomDragComp, insertIndex++ );
|
||||
resizeComp.add( leftDragComp, insertIndex++ );
|
||||
resizeComp.add( rightDragComp, insertIndex++ );
|
||||
|
||||
resizeComp.addComponentListener( this );
|
||||
resizeComp.addPropertyChangeListener( "ancestor", this );
|
||||
@@ -106,11 +103,10 @@ public abstract class FlatWindowResizer
|
||||
resizeComp.removeComponentListener( this );
|
||||
resizeComp.removePropertyChangeListener( "ancestor", this );
|
||||
|
||||
Container cont = topDragComp.getParent();
|
||||
cont.remove( topDragComp );
|
||||
cont.remove( bottomDragComp );
|
||||
cont.remove( leftDragComp );
|
||||
cont.remove( rightDragComp );
|
||||
resizeComp.remove( topDragComp );
|
||||
resizeComp.remove( bottomDragComp );
|
||||
resizeComp.remove( leftDragComp );
|
||||
resizeComp.remove( rightDragComp );
|
||||
}
|
||||
|
||||
public void doLayout() {
|
||||
@@ -121,7 +117,7 @@ public abstract class FlatWindowResizer
|
||||
int y = 0;
|
||||
int width = resizeComp.getWidth();
|
||||
int height = resizeComp.getHeight();
|
||||
if( width == 0 || height == 0 )
|
||||
if( width <= 0 || height <= 0 )
|
||||
return;
|
||||
|
||||
Insets resizeInsets = getResizeInsets();
|
||||
@@ -192,7 +188,7 @@ public abstract class FlatWindowResizer
|
||||
protected abstract Dimension getWindowMinimumSize();
|
||||
protected abstract Dimension getWindowMaximumSize();
|
||||
|
||||
protected void beginResizing( int resizeDir ) {}
|
||||
protected void beginResizing( int resizeDir, MouseEvent e ) {}
|
||||
protected void endResizing() {}
|
||||
|
||||
//---- interface PropertyChangeListener ----
|
||||
@@ -251,8 +247,7 @@ public abstract class FlatWindowResizer
|
||||
centerComp = new JPanel();
|
||||
centerComp.setOpaque( false );
|
||||
centerComp.setVisible( false );
|
||||
Container cont = rootPane.getLayeredPane();
|
||||
cont.add( centerComp, WINDOW_RESIZER_LAYER, 4 );
|
||||
rootPane.add( centerComp, 5 );
|
||||
|
||||
// On Linux, limit window resizing to screen bounds because otherwise
|
||||
// there would be a strange effect when the mouse is moved over a sidebar
|
||||
@@ -262,8 +257,7 @@ public abstract class FlatWindowResizer
|
||||
|
||||
@Override
|
||||
public void uninstall() {
|
||||
Container cont = topDragComp.getParent();
|
||||
cont.remove( centerComp );
|
||||
resizeComp.remove( centerComp );
|
||||
|
||||
super.uninstall();
|
||||
}
|
||||
@@ -376,7 +370,25 @@ public abstract class FlatWindowResizer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beginResizing( int resizeDir ) {
|
||||
protected void beginResizing( int resizeDir, MouseEvent e ) {
|
||||
// on Linux, resize window using window manager
|
||||
if( SystemInfo.isLinux && window != null && FlatNativeLinuxLibrary.isWMUtilsSupported( window ) ) {
|
||||
int direction = -1;
|
||||
switch( resizeDir ) {
|
||||
case N_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOP; break;
|
||||
case S_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOM; break;
|
||||
case W_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_LEFT; break;
|
||||
case E_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_RIGHT; break;
|
||||
case NW_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOPLEFT; break;
|
||||
case NE_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_TOPRIGHT; break;
|
||||
case SW_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOMLEFT; break;
|
||||
case SE_RESIZE_CURSOR: direction = FlatNativeLinuxLibrary.SIZE_BOTTOMRIGHT; break;
|
||||
}
|
||||
|
||||
if( direction >= 0 && FlatNativeLinuxLibrary.moveOrResizeWindow( window, e, direction ) )
|
||||
return;
|
||||
}
|
||||
|
||||
centerComp.setBounds( 0, 0, resizeComp.getWidth(), resizeComp.getHeight() );
|
||||
centerComp.setCursor( getPredefinedCursor( resizeDir ) );
|
||||
centerComp.setVisible( true );
|
||||
@@ -468,7 +480,7 @@ public abstract class FlatWindowResizer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beginResizing( int resizeDir ) {
|
||||
protected void beginResizing( int resizeDir, MouseEvent e ) {
|
||||
int direction = 0;
|
||||
switch( resizeDir ) {
|
||||
case N_RESIZE_CURSOR: direction = NORTH; break;
|
||||
@@ -587,7 +599,7 @@ debug*/
|
||||
dragRightOffset = windowBounds.x + windowBounds.width - xOnScreen;
|
||||
dragBottomOffset = windowBounds.y + windowBounds.height - yOnScreen;
|
||||
|
||||
beginResizing( resizeDir );
|
||||
beginResizing( resizeDir, e );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.function.BiPredicate;
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class StackUtils
|
||||
public class StackUtils
|
||||
{
|
||||
private static final StackUtils INSTANCE = new StackUtilsImpl();
|
||||
|
||||
|
||||
@@ -224,6 +224,9 @@ public class ColorFunctions
|
||||
if( functions.length == 1 && functions[0] instanceof Mix ) {
|
||||
Mix mixFunction = (Mix) functions[0];
|
||||
return mix( color, mixFunction.color2, mixFunction.weight / 100 );
|
||||
} else if( functions.length == 1 && functions[0] instanceof Mix2 ) {
|
||||
Mix2 mixFunction = (Mix2) functions[0];
|
||||
return mix( mixFunction.color1, color, mixFunction.weight / 100 );
|
||||
}
|
||||
|
||||
// convert RGB to HSL
|
||||
@@ -386,7 +389,11 @@ public class ColorFunctions
|
||||
//---- class Mix ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Mix two colors.
|
||||
* Mix two colors using {@link ColorFunctions#mix(Color, Color, float)}.
|
||||
* First color is passed to {@link #apply(float[])}.
|
||||
* Second color is {@link #color2}.
|
||||
* <p>
|
||||
* Use {@link Mix2} to tint or shade color.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
@@ -420,4 +427,44 @@ public class ColorFunctions
|
||||
return String.format( "mix(#%08x,%.0f%%)", color2.getRGB(), weight );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class Mix2 ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Mix two colors using {@link ColorFunctions#mix(Color, Color, float)}.
|
||||
* First color is {@link #color1}.
|
||||
* Second color is passed to {@link #apply(float[])}.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public static class Mix2
|
||||
implements ColorFunction
|
||||
{
|
||||
public final Color color1;
|
||||
public final float weight;
|
||||
|
||||
public Mix2( Color color1, float weight ) {
|
||||
this.color1 = color1;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply( float[] hsla ) {
|
||||
// convert from HSL to RGB because color mixing is done on RGB values
|
||||
Color color2 = HSLColor.toRGB( hsla[0], hsla[1], hsla[2], hsla[3] / 100 );
|
||||
|
||||
// mix
|
||||
Color color = mix( color1, color2, weight / 100 );
|
||||
|
||||
// convert RGB to HSL
|
||||
float[] hsl = HSLColor.fromRGB( color );
|
||||
System.arraycopy( hsl, 0, hsla, 0, hsl.length );
|
||||
hsla[3] = (color.getAlpha() / 255f) * 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format( "mix2(#%08x,%.0f%%)", color1.getRGB(), weight );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
@@ -27,7 +28,9 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.RepaintManager;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.FlatSystemProperties;
|
||||
import com.formdev.flatlaf.ui.StackUtils;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
@@ -323,6 +326,19 @@ public class HiDPIUtils
|
||||
public void drawGlyphVector( GlyphVector g, float x, float y ) {
|
||||
super.drawGlyphVector( g, x, y + yCorrection );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect( int x, int y, int width, int height ) {
|
||||
// fix hard coded black color in HRuleView.paint() of '<hr noshade>'
|
||||
if( super.getColor() == Color.black &&
|
||||
StackUtils.wasInvokedFrom( "javax.swing.text.html.HRuleView", "paint", 4 ) )
|
||||
{
|
||||
super.setColor( FlatLaf.isLafDark() ? Color.lightGray : Color.darkGray );
|
||||
super.fillRect( x, y, width, height );
|
||||
super.setColor( Color.black );
|
||||
} else
|
||||
super.fillRect( x, y, width, height );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ public class SystemInfo
|
||||
public static final boolean isWindows;
|
||||
public static final boolean isMacOS;
|
||||
public static final boolean isLinux;
|
||||
/** @since 3.6 */ public static final boolean isUnknownOS;
|
||||
|
||||
// OS versions
|
||||
public static final long osVersion;
|
||||
@@ -59,6 +60,7 @@ public class SystemInfo
|
||||
public static final boolean isJetBrainsJVM_11_orLater;
|
||||
|
||||
// UI toolkits
|
||||
/** @since 3.6 */ public static final boolean isGNOME;
|
||||
public static final boolean isKDE;
|
||||
|
||||
// other
|
||||
@@ -75,6 +77,7 @@ public class SystemInfo
|
||||
isWindows = osName.startsWith( "windows" );
|
||||
isMacOS = osName.startsWith( "mac" );
|
||||
isLinux = osName.startsWith( "linux" );
|
||||
isUnknownOS = !isWindows && !isMacOS && !isLinux;
|
||||
|
||||
// OS versions
|
||||
osVersion = scanVersion( System.getProperty( "os.version" ) );
|
||||
@@ -104,7 +107,13 @@ public class SystemInfo
|
||||
isJetBrainsJVM_11_orLater = isJetBrainsJVM && isJava_11_orLater;
|
||||
|
||||
// UI toolkits
|
||||
isKDE = (isLinux && System.getenv( "KDE_FULL_SESSION" ) != null);
|
||||
String desktop = isLinux ? System.getenv( "XDG_CURRENT_DESKTOP" ) : null;
|
||||
isGNOME = (isLinux &&
|
||||
(System.getenv( "GNOME_DESKTOP_SESSION_ID" ) != null ||
|
||||
(desktop != null && desktop.contains( "GNOME" ))));
|
||||
isKDE = (isLinux &&
|
||||
(System.getenv( "KDE_FULL_SESSION" ) != null ||
|
||||
(desktop != null && desktop.contains( "KDE" ))));
|
||||
|
||||
// other
|
||||
isProjector = Boolean.getBoolean( "org.jetbrains.projector.server.enable" );
|
||||
|
||||
@@ -61,7 +61,6 @@ Component.arrowType = triangle
|
||||
#---- ProgressBar ----
|
||||
|
||||
ProgressBar.foreground = darken(@foreground,10%)
|
||||
ProgressBar.selectionForeground = @background
|
||||
|
||||
|
||||
#---- RadioButton ----
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
# general background and foreground (text color)
|
||||
@background = #3c3f41
|
||||
@foreground = #bbb
|
||||
@foreground = #ddd
|
||||
@disabledBackground = @background
|
||||
@disabledForeground = shade(@foreground,25%)
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
# selection
|
||||
@selectionBackground = @accentSelectionBackground
|
||||
@selectionForeground = contrast(@selectionBackground, @background, @foreground, 25%)
|
||||
@selectionForeground = contrast(@selectionBackground, shade(@background), tint(@foreground), 25%)
|
||||
@selectionInactiveBackground = spin(saturate(shade(@selectionBackground,70%),20%),-15)
|
||||
@selectionInactiveForeground = @foreground
|
||||
|
||||
@@ -187,6 +187,8 @@ Component.error.borderColor = desaturate($Component.error.focusedBorderColor,25%
|
||||
Component.error.focusedBorderColor = #8b3c3c
|
||||
Component.warning.borderColor = darken(desaturate($Component.warning.focusedBorderColor,20%),10%)
|
||||
Component.warning.focusedBorderColor = #ac7920
|
||||
Component.success.borderColor = desaturate($Component.success.focusedBorderColor,25%)
|
||||
Component.success.focusedBorderColor = #648b3c
|
||||
Component.custom.borderColor = desaturate(#f00,50%,relative derived noAutoInverse)
|
||||
|
||||
|
||||
@@ -262,7 +264,7 @@ PopupMenu.hoverScrollArrowBackground = lighten(@background,5%)
|
||||
ProgressBar.background = lighten(@background,8%)
|
||||
ProgressBar.foreground = @accentSliderColor
|
||||
ProgressBar.selectionBackground = @foreground
|
||||
ProgressBar.selectionForeground = contrast($ProgressBar.foreground, @background, @foreground, 25%)
|
||||
ProgressBar.selectionForeground = contrast($ProgressBar.foreground, shade(@background), tint(@foreground), 25%)
|
||||
|
||||
|
||||
#---- RootPane ----
|
||||
@@ -284,7 +286,7 @@ ScrollBar.pressedButtonBackground = lighten(@background,10%,derived noAutoInvers
|
||||
|
||||
#---- Separator ----
|
||||
|
||||
Separator.foreground = tint(@background,10%)
|
||||
Separator.foreground = tint(@background,15%)
|
||||
|
||||
|
||||
#---- Slider ----
|
||||
@@ -341,8 +343,13 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
||||
#---- TitlePane ----
|
||||
|
||||
TitlePane.embeddedForeground = darken($TitlePane.foreground,15%)
|
||||
TitlePane.buttonHoverBackground = lighten($TitlePane.background,15%,derived)
|
||||
TitlePane.buttonPressedBackground = lighten($TitlePane.background,10%,derived)
|
||||
TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived)
|
||||
TitlePane.buttonPressedBackground = lighten($TitlePane.background,6%,derived)
|
||||
|
||||
# Linux
|
||||
[linux]TitlePane.buttonBackground = lighten($TitlePane.background,5%,derived)
|
||||
[linux]TitlePane.buttonHoverBackground = lighten($TitlePane.background,10%,derived)
|
||||
[linux]TitlePane.buttonPressedBackground = lighten($TitlePane.background,15%,derived)
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
@@ -50,6 +50,9 @@ mini.font = -3
|
||||
#defaultFont = ...
|
||||
|
||||
# font weights
|
||||
# fallback for unknown platform
|
||||
light.font = +0
|
||||
semibold.font = +0
|
||||
# Windows
|
||||
[win]light.font = "Segoe UI Light"
|
||||
[win]semibold.font = "Segoe UI Semibold"
|
||||
@@ -59,15 +62,12 @@ mini.font = -3
|
||||
# Linux
|
||||
[linux]light.font = "Lato Light", "Ubuntu Light", "Cantarell Light"
|
||||
[linux]semibold.font = "Lato Semibold", "Ubuntu Medium", "Montserrat SemiBold"
|
||||
# fallback for unknown platform
|
||||
light.font = +0
|
||||
semibold.font = +0
|
||||
|
||||
# monospaced
|
||||
monospaced.font = Monospaced
|
||||
[win]monospaced.font = Monospaced
|
||||
[mac]monospaced.font = Menlo, Monospaced
|
||||
[linux]monospaced.font = "Liberation Mono", "Ubuntu Mono", Monospaced
|
||||
monospaced.font = Monospaced
|
||||
|
||||
# styles
|
||||
[style].h00 = font: $h00.font
|
||||
@@ -564,8 +564,8 @@ RadioButtonMenuItem.background = @menuBackground
|
||||
#---- RootPane ----
|
||||
|
||||
RootPane.border = com.formdev.flatlaf.ui.FlatRootPaneUI$FlatWindowBorder
|
||||
RootPane.borderDragThickness = 5
|
||||
RootPane.cornerDragWidth = 16
|
||||
RootPane.borderDragThickness = 6
|
||||
RootPane.cornerDragWidth = 32
|
||||
RootPane.honorFrameMinimumSizeOnResize = false
|
||||
RootPane.honorDialogMinimumSizeOnResize = true
|
||||
|
||||
@@ -823,9 +823,14 @@ TitlePane.iconMargins = 3,8,3,8
|
||||
TitlePane.titleMargins = 3,0,3,0
|
||||
TitlePane.titleMinimumWidth = 60
|
||||
TitlePane.buttonSize = 44,30
|
||||
TitlePane.buttonInsets = 0,0,0,0
|
||||
TitlePane.buttonArc = 0
|
||||
TitlePane.buttonMinimumWidth = 30
|
||||
TitlePane.buttonMaximizedHeight = 22
|
||||
TitlePane.buttonSymbolHeight = 10
|
||||
TitlePane.buttonsGap = 0
|
||||
TitlePane.buttonsMargins = 0,0,0,0
|
||||
TitlePane.buttonsFillVertically = true
|
||||
TitlePane.centerTitle = false
|
||||
TitlePane.centerTitleIfMenuBarEmbedded = true
|
||||
TitlePane.showIconBesideTitle = false
|
||||
@@ -856,6 +861,27 @@ TitlePane.small.iconifyIcon = com.formdev.flatlaf.icons.FlatWindowIconifyIcon, s
|
||||
TitlePane.small.maximizeIcon = com.formdev.flatlaf.icons.FlatWindowMaximizeIcon, small
|
||||
TitlePane.small.restoreIcon = com.formdev.flatlaf.icons.FlatWindowRestoreIcon, small
|
||||
|
||||
# Linux
|
||||
[linux]TitlePane.buttonSize = 26,26
|
||||
[linux]TitlePane.buttonInsets = 2,2,2,2
|
||||
[linux]TitlePane.buttonArc = 999
|
||||
[linux]TitlePane.buttonMaximizedHeight = -1
|
||||
[linux]TitlePane.buttonSymbolHeight = 8
|
||||
[linux]TitlePane.buttonsGap = 8
|
||||
[linux]TitlePane.buttonsMargins = 4,4,4,4
|
||||
[linux]TitlePane.buttonsFillVertically = false
|
||||
[linux]TitlePane.small.buttonSize = 20,20
|
||||
[linux]TitlePane.small.buttonInsets = 1,1,1,1
|
||||
[linux]TitlePane.small.buttonSymbolHeight = 6
|
||||
[linux]TitlePane.small.buttonsGap = 4
|
||||
[linux]TitlePane.small.buttonsMargins = 2,2,2,2
|
||||
[linux]TitlePane.closeBackground = $?TitlePane.buttonBackground
|
||||
[linux]TitlePane.closeInactiveBackground = $?TitlePane.buttonInactiveBackground
|
||||
[linux]TitlePane.closeHoverBackground = $?TitlePane.buttonHoverBackground
|
||||
[linux]TitlePane.closePressedBackground = $?TitlePane.buttonPressedBackground
|
||||
[linux]TitlePane.closeHoverForeground = $?TitlePane.foreground
|
||||
[linux]TitlePane.closePressedForeground = $?TitlePane.foreground
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
@background = #f2f2f2
|
||||
@foreground = #000
|
||||
@disabledBackground = @background
|
||||
@disabledForeground = tint(@foreground,55%)
|
||||
@disabledForeground = tint(@foreground,50%)
|
||||
|
||||
# component background
|
||||
@buttonBackground = lighten(@background,5%)
|
||||
@@ -194,6 +194,8 @@ Component.error.borderColor = lighten(desaturate($Component.error.focusedBorderC
|
||||
Component.error.focusedBorderColor = #e53e4d
|
||||
Component.warning.borderColor = lighten(saturate($Component.warning.focusedBorderColor,25%),20%)
|
||||
Component.warning.focusedBorderColor = #e2a53a
|
||||
Component.success.borderColor = lighten(desaturate($Component.success.focusedBorderColor,20%),25%)
|
||||
Component.success.focusedBorderColor = #14dc92
|
||||
Component.custom.borderColor = lighten(desaturate(#f00,20%,derived noAutoInverse),25%,derived noAutoInverse)
|
||||
|
||||
|
||||
@@ -347,8 +349,13 @@ TableHeader.bottomSeparatorColor = $TableHeader.separatorColor
|
||||
#---- TitlePane ----
|
||||
|
||||
TitlePane.embeddedForeground = lighten($TitlePane.foreground,35%)
|
||||
TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
|
||||
TitlePane.buttonPressedBackground = darken($TitlePane.background,8%,derived)
|
||||
TitlePane.buttonHoverBackground = darken($TitlePane.background,5%,derived)
|
||||
TitlePane.buttonPressedBackground = darken($TitlePane.background,3%,derived)
|
||||
|
||||
# Linux
|
||||
[linux]TitlePane.buttonBackground = darken($TitlePane.background,5%,derived)
|
||||
[linux]TitlePane.buttonHoverBackground = darken($TitlePane.background,10%,derived)
|
||||
[linux]TitlePane.buttonPressedBackground = darken($TitlePane.background,15%,derived)
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
@@ -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-<author>}',
|
||||
# where '<author>' is replaced with "author" value from .theme.json file
|
||||
# 6. properties starting with '{<name>---<author>}',
|
||||
# where '<name>' and '<author>' are replaced with "name" and "author" values from .theme.json file
|
||||
# 7. properties starting with '{<name>}',
|
||||
# where '<name>' 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,34 +77,33 @@ 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 ----
|
||||
|
||||
# colors from JBUI.CurrentTheme.DefaultTabs.inactiveUnderlineColor()
|
||||
[light]TabbedPane.inactiveUnderlineColor = #9ca7b8
|
||||
[dark]TabbedPane.inactiveUnderlineColor = #747a80
|
||||
{*-light}TabbedPane.inactiveUnderlineColor = #9ca7b8
|
||||
{*-dark}TabbedPane.inactiveUnderlineColor = #747a80
|
||||
|
||||
|
||||
#---- 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,357 +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_-_Orange]ProgressBar.selectionForeground = #fff
|
||||
[Arc_Theme_Dark_-_Orange]ToolBar.separatorColor = lazy(Separator.foreground)
|
||||
{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
|
||||
|
||||
[Carbon]Table.selectionBackground = lazy(List.selectionBackground)
|
||||
[Carbon]Table.selectionInactiveForeground = lazy(List.selectionInactiveForeground)
|
||||
[Carbon]TextField.background = @ijTextBackgroundL4
|
||||
{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}RadioButtonMenuItem.foreground = $MenuItem.foreground
|
||||
{Arc_Theme_Dark_-_Orange}ToolBar.background = @background
|
||||
|
||||
[Cobalt_2]Component.accentColor = lazy(Component.focusColor)
|
||||
[Cobalt_2]CheckBox.icon.background = #002946
|
||||
[Cobalt_2]CheckBox.icon.checkmarkColor = #002946
|
||||
[Cobalt_2]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||
[Cobalt_2]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||
[Cobalt_2]ComboBox.background = @ijTextBackgroundL3
|
||||
[Cobalt_2]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||
[Cobalt_2]TextField.background = @ijTextBackgroundL3
|
||||
[Cobalt_2]Table.background = lazy(List.background)
|
||||
[Cobalt_2]Tree.background = lazy(List.background)
|
||||
{Carbon}Separator.foreground = @ijSeparatorDark
|
||||
{Carbon}ToolBar.separatorColor = $Separator.foreground
|
||||
{Carbon}Table.selectionBackground = $List.selectionBackground
|
||||
{Carbon}TextField.background = @ijTextBackgroundL4
|
||||
|
||||
[Cyan_light]MenuItem.checkBackground = @ijMenuCheckBackgroundL20
|
||||
[Cyan_light]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL20
|
||||
{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}Slider.thumbColor = $ProgressBar.foreground
|
||||
{Cobalt_2}Slider.disabledTrackColor = $Separator.foreground
|
||||
{Cobalt_2}TextField.background = @ijTextBackgroundL3
|
||||
{Cobalt_2}Table.background = $List.background
|
||||
{Cobalt_2}Tree.background = $List.background
|
||||
|
||||
[Dark_Flat_Theme]*.inactiveForeground = #808080
|
||||
[Dark_Flat_Theme]Component.accentColor = lazy(List.selectionBackground)
|
||||
[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)
|
||||
{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_purple]Slider.focusedColor = fade($Component.focusColor,70%,derived)
|
||||
{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}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
|
||||
|
||||
[Dracula---Zihan_Ma]Component.accentColor = lazy(Component.focusColor)
|
||||
[Dracula---Zihan_Ma]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
||||
[Dracula---Zihan_Ma]ProgressBar.selectionBackground = #fff
|
||||
[Dracula---Zihan_Ma]ProgressBar.selectionForeground = #fff
|
||||
{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}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||
{Gradianto_Dark_Fuchsia}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||
{Gradianto_Dark_Fuchsia}TextField.background = @ijTextBackgroundL4
|
||||
{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]TextField.background = @ijTextBackgroundL3
|
||||
[Gradianto_Deep_Ocean]Tree.background = lazy(List.background)
|
||||
{Gradianto_Deep_Ocean}Separator.foreground = @ijSeparatorDark
|
||||
{Gradianto_Deep_Ocean}ToolBar.separatorColor = $Separator.foreground
|
||||
{Gradianto_Deep_Ocean}TextField.background = @ijTextBackgroundL3
|
||||
{Gradianto_Deep_Ocean}Tree.background = $List.background
|
||||
|
||||
[Gradianto_Midnight_Blue]ScrollBar.thumb = #533B6B
|
||||
[Gradianto_Midnight_Blue]Table.selectionForeground = lazy(List.selectionForeground)
|
||||
[Gradianto_Midnight_Blue]TextField.background = @ijTextBackgroundL4
|
||||
[Gradianto_Midnight_Blue]Tree.background = lazy(List.background)
|
||||
{Gradianto_Midnight_Blue}ScrollBar.thumb = #533B6B
|
||||
{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 = $List.background
|
||||
|
||||
[Gradianto_Nature_Green]Table.selectionForeground = lazy(List.selectionForeground)
|
||||
[Gradianto_Nature_Green]TextField.background = @ijTextBackgroundL4
|
||||
{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]ComboBox.background = @ijTextBackgroundL3
|
||||
[Gruvbox_Dark_Hard]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||
[Gruvbox_Dark_Hard]TextField.background = @ijTextBackgroundL3
|
||||
{Gruvbox_Dark_Hard}@accentBaseColor = #4B6EAF
|
||||
{Gruvbox_Dark_Hard}ComboBox.background = @ijTextBackgroundL3
|
||||
{Gruvbox_Dark_Hard}ComboBox.buttonBackground = $ComboBox.background
|
||||
{Gruvbox_Dark_Hard}TextField.background = @ijTextBackgroundL3
|
||||
|
||||
[Gruvbox_Dark_Medium]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||
[Gruvbox_Dark_Medium]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Medium]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||
[Gruvbox_Dark_Medium]ComboBox.background = @ijTextBackgroundL3
|
||||
[Gruvbox_Dark_Medium]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||
[Gruvbox_Dark_Medium]TextField.background = @ijTextBackgroundL3
|
||||
{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
|
||||
|
||||
[Gruvbox_Dark_Soft]Component.accentColor = lazy(TabbedPane.underlineColor)
|
||||
[Gruvbox_Dark_Soft]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||
[Gruvbox_Dark_Soft]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||
[Gruvbox_Dark_Soft]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||
[Gruvbox_Dark_Soft]ComboBox.background = @ijTextBackgroundL3
|
||||
[Gruvbox_Dark_Soft]ComboBox.buttonBackground = @ijTextBackgroundL3
|
||||
[Gruvbox_Dark_Soft]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)
|
||||
|
||||
[High_contrast]Component.accentColor = lazy(Component.focusColor)
|
||||
[High_contrast]ToggleButton.selectedBackground = #fff
|
||||
[High_contrast]ToggleButton.selectedForeground = #000
|
||||
[High_contrast]ToggleButton.disabledSelectedBackground = #444
|
||||
[High_contrast]ToggleButton.toolbar.selectedBackground = #fff
|
||||
[High_contrast][style]Button.inTextField = \
|
||||
{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]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]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}@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}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 = $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]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]TextField.background = @ijTextBackgroundL4
|
||||
@Monocai.selectionBackground = lazy(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]List.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||
[Monocai]Table.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||
[Monocai]Tree.selectionInactiveBackground = @Monocai.selectionInactiveBackground
|
||||
{Monocai}@accentUnderlineColor = @accentBaseColor
|
||||
{Monocai}*.acceleratorForeground = @menuAcceleratorForeground
|
||||
{Monocai}*.acceleratorSelectionForeground = @menuAcceleratorSelectionForeground
|
||||
{Monocai}Button.default.foreground = @background
|
||||
{Monocai}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||
{Monocai}TabbedPane.underlineColor = @accentUnderlineColor
|
||||
{Monocai}TextField.background = @ijTextBackgroundL4
|
||||
@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 = $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]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}@disabledForeground = #616E88
|
||||
{Nord}*.disabledText = @disabledForeground
|
||||
{Nord}*.disabledForeground = @disabledForeground
|
||||
{Nord}*.inactiveForeground = @disabledForeground
|
||||
{Nord}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||
{Nord}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||
{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}*.selectionInactiveBackground = #21384E
|
||||
{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}MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||
{One_Dark}MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||
{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]TextField.background = @ijTextBackgroundL4
|
||||
[Spacegray]TextField.selectionBackground = lazy(Tree.selectionBackground)
|
||||
[Spacegray]TextField.selectionForeground = lazy(Tree.selectionForeground)
|
||||
{Spacegray}ComboBox.background = @ijTextBackgroundL4
|
||||
{Spacegray}ComboBox.buttonBackground = $ComboBox.background
|
||||
{Spacegray}TextField.background = @ijTextBackgroundL4
|
||||
|
||||
[vuesion-theme]*.disabledForeground = #8C8C8C
|
||||
[vuesion-theme]*.disabledText = #8C8C8C
|
||||
[vuesion-theme]*.inactiveForeground = #8C8C8C
|
||||
[vuesion-theme]Component.accentColor = lazy(Button.default.endBackground)
|
||||
[vuesion-theme]MenuItem.checkBackground = @ijMenuCheckBackgroundL10
|
||||
[vuesion-theme]MenuItem.underlineSelectionCheckBackground = @ijMenuCheckBackgroundL10
|
||||
[vuesion-theme]Slider.trackValueColor = #ececee
|
||||
[vuesion-theme]Slider.trackColor = #303a45
|
||||
[vuesion-theme]Slider.thumbColor = #ececee
|
||||
[vuesion-theme]Slider.focusedColor = fade(#ececee,20%)
|
||||
[vuesion-theme]ComboBox.background = @ijTextBackgroundL4
|
||||
[vuesion-theme]ComboBox.buttonBackground = @ijTextBackgroundL4
|
||||
[vuesion-theme]TextField.background = @ijTextBackgroundL4
|
||||
[vuesion-theme]TextField.selectionBackground = lighten(#303A45,15%)
|
||||
{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}ProgressBar.background = #303a45
|
||||
{vuesion-theme}ProgressBar.foreground = #ececee
|
||||
{vuesion-theme}Slider.thumbColor = #ececee
|
||||
{vuesion-theme}Slider.focusedColor = fade($Slider.thumbColor,20%)
|
||||
{vuesion-theme}ComboBox.background = @ijTextBackgroundL4
|
||||
{vuesion-theme}ComboBox.buttonBackground = $ComboBox.background
|
||||
{vuesion-theme}TextField.background = @ijTextBackgroundL4
|
||||
{vuesion-theme}TextField.selectionBackground = lighten(#303A45,15%)
|
||||
|
||||
[Xcode-Dark]TextField.background = @ijTextBackgroundL4
|
||||
{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
|
||||
|
||||
[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)
|
||||
|
||||
[GitHub]ProgressBar.selectionBackground = #222
|
||||
[GitHub]ProgressBar.selectionForeground = #222
|
||||
[GitHub]TextField.background = @ijTextBackgroundL3
|
||||
[GitHub]List.selectionBackground = lazy(Table.selectionBackground)
|
||||
[GitHub]Tree.selectionBackground = lazy(Table.selectionBackground)
|
||||
{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
|
||||
|
||||
[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)
|
||||
{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
|
||||
|
||||
[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]TextField.background = @ijTextBackgroundL3
|
||||
[Light_Owl]List.selectionBackground = lazy(Table.selectionBackground)
|
||||
[Light_Owl]Tree.selectionBackground = lazy(Table.selectionBackground)
|
||||
{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
|
||||
|
||||
[Material_Darker]*.selectionBackground = lighten(#2D2D2D,15%)
|
||||
[Material_Darker]Separator.foreground = lazy(Slider.trackColor)
|
||||
[Material_Darker]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||
{Dracula---Mallowigi}ProgressBar.selectionBackground = #fff
|
||||
{Dracula---Mallowigi}ProgressBar.selectionForeground = #fff
|
||||
{Dracula---Mallowigi}List.selectionBackground = $Table.selectionBackground
|
||||
{Dracula---Mallowigi}Tree.selectionBackground = $Table.selectionBackground
|
||||
{Dracula---Mallowigi}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
{Dracula---Mallowigi}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
|
||||
[Material_Deep_Ocean]*.selectionBackground = lighten(#222533,15%)
|
||||
[Material_Deep_Ocean]Separator.foreground = lazy(Slider.trackColor)
|
||||
[Material_Deep_Ocean]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||
{GitHub}ProgressBar.selectionBackground = #222
|
||||
{GitHub}ProgressBar.selectionForeground = #222
|
||||
{GitHub}TextField.background = @ijTextBackgroundL3
|
||||
{GitHub}List.selectionBackground = $Table.selectionBackground
|
||||
{GitHub}Tree.selectionBackground = $Table.selectionBackground
|
||||
{GitHub}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
{GitHub}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
|
||||
[Material_Lighter]List.selectionInactiveForeground = lazy(Tree.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)
|
||||
{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
|
||||
|
||||
[Material_Oceanic]ProgressBar.selectionBackground = #ddd
|
||||
[Material_Oceanic]ProgressBar.selectionForeground = #ddd
|
||||
[Material_Oceanic]Separator.foreground = lazy(Slider.trackColor)
|
||||
[Material_Oceanic]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||
{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 = $Table.selectionBackground
|
||||
{Light_Owl}Tree.selectionBackground = $Table.selectionBackground
|
||||
{Light_Owl}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
{Light_Owl}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
|
||||
[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_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
|
||||
|
||||
[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)
|
||||
{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
|
||||
|
||||
[Moonlight]ComboBox.selectionBackground = lazy(List.selectionBackground)
|
||||
[Moonlight]Table.selectionBackground = lazy(List.selectionBackground)
|
||||
[Moonlight]Separator.foreground = lazy(Slider.trackColor)
|
||||
[Moonlight]ToolBar.separatorColor = lazy(Slider.trackColor)
|
||||
{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}RadioButtonMenuItem.selectionForeground = $Table.selectionForeground
|
||||
{Material_Lighter}Table.selectionBackground = $List.selectionBackground
|
||||
{Material_Lighter}Tree.selectionForeground = $Table.selectionForeground
|
||||
{Material_Lighter}Tree.selectionInactiveBackground = $List.selectionInactiveBackground
|
||||
|
||||
[Night_Owl]ProgressBar.selectionBackground = #ddd
|
||||
[Night_Owl]ProgressBar.selectionForeground = #ddd
|
||||
{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}List.selectionBackground = $Table.selectionBackground
|
||||
{Material_Oceanic}Tree.selectionBackground = $Table.selectionBackground
|
||||
{Material_Oceanic}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
{Material_Oceanic}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
|
||||
[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)
|
||||
{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 = $Table.selectionBackground
|
||||
{Material_Palenight}Tree.selectionBackground = $Table.selectionBackground
|
||||
{Material_Palenight}List.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
{Material_Palenight}Table.selectionInactiveBackground = $Tree.selectionInactiveBackground
|
||||
|
||||
[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)
|
||||
{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 = $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}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}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
|
||||
|
||||
@@ -112,6 +112,7 @@ Button.borderWidth = 0
|
||||
Button.disabledBackground = darken($Button.background,10%)
|
||||
|
||||
Button.default.borderWidth = 0
|
||||
Button.default.foreground = contrast($Button.default.background, @background, @selectionForeground, 25%)
|
||||
|
||||
Button.toolbar.hoverBackground = #fff1
|
||||
Button.toolbar.pressedBackground = #fff2
|
||||
@@ -293,6 +294,7 @@ TextPane.selectionForeground = @textSelectionForeground
|
||||
|
||||
ToggleButton.disabledBackground = $Button.disabledBackground
|
||||
ToggleButton.selectedBackground = lighten($ToggleButton.background,20%,derived)
|
||||
ToggleButton.selectedForeground = lighten($ToggleButton.foreground,20%)
|
||||
|
||||
ToggleButton.toolbar.selectedBackground = #fff3
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
# general background and foreground (text color)
|
||||
@background = #f6f6f6
|
||||
@foreground = over(@nsControlTextColor,@background)
|
||||
@disabledForeground = over(@nsTertiaryLabelColor,@background)
|
||||
@disabledForeground = over(@nsSecondaryLabelColor,@background)
|
||||
|
||||
# component background
|
||||
@buttonBackground = @nsControlColor
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
@@ -29,6 +31,13 @@ import javax.swing.UIDefaults.LazyValue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.ColorFunction;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.Fade;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.HSLChange;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.HSLIncreaseDecrease;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.Mix;
|
||||
import com.formdev.flatlaf.util.ColorFunctions.Mix2;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
@@ -180,6 +189,269 @@ public class TestUIDefaultsLoader
|
||||
assertEquals( expected, ((LazyValue)UIDefaultsLoader.parseValue( "dummyIcon", value, null )).createValue( null ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseColorFunctions() {
|
||||
// lighten
|
||||
assertEquals( new Color( 0xff6666 ), parseColor( "lighten(#f00, 20%)" ) );
|
||||
assertEquals( new Color( 0xff3333 ), parseColor( "lighten(#f00, 20%, relative)" ) );
|
||||
assertEquals( new Color( 0xaaaaaa ), parseColor( "lighten(#ddd, 20%, autoInverse)" ) );
|
||||
assertEquals( new Color( 0xb1b1b1 ), parseColor( "lighten(#ddd, 20%, relative autoInverse)" ) );
|
||||
|
||||
// darken
|
||||
assertEquals( new Color( 0x990000 ), parseColor( "darken(#f00, 20%)" ) );
|
||||
assertEquals( new Color( 0xcc0000 ), parseColor( "darken(#f00, 20%, relative)" ) );
|
||||
assertEquals( new Color( 0x555555 ), parseColor( "darken(#222, 20%, autoInverse)" ) );
|
||||
assertEquals( new Color( 0x292929 ), parseColor( "darken(#222, 20%, relative autoInverse)" ) );
|
||||
|
||||
// saturate
|
||||
assertEquals( new Color( 0xf32e2e ), parseColor( "saturate(#d44, 20%)" ) );
|
||||
assertEquals( new Color( 0xec3535 ), parseColor( "saturate(#d44, 20%, relative)" ) );
|
||||
assertEquals( new Color( 0xc75a5a ), parseColor( "saturate(#d44, 20%, autoInverse)" ) );
|
||||
assertEquals( new Color( 0xce5353 ), parseColor( "saturate(#d44, 20%, relative autoInverse)" ) );
|
||||
|
||||
// desaturate
|
||||
assertEquals( new Color( 0x745858 ), parseColor( "desaturate(#844, 20%)" ) );
|
||||
assertEquals( new Color( 0x814b4b ), parseColor( "desaturate(#844, 20%, relative)" ) );
|
||||
assertEquals( new Color( 0x9c3030 ), parseColor( "desaturate(#844, 20%, autoInverse)" ) );
|
||||
assertEquals( new Color( 0x8f3d3d ), parseColor( "desaturate(#844, 20%, relative autoInverse)" ) );
|
||||
|
||||
// fadein
|
||||
assertEquals( new Color( 0xddff0000, true ), parseColor( "fadein(#f00a, 20%)" ) );
|
||||
assertEquals( new Color( 0xccff0000, true ), parseColor( "fadein(#f00a, 20%, relative)" ) );
|
||||
assertEquals( new Color( 0x77ff0000, true ), parseColor( "fadein(#f00a, 20%, autoInverse)" ) );
|
||||
assertEquals( new Color( 0x88ff0000, true ), parseColor( "fadein(#f00a, 20%, relative autoInverse)" ) );
|
||||
|
||||
// fadeout
|
||||
assertEquals( new Color( 0x11ff0000, true ), parseColor( "fadeout(#f004, 20%)" ) );
|
||||
assertEquals( new Color( 0x36ff0000, true ), parseColor( "fadeout(#f004, 20%, relative)" ) );
|
||||
assertEquals( new Color( 0x77ff0000, true ), parseColor( "fadeout(#f004, 20%, autoInverse)" ) );
|
||||
assertEquals( new Color( 0x52ff0000, true ), parseColor( "fadeout(#f004, 20%, relative autoInverse)" ) );
|
||||
|
||||
// fade
|
||||
assertEquals( new Color( 0x33ff0000, true ), parseColor( "fade(#f00, 20%)" ) );
|
||||
assertEquals( new Color( 0xccff0000, true ), parseColor( "fade(#ff000010, 80%)" ) );
|
||||
|
||||
// spin
|
||||
assertEquals( new Color( 0xffaa00 ), parseColor( "spin(#f00, 40)" ) );
|
||||
assertEquals( new Color( 0xff00aa ), parseColor( "spin(#f00, -40)" ) );
|
||||
|
||||
// changeHue / changeSaturation / changeLightness / changeAlpha
|
||||
assertEquals( new Color( 0xffaa00 ), parseColor( "changeHue(#f00, 40)" ) );
|
||||
assertEquals( new Color( 0xb34d4d ), parseColor( "changeSaturation(#f00, 40%)" ) );
|
||||
assertEquals( new Color( 0xcc0000 ), parseColor( "changeLightness(#f00, 40%)" ) );
|
||||
assertEquals( new Color( 0x66ff0000, true ), parseColor( "changeAlpha(#f00, 40%)" ) );
|
||||
|
||||
// mix
|
||||
assertEquals( new Color( 0x808000 ), parseColor( "mix(#f00, #0f0)" ) );
|
||||
assertEquals( new Color( 0xbf4000 ), parseColor( "mix(#f00, #0f0, 75%)" ) );
|
||||
|
||||
// tint
|
||||
assertEquals( new Color( 0xff80ff ), parseColor( "tint(#f0f)" ) );
|
||||
assertEquals( new Color( 0xffbfff ), parseColor( "tint(#f0f, 75%)" ) );
|
||||
|
||||
// shade
|
||||
assertEquals( new Color( 0x800080 ), parseColor( "shade(#f0f)" ) );
|
||||
assertEquals( new Color( 0x400040 ), parseColor( "shade(#f0f, 75%)" ) );
|
||||
|
||||
// contrast
|
||||
assertEquals( new Color( 0x0000ff ), parseColor( "contrast(#bbb, #00f, #0f0)" ) );
|
||||
assertEquals( new Color( 0x00ff00 ), parseColor( "contrast(#444, #00f, #0f0)" ) );
|
||||
assertEquals( new Color( 0x00ff00 ), parseColor( "contrast(#bbb, #00f, #0f0, 60%)" ) );
|
||||
|
||||
// rgb / rgba
|
||||
assertEquals( new Color( 0x5a8120 ), parseColor( "rgb(90, 129, 32)" ) );
|
||||
assertEquals( new Color( 0x5a8120 ), parseColor( "rgb(90, 129, 32)" ) );
|
||||
assertEquals( new Color( 0x197fb2 ), parseColor( "rgb(10%,50%,70%)" ) );
|
||||
assertEquals( new Color( 0x197f46 ), parseColor( "rgb(10%,50%,70)" ) );
|
||||
assertEquals( new Color( 0x405a8120, true ), parseColor( "rgba(90, 129, 32, 64)" ) );
|
||||
assertEquals( new Color( 0x335a8120, true ), parseColor( "rgba(90, 129, 32, 20%)" ) );
|
||||
|
||||
// hsl / hsla
|
||||
assertEquals( new Color( 0x7fff00 ), parseColor( "hsl(90, 100%, 50%)" ) );
|
||||
assertEquals( new Color( 0x337fff00, true ), parseColor( "hsla(90, 100%, 50%, 20%)" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseLazyColorFunctions() {
|
||||
// lighten
|
||||
assertEquals( new Color( 0xff6666 ), parseColorLazy( "lighten(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
|
||||
|
||||
// darken
|
||||
assertEquals( new Color( 0x990000 ), parseColorLazy( "darken(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
|
||||
|
||||
// saturate
|
||||
assertEquals( new Color( 0xf32e2e ), parseColorLazy( "saturate(dummyColor, 20%, lazy)", new Color( 0xdd4444 ) ) );
|
||||
|
||||
// desaturate
|
||||
assertEquals( new Color( 0x745858 ), parseColorLazy( "desaturate(dummyColor, 20%, lazy)", new Color( 0x884444 ) ) );
|
||||
|
||||
// fadein
|
||||
assertEquals( new Color( 0xddff0000, true ), parseColorLazy( "fadein(dummyColor, 20%, lazy)", new Color( 0xaaff0000, true ) ) );
|
||||
|
||||
// fadeout
|
||||
assertEquals( new Color( 0x11ff0000, true ), parseColorLazy( "fadeout(dummyColor, 20%, lazy)", new Color( 0x44ff0000, true ) ) );
|
||||
|
||||
// fade
|
||||
assertEquals( new Color( 0x33ff0000, true ), parseColorLazy( "fade(dummyColor, 20%, lazy)", new Color( 0xff0000 ) ) );
|
||||
assertEquals( new Color( 0xccff0000, true ), parseColorLazy( "fade(dummyColor, 80%, lazy)", new Color( 0x10ff0000, true ) ) );
|
||||
|
||||
// spin
|
||||
assertEquals( new Color( 0xffaa00 ), parseColorLazy( "spin(dummyColor, 40, lazy)", new Color( 0xff0000 ) ) );
|
||||
assertEquals( new Color( 0xff00aa ), parseColorLazy( "spin(dummyColor, -40, lazy)", new Color( 0xff0000 ) ) );
|
||||
|
||||
// changeHue / changeSaturation / changeLightness / changeAlpha
|
||||
assertEquals( new Color( 0xffaa00 ), parseColorLazy( "changeHue(dummyColor, 40, lazy)", new Color( 0xff0000 ) ) );
|
||||
assertEquals( new Color( 0xb34d4d ), parseColorLazy( "changeSaturation(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
|
||||
assertEquals( new Color( 0xcc0000 ), parseColorLazy( "changeLightness(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
|
||||
assertEquals( new Color( 0x66ff0000, true ), parseColorLazy( "changeAlpha(dummyColor, 40%, lazy)", new Color( 0xff0000 ) ) );
|
||||
|
||||
// mix
|
||||
assertEquals( new Color( 0x808000 ), parseColorLazy( "mix(#f00, dummyColor, lazy)", new Color( 0x00ff00 ) ) );
|
||||
assertEquals( new Color( 0xbf4000 ), parseColorLazy( "mix(#f00, dummyColor, 75%, lazy)", new Color( 0x00ff00 ) ) );
|
||||
|
||||
// tint
|
||||
assertEquals( new Color( 0xff80ff ), parseColorLazy( "tint(dummyColor, lazy)", new Color( 0xff00ff ) ) );
|
||||
assertEquals( new Color( 0xffbfff ), parseColorLazy( "tint(dummyColor, 75%, lazy)", new Color( 0xff00ff ) ) );
|
||||
|
||||
// shade
|
||||
assertEquals( new Color( 0x800080 ), parseColorLazy( "shade(dummyColor, lazy)", new Color( 0xff00ff ) ) );
|
||||
assertEquals( new Color( 0x400040 ), parseColorLazy( "shade(dummyColor, 75%, lazy)", new Color( 0xff00ff ) ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseDerivedColorFunctions() {
|
||||
// mix
|
||||
assertDerivedColorEquals( new Color( 0x808000 ), "mix(#f00, #0f0, derived)", new Mix2( Color.red, 50 ) );
|
||||
assertDerivedColorEquals( new Color( 0xbf4000 ), "mix(#f00, #0f0, 75%, derived)", new Mix2( Color.red, 75 ) );
|
||||
|
||||
// tint
|
||||
assertDerivedColorEquals( new Color( 0xff80ff ), "tint(#f0f, derived)", new Mix2( Color.white, 50 ) );
|
||||
assertDerivedColorEquals( new Color( 0xffbfff ), "tint(#f0f, 75%, derived)", new Mix2( Color.white, 75 ) );
|
||||
|
||||
// shade
|
||||
assertDerivedColorEquals( new Color( 0x800080 ), "shade(#f0f, derived)", new Mix2( Color.black, 50 ) );
|
||||
assertDerivedColorEquals( new Color( 0x400040 ), "shade(#f0f, 75%, derived)", new Mix2( Color.black, 75 ) );
|
||||
|
||||
|
||||
// lighten
|
||||
assertDerivedColorEquals( new Color( 0xff6666 ), "lighten(#f00, 20%, derived)", new HSLIncreaseDecrease( 2, true, 20, false, true ) );
|
||||
assertDerivedColorEquals( new Color( 0xff3333 ), "lighten(#f00, 20%, derived relative)", new HSLIncreaseDecrease( 2, true, 20, true, true ) );
|
||||
assertDerivedColorEquals( new Color( 0xffffff ), "lighten(#ddd, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 2, true, 20, false, false ) );
|
||||
assertDerivedColorEquals( new Color( 0xffffff ), "lighten(#ddd, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 2, true, 20, true, false ) );
|
||||
|
||||
// darken
|
||||
assertDerivedColorEquals( new Color( 0x990000 ), "darken(#f00, 20%, derived)", new HSLIncreaseDecrease( 2, false, 20, false, true ) );
|
||||
assertDerivedColorEquals( new Color( 0xcc0000 ), "darken(#f00, 20%, derived relative)", new HSLIncreaseDecrease( 2, false, 20, true, true ) );
|
||||
assertDerivedColorEquals( new Color( 0x000000 ), "darken(#222, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 2, false, 20, false, false ) );
|
||||
assertDerivedColorEquals( new Color( 0x1b1b1b ), "darken(#222, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 2, false, 20, true, false ) );
|
||||
|
||||
// saturate
|
||||
assertDerivedColorEquals( new Color( 0xc75a5a ), "saturate(#d44, 20%, derived)", new HSLIncreaseDecrease( 1, true, 20, false, true ) );
|
||||
assertDerivedColorEquals( new Color( 0xce5353 ), "saturate(#d44, 20%, derived relative)", new HSLIncreaseDecrease( 1, true, 20, true, true ) );
|
||||
assertDerivedColorEquals( new Color( 0xf32e2e ), "saturate(#d44, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 1, true, 20, false, false ) );
|
||||
assertDerivedColorEquals( new Color( 0xec3535 ), "saturate(#d44, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 1, true, 20, true, false ) );
|
||||
|
||||
// desaturate
|
||||
assertDerivedColorEquals( new Color( 0x9c3030 ), "desaturate(#844, 20%, derived)", new HSLIncreaseDecrease( 1, false, 20, false, true ) );
|
||||
assertDerivedColorEquals( new Color( 0x8f3d3d ), "desaturate(#844, 20%, derived relative)", new HSLIncreaseDecrease( 1, false, 20, true, true ) );
|
||||
assertDerivedColorEquals( new Color( 0x745858 ), "desaturate(#844, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 1, false, 20, false, false ) );
|
||||
assertDerivedColorEquals( new Color( 0x814b4b ), "desaturate(#844, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 1, false, 20, true, false ) );
|
||||
|
||||
// fadein
|
||||
assertDerivedColorEquals( new Color( 0x77ff0000, true ), "fadein(#f00a, 20%, derived)", new HSLIncreaseDecrease( 3, true, 20, false, true ) );
|
||||
assertDerivedColorEquals( new Color( 0x88ff0000, true ), "fadein(#f00a, 20%, derived relative)", new HSLIncreaseDecrease( 3, true, 20, true, true ) );
|
||||
assertDerivedColorEquals( new Color( 0xddff0000, true ), "fadein(#f00a, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 3, true, 20, false, false ) );
|
||||
assertDerivedColorEquals( new Color( 0xccff0000, true ), "fadein(#f00a, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 3, true, 20, true, false ) );
|
||||
|
||||
// fadeout
|
||||
assertDerivedColorEquals( new Color( 0x77ff0000, true ), "fadeout(#f004, 20%, derived)", new HSLIncreaseDecrease( 3, false, 20, false, true ) );
|
||||
assertDerivedColorEquals( new Color( 0x52ff0000, true ), "fadeout(#f004, 20%, derived relative)", new HSLIncreaseDecrease( 3, false, 20, true, true ) );
|
||||
assertDerivedColorEquals( new Color( 0x11ff0000, true ), "fadeout(#f004, 20%, derived noAutoInverse)", new HSLIncreaseDecrease( 3, false, 20, false, false ) );
|
||||
assertDerivedColorEquals( new Color( 0x36ff0000, true ), "fadeout(#f004, 20%, derived relative noAutoInverse)", new HSLIncreaseDecrease( 3, false, 20, true, false ) );
|
||||
|
||||
// fade
|
||||
assertDerivedColorEquals( new Color( 0x33ff0000, true ), "fade(#f00, 20%, derived)", new Fade( 20 ) );
|
||||
assertDerivedColorEquals( new Color( 0xccff0000, true ), "fade(#ff000010, 80%, derived)", new Fade( 80 ) );
|
||||
|
||||
// spin
|
||||
assertDerivedColorEquals( new Color( 0xffaa00 ), "spin(#f00, 40, derived)", new HSLIncreaseDecrease( 0, true, 40, false, false ) );
|
||||
assertDerivedColorEquals( new Color( 0xff00aa ), "spin(#f00, -40, derived)", new HSLIncreaseDecrease( 0, true, -40, false, false ) );
|
||||
|
||||
// changeHue / changeSaturation / changeLightness / changeAlpha
|
||||
assertDerivedColorEquals( new Color( 0xffaa00 ), "changeHue(#f00, 40, derived)", new HSLChange( 0, 40 ) );
|
||||
assertDerivedColorEquals( new Color( 0xb34d4d ), "changeSaturation(#f00, 40%, derived)", new HSLChange( 1, 40 ) );
|
||||
assertDerivedColorEquals( new Color( 0xcc0000 ), "changeLightness(#f00, 40%, derived)", new HSLChange( 2, 40 ) );
|
||||
assertDerivedColorEquals( new Color( 0x66ff0000, true ), "changeAlpha(#f00, 40%, derived)", new HSLChange( 3, 40 ) );
|
||||
|
||||
// mix
|
||||
assertDerivedColorEquals( new Color( 0x808000 ), "mix(#f00, #0f0, derived)", new Mix2( new Color( 0xff0000 ), 50 ) );
|
||||
assertDerivedColorEquals( new Color( 0xbf4000 ), "mix(#f00, #0f0, 75%, derived)", new Mix2( new Color( 0xff0000 ), 75 ) );
|
||||
|
||||
// tint
|
||||
assertDerivedColorEquals( new Color( 0xff80ff ), "tint(#f0f, derived)", new Mix2( new Color( 0xffffff ), 50 ) );
|
||||
assertDerivedColorEquals( new Color( 0xffbfff ), "tint(#f0f, 75%, derived)", new Mix2( new Color( 0xffffff ), 75 ) );
|
||||
|
||||
// shade
|
||||
assertDerivedColorEquals( new Color( 0x800080 ), "shade(#f0f, derived)", new Mix2( new Color( 0x000000 ), 50 ) );
|
||||
assertDerivedColorEquals( new Color( 0x400040 ), "shade(#f0f, 75%, derived)", new Mix2( new Color( 0x000000 ), 75 ) );
|
||||
}
|
||||
|
||||
private void assertDerivedColorEquals( Color expectedColor, String actualStyle, ColorFunction... expectedFunctions ) {
|
||||
Object actual = parseColor( actualStyle );
|
||||
assertInstanceOf( DerivedColor.class, actual );
|
||||
assertEquals( expectedColor, actual );
|
||||
|
||||
ColorFunction[] actualFunctions = ((DerivedColor)actual).getFunctions();
|
||||
assertEquals( expectedFunctions.length, actualFunctions.length );
|
||||
for( int i = 0; i < expectedFunctions.length; i++ )
|
||||
assertColorFunctionEquals( expectedFunctions[i], actualFunctions[i] );
|
||||
}
|
||||
|
||||
private void assertColorFunctionEquals( ColorFunction expected, ColorFunction actual ) {
|
||||
assertEquals( expected.getClass(), actual.getClass() );
|
||||
|
||||
if( expected instanceof HSLIncreaseDecrease ) {
|
||||
HSLIncreaseDecrease e = (HSLIncreaseDecrease) expected;
|
||||
HSLIncreaseDecrease a = (HSLIncreaseDecrease) actual;
|
||||
assertEquals( e.hslIndex, a.hslIndex );
|
||||
assertEquals( e.increase, a.increase );
|
||||
assertEquals( e.amount, a.amount );
|
||||
assertEquals( e.relative, a.relative );
|
||||
assertEquals( e.autoInverse, a.autoInverse );
|
||||
} else if( expected instanceof HSLChange ) {
|
||||
HSLChange e = (HSLChange) expected;
|
||||
HSLChange a = (HSLChange) actual;
|
||||
assertEquals( e.hslIndex, a.hslIndex );
|
||||
assertEquals( e.value, a.value );
|
||||
} else if( expected instanceof Fade ) {
|
||||
Fade e = (Fade) expected;
|
||||
Fade a = (Fade) actual;
|
||||
assertEquals( e.amount, a.amount );
|
||||
} else if( expected instanceof Mix ) {
|
||||
Mix e = (Mix) expected;
|
||||
Mix a = (Mix) actual;
|
||||
assertEquals( e.color2, a.color2 );
|
||||
assertEquals( e.weight, a.weight );
|
||||
} else if( expected instanceof Mix2 ) {
|
||||
Mix2 e = (Mix2) expected;
|
||||
Mix2 a = (Mix2) actual;
|
||||
assertEquals( e.color1, a.color1 );
|
||||
assertEquals( e.weight, a.weight );
|
||||
} else
|
||||
assertTrue( false );
|
||||
}
|
||||
|
||||
private Object parseColor( String value ) {
|
||||
return UIDefaultsLoader.parseValue( "dummyColor", value, null );
|
||||
}
|
||||
|
||||
private Object parseColorLazy( String value, Color actual ) {
|
||||
UIManager.put( "dummyColor", actual );
|
||||
Object v = UIDefaultsLoader.parseValue( "dummyColor", value, null );
|
||||
assertInstanceOf( LazyValue.class, v );
|
||||
return ((LazyValue)v).createValue( null );
|
||||
}
|
||||
|
||||
//---- class TestInstance -------------------------------------------------
|
||||
|
||||
@SuppressWarnings( "EqualsHashCode" ) // Error Prone
|
||||
|
||||
@@ -1080,6 +1080,8 @@ public class TestFlatStyleableInfo
|
||||
"error.focusedBorderColor", Color.class,
|
||||
"warning.borderColor", Color.class,
|
||||
"warning.focusedBorderColor", Color.class,
|
||||
"success.borderColor", Color.class,
|
||||
"success.focusedBorderColor", Color.class,
|
||||
"custom.borderColor", Color.class,
|
||||
|
||||
"outline", String.class,
|
||||
|
||||
@@ -1024,6 +1024,8 @@ public class TestFlatStyleableValue
|
||||
testColor( c, ui, "error.focusedBorderColor", 0x123456 );
|
||||
testColor( c, ui, "warning.borderColor", 0x123456 );
|
||||
testColor( c, ui, "warning.focusedBorderColor", 0x123456 );
|
||||
testColor( c, ui, "success.borderColor", 0x123456 );
|
||||
testColor( c, ui, "success.focusedBorderColor", 0x123456 );
|
||||
testColor( c, ui, "custom.borderColor", 0x123456 );
|
||||
|
||||
testString( c, ui, "outline", "error" );
|
||||
@@ -1121,6 +1123,8 @@ public class TestFlatStyleableValue
|
||||
testValue( border, "error.focusedBorderColor", Color.WHITE );
|
||||
testValue( border, "warning.borderColor", Color.WHITE );
|
||||
testValue( border, "warning.focusedBorderColor", Color.WHITE );
|
||||
testValue( border, "success.borderColor", Color.WHITE );
|
||||
testValue( border, "success.focusedBorderColor", Color.WHITE );
|
||||
testValue( border, "custom.borderColor", Color.WHITE );
|
||||
}
|
||||
|
||||
|
||||
@@ -1278,6 +1278,8 @@ public class TestFlatStyling
|
||||
applyStyle.accept( "error.focusedBorderColor: #fff" );
|
||||
applyStyle.accept( "warning.borderColor: #fff" );
|
||||
applyStyle.accept( "warning.focusedBorderColor: #fff" );
|
||||
applyStyle.accept( "success.borderColor: #fff" );
|
||||
applyStyle.accept( "success.focusedBorderColor: #fff" );
|
||||
applyStyle.accept( "custom.borderColor: desaturate(#f00,50%,relative derived noAutoInverse)" );
|
||||
|
||||
applyStyle.accept( "outline: error" );
|
||||
@@ -1363,6 +1365,8 @@ public class TestFlatStyling
|
||||
border.applyStyleProperty( "error.focusedBorderColor", Color.WHITE );
|
||||
border.applyStyleProperty( "warning.borderColor", Color.WHITE );
|
||||
border.applyStyleProperty( "warning.focusedBorderColor", Color.WHITE );
|
||||
border.applyStyleProperty( "success.borderColor", Color.WHITE );
|
||||
border.applyStyleProperty( "success.focusedBorderColor", Color.WHITE );
|
||||
border.applyStyleProperty( "custom.borderColor", Color.WHITE );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user