mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-09 16:25:10 +03:00
Styling: support specifying explicit value type for parsing CSS values (for future use)
This commit is contained in:
@@ -784,14 +784,17 @@ public abstract class FlatLaf
|
||||
* <p>
|
||||
* See: <a href="https://www.formdev.com/flatlaf/properties-files/">https://www.formdev.com/flatlaf/properties-files/</a>
|
||||
*
|
||||
* @param key the key, which is used to determine the value type
|
||||
* @param key the key, which is used to determine the value type if parameter {@code valueType} is {@code null}
|
||||
* @param value the value string
|
||||
* @param valueType the expected value type, or {@code null}
|
||||
* @return the binary value
|
||||
* @throws IllegalArgumentException on syntax errors
|
||||
* @since TODO
|
||||
*/
|
||||
public static Object parseDefaultsValue( String key, String value ) throws IllegalArgumentException {
|
||||
return UIDefaultsLoader.parseValue( key, value );
|
||||
public static Object parseDefaultsValue( String key, String value, Class<?> valueType )
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
return UIDefaultsLoader.parseValue( key, value, valueType );
|
||||
}
|
||||
|
||||
private static void reSetLookAndFeel() {
|
||||
|
||||
@@ -338,7 +338,7 @@ public class IntelliJTheme
|
||||
|
||||
// parse value
|
||||
try {
|
||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr );
|
||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr, null );
|
||||
} catch( RuntimeException ex ) {
|
||||
UIDefaultsLoader.logParseError( key, valueStr, ex, false );
|
||||
return; // ignore invalid value
|
||||
|
||||
@@ -33,8 +33,10 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.UIDefaults.ActiveValue;
|
||||
import javax.swing.UIDefaults.LazyValue;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
@@ -241,7 +243,7 @@ class UIDefaultsLoader
|
||||
|
||||
String value = resolveValue( (String) e.getValue(), propertiesGetter );
|
||||
try {
|
||||
defaults.put( key, parseValue( key, value, null, resolver, addonClassLoaders ) );
|
||||
defaults.put( key, parseValue( key, value, null, null, resolver, addonClassLoaders ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
logParseError( key, value, ex, true );
|
||||
}
|
||||
@@ -292,12 +294,13 @@ class UIDefaultsLoader
|
||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS, GRAYFILTER, NULL, LAZY }
|
||||
|
||||
private static ValueType[] tempResultValueType = new ValueType[1];
|
||||
private static Map<Class<?>, ValueType> javaValueTypes;
|
||||
|
||||
static Object parseValue( String key, String value ) {
|
||||
return parseValue( key, value, null, v -> v, Collections.emptyList() );
|
||||
static Object parseValue( String key, String value, Class<?> valueType ) {
|
||||
return parseValue( key, value, valueType, null, v -> v, Collections.emptyList() );
|
||||
}
|
||||
|
||||
static Object parseValue( String key, String value, ValueType[] resultValueType,
|
||||
static Object parseValue( String key, String value, Class<?> javaValueType, ValueType[] resultValueType,
|
||||
Function<String, String> resolver, List<ClassLoader> addonClassLoaders )
|
||||
{
|
||||
if( resultValueType == null )
|
||||
@@ -305,71 +308,106 @@ class UIDefaultsLoader
|
||||
|
||||
value = value.trim();
|
||||
|
||||
// null, false, true
|
||||
switch( value ) {
|
||||
case "null": resultValueType[0] = ValueType.NULL; return null;
|
||||
case "false": resultValueType[0] = ValueType.BOOLEAN; return false;
|
||||
case "true": resultValueType[0] = ValueType.BOOLEAN; return true;
|
||||
}
|
||||
|
||||
// check for function "lazy"
|
||||
// Syntax: lazy(uiKey)
|
||||
if( value.startsWith( "lazy(" ) && value.endsWith( ")" ) ) {
|
||||
resultValueType[0] = ValueType.LAZY;
|
||||
String uiKey = value.substring( 5, value.length() - 1 ).trim();
|
||||
return (LazyValue) t -> {
|
||||
return lazyUIManagerGet( uiKey );
|
||||
};
|
||||
// null
|
||||
if( value.equals( "null" ) ) {
|
||||
resultValueType[0] = ValueType.NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
ValueType valueType = ValueType.UNKNOWN;
|
||||
|
||||
// check whether value type is specified in the value
|
||||
if( value.startsWith( "#" ) )
|
||||
valueType = ValueType.COLOR;
|
||||
else if( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
|
||||
valueType = ValueType.STRING;
|
||||
value = value.substring( 1, value.length() - 1 );
|
||||
} else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
int end = value.indexOf( TYPE_PREFIX_END );
|
||||
if( end != -1 ) {
|
||||
try {
|
||||
String typeStr = value.substring( TYPE_PREFIX.length(), end );
|
||||
valueType = ValueType.valueOf( typeStr.toUpperCase( Locale.ENGLISH ) );
|
||||
if( javaValueType != null ) {
|
||||
if( javaValueTypes == null ) {
|
||||
// create lazy
|
||||
javaValueTypes = new HashMap<>();
|
||||
javaValueTypes.put( String.class, ValueType.STRING );
|
||||
javaValueTypes.put( boolean.class, ValueType.BOOLEAN );
|
||||
javaValueTypes.put( Boolean.class, ValueType.BOOLEAN );
|
||||
javaValueTypes.put( char.class, ValueType.CHARACTER );
|
||||
javaValueTypes.put( Character.class, ValueType.CHARACTER );
|
||||
javaValueTypes.put( int.class, ValueType.INTEGER );
|
||||
javaValueTypes.put( Integer.class, ValueType.INTEGER );
|
||||
javaValueTypes.put( float.class, ValueType.FLOAT );
|
||||
javaValueTypes.put( Float.class, ValueType.FLOAT );
|
||||
javaValueTypes.put( Border.class, ValueType.BORDER );
|
||||
javaValueTypes.put( Icon.class, ValueType.ICON );
|
||||
javaValueTypes.put( Insets.class, ValueType.INSETS );
|
||||
javaValueTypes.put( Dimension.class, ValueType.DIMENSION );
|
||||
javaValueTypes.put( Color.class, ValueType.COLOR );
|
||||
}
|
||||
|
||||
// remove type from value
|
||||
value = value.substring( end + TYPE_PREFIX_END.length() );
|
||||
} catch( IllegalArgumentException ex ) {
|
||||
// ignore
|
||||
// map java value type to parser value type
|
||||
valueType = javaValueTypes.get( javaValueType );
|
||||
if( valueType == null )
|
||||
throw new IllegalArgumentException( "unsupported value type '" + javaValueType.getName() + "'" );
|
||||
|
||||
// remove '"' from strings
|
||||
if( valueType == ValueType.STRING && value.startsWith( "\"" ) && value.endsWith( "\"" ) )
|
||||
value = value.substring( 1, value.length() - 1 );
|
||||
} else {
|
||||
// false, true
|
||||
switch( value ) {
|
||||
case "false": resultValueType[0] = ValueType.BOOLEAN; return false;
|
||||
case "true": resultValueType[0] = ValueType.BOOLEAN; return true;
|
||||
}
|
||||
|
||||
// check for function "lazy"
|
||||
// Syntax: lazy(uiKey)
|
||||
if( value.startsWith( "lazy(" ) && value.endsWith( ")" ) ) {
|
||||
resultValueType[0] = ValueType.LAZY;
|
||||
String uiKey = value.substring( 5, value.length() - 1 ).trim();
|
||||
return (LazyValue) t -> {
|
||||
return lazyUIManagerGet( uiKey );
|
||||
};
|
||||
}
|
||||
|
||||
// check whether value type is specified in the value
|
||||
if( value.startsWith( "#" ) )
|
||||
valueType = ValueType.COLOR;
|
||||
else if( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
|
||||
valueType = ValueType.STRING;
|
||||
value = value.substring( 1, value.length() - 1 );
|
||||
} else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
int end = value.indexOf( TYPE_PREFIX_END );
|
||||
if( end != -1 ) {
|
||||
try {
|
||||
String typeStr = value.substring( TYPE_PREFIX.length(), end );
|
||||
valueType = ValueType.valueOf( typeStr.toUpperCase( Locale.ENGLISH ) );
|
||||
|
||||
// remove type from value
|
||||
value = value.substring( end + TYPE_PREFIX_END.length() );
|
||||
} catch( IllegalArgumentException ex ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determine value type from key
|
||||
if( valueType == ValueType.UNKNOWN ) {
|
||||
if( key.endsWith( "UI" ) )
|
||||
valueType = ValueType.STRING;
|
||||
else if( key.endsWith( "Color" ) ||
|
||||
(key.endsWith( "ground" ) &&
|
||||
(key.endsWith( ".background" ) || key.endsWith( "Background" ) || key.equals( "background" ) ||
|
||||
key.endsWith( ".foreground" ) || key.endsWith( "Foreground" ) || key.equals( "foreground" ))) )
|
||||
valueType = ValueType.COLOR;
|
||||
else if( key.endsWith( ".border" ) || key.endsWith( "Border" ) )
|
||||
valueType = ValueType.BORDER;
|
||||
else if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) )
|
||||
valueType = ValueType.ICON;
|
||||
else if( key.endsWith( ".margin" ) || key.equals( "margin" ) ||
|
||||
key.endsWith( ".padding" ) || key.equals( "padding" ) ||
|
||||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
|
||||
valueType = ValueType.INSETS;
|
||||
else if( key.endsWith( "Size" ) )
|
||||
valueType = ValueType.DIMENSION;
|
||||
else if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
|
||||
valueType = ValueType.INTEGER;
|
||||
else if( key.endsWith( "Char" ) )
|
||||
valueType = ValueType.CHARACTER;
|
||||
else if( key.endsWith( "grayFilter" ) )
|
||||
valueType = ValueType.GRAYFILTER;
|
||||
// determine value type from key
|
||||
if( valueType == ValueType.UNKNOWN ) {
|
||||
if( key.endsWith( "UI" ) )
|
||||
valueType = ValueType.STRING;
|
||||
else if( key.endsWith( "Color" ) ||
|
||||
(key.endsWith( "ground" ) &&
|
||||
(key.endsWith( ".background" ) || key.endsWith( "Background" ) || key.equals( "background" ) ||
|
||||
key.endsWith( ".foreground" ) || key.endsWith( "Foreground" ) || key.equals( "foreground" ))) )
|
||||
valueType = ValueType.COLOR;
|
||||
else if( key.endsWith( ".border" ) || key.endsWith( "Border" ) )
|
||||
valueType = ValueType.BORDER;
|
||||
else if( key.endsWith( ".icon" ) || key.endsWith( "Icon" ) )
|
||||
valueType = ValueType.ICON;
|
||||
else if( key.endsWith( ".margin" ) || key.equals( "margin" ) ||
|
||||
key.endsWith( ".padding" ) || key.equals( "padding" ) ||
|
||||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
|
||||
valueType = ValueType.INSETS;
|
||||
else if( key.endsWith( "Size" ) )
|
||||
valueType = ValueType.DIMENSION;
|
||||
else if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
|
||||
valueType = ValueType.INTEGER;
|
||||
else if( key.endsWith( "Char" ) )
|
||||
valueType = ValueType.CHARACTER;
|
||||
else if( key.endsWith( "grayFilter" ) )
|
||||
valueType = ValueType.GRAYFILTER;
|
||||
}
|
||||
}
|
||||
|
||||
resultValueType[0] = valueType;
|
||||
@@ -377,6 +415,7 @@ class UIDefaultsLoader
|
||||
// parse value
|
||||
switch( valueType ) {
|
||||
case STRING: return value;
|
||||
case BOOLEAN: return parseBoolean( value );
|
||||
case CHARACTER: return parseCharacter( value );
|
||||
case INTEGER: return parseInteger( value, true );
|
||||
case FLOAT: return parseFloat( value, true );
|
||||
@@ -869,6 +908,14 @@ class UIDefaultsLoader
|
||||
return val;
|
||||
}
|
||||
|
||||
private static Boolean parseBoolean( String value ) {
|
||||
switch( value ) {
|
||||
case "false": return false;
|
||||
case "true": return true;
|
||||
}
|
||||
throw new IllegalArgumentException( "invalid boolean '" + value + "'" );
|
||||
}
|
||||
|
||||
private static Character parseCharacter( String value ) {
|
||||
if( value.length() != 1 )
|
||||
throw new IllegalArgumentException( "invalid character '" + value + "'" );
|
||||
|
||||
@@ -198,7 +198,7 @@ public class FlatStyleSupport
|
||||
if( key.startsWith( "[" ) )
|
||||
key = key.substring( key.indexOf( ']' ) + 1 );
|
||||
|
||||
return FlatLaf.parseDefaultsValue( key, value );
|
||||
return FlatLaf.parseDefaultsValue( key, value, null );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2021 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Insets;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class TestUIDefaultsLoader
|
||||
{
|
||||
@Test
|
||||
void parseValue() {
|
||||
assertEquals( null, UIDefaultsLoader.parseValue( "dummy", "null", null ) );
|
||||
assertEquals( false, UIDefaultsLoader.parseValue( "dummy", "false", null ) );
|
||||
assertEquals( true, UIDefaultsLoader.parseValue( "dummy", "true", null ) );
|
||||
|
||||
assertEquals( "hello", UIDefaultsLoader.parseValue( "dummy", "hello", null ) );
|
||||
assertEquals( "hello", UIDefaultsLoader.parseValue( "dummy", "\"hello\"", null ) );
|
||||
assertEquals( "null", UIDefaultsLoader.parseValue( "dummy", "\"null\"", null ) );
|
||||
|
||||
assertEquals( 'a', UIDefaultsLoader.parseValue( "dummyChar", "a", null ) );
|
||||
assertEquals( 123, UIDefaultsLoader.parseValue( "dummy", "123", null ) );
|
||||
assertEquals( 123, UIDefaultsLoader.parseValue( "dummyWidth", "123", null ) );
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", null ) );
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummyWidth", "{float}1.23", null ) );
|
||||
|
||||
assertEquals( new Insets( 2,2,2,2 ), UIDefaultsLoader.parseValue( "dummyInsets", "2,2,2,2", null ) );
|
||||
assertEquals( new Dimension( 2,2 ), UIDefaultsLoader.parseValue( "dummySize", "2,2", null ) );
|
||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", null ) );
|
||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummyColor", "#f00", null ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseValueWithJavaType() {
|
||||
assertEquals( null, UIDefaultsLoader.parseValue( "dummy", "null", String.class ) );
|
||||
assertEquals( false, UIDefaultsLoader.parseValue( "dummy", "false", boolean.class ) );
|
||||
assertEquals( true, UIDefaultsLoader.parseValue( "dummy", "true", Boolean.class ) );
|
||||
|
||||
assertEquals( "hello", UIDefaultsLoader.parseValue( "dummy", "hello", String.class ) );
|
||||
assertEquals( "hello", UIDefaultsLoader.parseValue( "dummy", "\"hello\"", String.class ) );
|
||||
assertEquals( "null", UIDefaultsLoader.parseValue( "dummy", "\"null\"", String.class ) );
|
||||
assertEquals( null, UIDefaultsLoader.parseValue( "dummy", "null", String.class ) );
|
||||
|
||||
assertEquals( 'a', UIDefaultsLoader.parseValue( "dummy", "a", char.class ) );
|
||||
assertEquals( 'a', UIDefaultsLoader.parseValue( "dummy", "a", Character.class ) );
|
||||
assertEquals( 123, UIDefaultsLoader.parseValue( "dummy", "123", int.class ) );
|
||||
assertEquals( 123, UIDefaultsLoader.parseValue( "dummy", "123", Integer.class ) );
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", float.class ) );
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", Float.class ) );
|
||||
|
||||
assertEquals( new Insets( 2,2,2,2 ), UIDefaultsLoader.parseValue( "dummy", "2,2,2,2", Insets.class ) );
|
||||
assertEquals( new Dimension( 2,2 ), UIDefaultsLoader.parseValue( "dummy", "2,2", Dimension.class ) );
|
||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", Color.class ) );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user