Theme Editor: support color preview for color functions

UIDefaultsLoader: made some private methods package private and return parsed valued type
This commit is contained in:
Karl Tauber
2020-07-07 14:03:39 +02:00
parent 283ba83cef
commit 7ed90cddf8
7 changed files with 242 additions and 17 deletions

View File

@@ -21,5 +21,5 @@ plugins {
dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( "com.fifesoft:rsyntaxtextarea:3.1.0" )
implementation( "com.fifesoft:rsyntaxtextarea:3.1.1" )
}

View File

@@ -16,6 +16,11 @@
package com.formdev.flatlaf;
import java.util.Collections;
import java.util.Properties;
import java.util.function.Function;
import com.formdev.flatlaf.UIDefaultsLoader.ValueType;
/**
* Enable accessing package private methods of {@link UIDefaultsLoader}.
*
@@ -23,6 +28,40 @@ package com.formdev.flatlaf;
*/
public class UIDefaultsLoaderAccessor
{
public static Object UNKNOWN = ValueType.UNKNOWN;
public static Object STRING = ValueType.STRING;
public static Object BOOLEAN = ValueType.BOOLEAN;
public static Object CHARACTER = ValueType.CHARACTER;
public static Object INTEGER = ValueType.INTEGER;
public static Object FLOAT = ValueType.FLOAT;
public static Object BORDER = ValueType.BORDER;
public static Object ICON = ValueType.ICON;
public static Object INSETS = ValueType.INSETS;
public static Object DIMENSION = ValueType.DIMENSION;
public static Object COLOR = ValueType.COLOR;
public static Object SCALEDINTEGER = ValueType.SCALEDINTEGER;
public static Object SCALEDFLOAT = ValueType.SCALEDFLOAT;
public static Object SCALEDINSETS = ValueType.SCALEDINSETS;
public static Object SCALEDDIMENSION = ValueType.SCALEDDIMENSION;
public static Object INSTANCE = ValueType.INSTANCE;
public static Object CLASS = ValueType.CLASS;
public static Object GRAYFILTER = ValueType.GRAYFILTER;
public static Object NULL = ValueType.NULL;
public static Object LAZY = ValueType.LAZY;
public static String resolveValue( Properties properties, String value ) {
return UIDefaultsLoader.resolveValue( properties, value );
}
public static Object parseValue( String key, String value, Object[] resultValueType,
Function<String, String> resolver )
{
ValueType[] resultValueType2 = new ValueType[1];
Object result = UIDefaultsLoader.parseValue( key, value, resultValueType2, resolver, Collections.emptyList() );
resultValueType[0] = resultValueType2[0];
return result;
}
public static int parseColorRGBA( String value ) {
return UIDefaultsLoader.parseColorRGBA( value );
}

View File

@@ -34,6 +34,7 @@ class FlatSyntaxTextArea
{
private boolean useColorOfColorTokens;
final FlatThemePropertiesSupport propertiesSupport = new FlatThemePropertiesSupport( this );
private final Map<String, Color> parsedColorsMap = new HashMap<>();
FlatSyntaxTextArea() {

View File

@@ -103,11 +103,18 @@ class FlatThemeEditorOverlay
g.setColor( color );
g.fillRect( px, r.y, pw, r.height );
// if color is semi-transparent paint also none-transparent color
int alpha = color.getAlpha();
if( alpha != 255 && pw > r.height * 2 ) {
g.setColor( new Color( color.getRGB() ) );
g.fillRect( px + pw - r.height, r.y, r.height, r.height );
}
// paint text
int textX = px - maxTextWidth;
if( textX > r.x + gap) {
float[] hsl = HSLColor.fromRGB( color );
String hslStr = String.format( "HSL %d %d %d",
String hslStr = String.format( "HSL %3d %2d %2d",
Math.round( hsl[0] ), Math.round( hsl[1] ), Math.round( hsl[2] ) );
g.setColor( textArea.getForeground() );
FlatUIUtils.drawString( textArea, g, hslStr, textX,
@@ -120,6 +127,10 @@ class FlatThemeEditorOverlay
}
private Color getColorInLine( FlatSyntaxTextArea textArea, int line ) {
Object value = textArea.propertiesSupport.getParsedValueAtLine( line );
if( value instanceof Color )
return (Color) value;
Token token = textArea.getTokenListForLine( line );
for( Token t = token; t != null && t.isPaintable(); t = t.getNextToken() ) {
if( t.getType() == FlatThemeTokenMaker.TOKEN_COLOR ) {

View File

@@ -0,0 +1,156 @@
/*
* Copyright 2020 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.themeeditor;
import java.awt.Color;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import com.formdev.flatlaf.UIDefaultsLoaderAccessor;
/**
* Supports parsing content of text area in FlatLaf properties syntax.
*
* @author Karl Tauber
*/
class FlatThemePropertiesSupport
implements DocumentListener
{
private final FlatSyntaxTextArea textArea;
private final Function<String, String> resolver;
private Properties propertiesCache;
private final Map<Integer, Object> parsedValueCache = new HashMap<>();
FlatThemePropertiesSupport( FlatSyntaxTextArea textArea ) {
this.textArea = textArea;
resolver = v -> {
return resolveValue( v );
};
textArea.getDocument().addDocumentListener( this );
}
private String resolveValue( String value ) {
return UIDefaultsLoaderAccessor.resolveValue( getProperties(), value );
}
Object getParsedValueAtLine( int line ) {
Integer lineKey = line;
Object parsedValue = parsedValueCache.get( lineKey );
if( parsedValue != null )
return !(parsedValue instanceof Exception) ? parsedValue : null;
KeyValue keyValue = getKeyValueAtLine( line );
if( keyValue == null )
return null;
try {
Object[] resultValueType = new Object[1];
String value = resolveValue( keyValue.value );
parsedValue = UIDefaultsLoaderAccessor.parseValue( keyValue.key, value, resultValueType, resolver );
parsedValueCache.put( lineKey, parsedValue );
return parsedValue;
} catch( Exception ex ) {
System.out.println( ex.getMessage() ); //TODO
parsedValueCache.put( lineKey, ex );
return null;
}
}
private KeyValue getKeyValueAtLine( int line ) {
try {
int startOffset = textArea.getLineStartOffset( line );
int endOffset = textArea.getLineEndOffset( line );
String text = textArea.getText( startOffset, endOffset - startOffset );
Properties properties = new Properties();
properties.load( new StringReader( text ) );
if( properties.isEmpty() )
return null;
String key = (String) properties.keys().nextElement();
String value = properties.getProperty( key );
return new KeyValue( key, value );
} catch( BadLocationException | IOException ex ) {
// ignore
return null;
}
}
private Properties getProperties() {
if( propertiesCache != null )
return propertiesCache;
propertiesCache = new Properties();
try {
propertiesCache.load( new StringReader( textArea.getText() ) );
} catch( IOException ex ) {
ex.printStackTrace(); //TODO
}
return propertiesCache;
}
private void clearCache() {
propertiesCache = null;
parsedValueCache.clear();
}
//---- interface DocumentListener ----
@Override
public void insertUpdate( DocumentEvent e ) {
clearCache();
}
@Override
public void removeUpdate( DocumentEvent e ) {
clearCache();
}
@Override
public void changedUpdate( DocumentEvent e ) {
}
//---- class KeyValue -----------------------------------------------------
static class CacheLineInfo {
Object parsedValue;
Object valueType;
Exception parseError;
Color origColor;
}
//---- class KeyValue -----------------------------------------------------
static class KeyValue {
final String key;
final String value;
KeyValue( String key, String value ) {
this.key = key;
this.value = value;
}
}
}

View File

@@ -33,8 +33,8 @@ Prop.lazy=lazy(Prop.string)
Prop.colorFunc1=rgb(12,34,56)
Prop.colorFunc2=rgba(12,34,56,78)
Prop.colorFunc3=hsl(12,34,56)
Prop.colorFunc4=hsla(12,34,56,78)
Prop.colorFunc3=hsl(12,34%,56%)
Prop.colorFunc4=hsla(12,34%,56%,78%)
Prop.colorFunc5=lighten(#fe1289,20%)
Prop.colorFunc6=darken(#fe1289,20%)