Styling: use annotation on fields to apply style properties (to avoid boilerplate code)

This commit is contained in:
Karl Tauber
2021-06-16 21:21:33 +02:00
parent db56486506
commit e0bc93371e
3 changed files with 90 additions and 46 deletions

View File

@@ -36,6 +36,7 @@ import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.plaf.basic.BasicRadioButtonUI; import javax.swing.plaf.basic.BasicRadioButtonUI;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.icons.FlatCheckBoxIcon; import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
/** /**
@@ -62,7 +63,7 @@ public class FlatRadioButtonUI
extends BasicRadioButtonUI extends BasicRadioButtonUI
{ {
protected int iconTextGap; protected int iconTextGap;
protected Color disabledText; @Styleable protected Color disabledText;
private Color defaultBackground; private Color defaultBackground;
@@ -158,15 +159,9 @@ public class FlatRadioButtonUI
* @since TODO * @since TODO
*/ */
protected Object applyStyleProperty( String key, Object value ) { protected Object applyStyleProperty( String key, Object value ) {
Object oldValue; //TODO style icon
switch( key ) {
case "disabledText": oldValue = disabledText; disabledText = (Color) value; break;
//TODO style icon return FlatStyleSupport.applyToAnnotatedObject( this, key, value );
default: throw new IllegalArgumentException( "unknown style '" + key + "'" );
}
return oldValue;
} }
private static Insets tempInsets = new Insets( 0, 0, 0, 0 ); private static Insets tempInsets = new Insets( 0, 0, 0, 0 );

View File

@@ -37,6 +37,7 @@ import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSliderUI; import javax.swing.plaf.basic.BasicSliderUI;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable;
import com.formdev.flatlaf.util.Graphics2DProxy; import com.formdev.flatlaf.util.Graphics2DProxy;
import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -78,23 +79,23 @@ import com.formdev.flatlaf.util.UIScale;
public class FlatSliderUI public class FlatSliderUI
extends BasicSliderUI extends BasicSliderUI
{ {
protected int trackWidth; @Styleable protected int trackWidth;
protected Dimension thumbSize; @Styleable protected Dimension thumbSize;
protected int focusWidth; @Styleable protected int focusWidth;
protected Color trackValueColor; @Styleable protected Color trackValueColor;
protected Color trackColor; @Styleable protected Color trackColor;
protected Color thumbColor; @Styleable protected Color thumbColor;
protected Color thumbBorderColor; @Styleable protected Color thumbBorderColor;
protected Color focusBaseColor; protected Color focusBaseColor;
protected Color focusedColor; @Styleable protected Color focusedColor;
protected Color focusedThumbBorderColor; @Styleable protected Color focusedThumbBorderColor;
protected Color hoverThumbColor; @Styleable protected Color hoverThumbColor;
protected Color pressedThumbColor; @Styleable protected Color pressedThumbColor;
protected Color disabledTrackColor; @Styleable protected Color disabledTrackColor;
protected Color disabledThumbColor; @Styleable protected Color disabledThumbColor;
protected Color disabledThumbBorderColor; @Styleable protected Color disabledThumbBorderColor;
protected Color tickColor; @Styleable protected Color tickColor;
private Color defaultBackground; private Color defaultBackground;
private Color defaultForeground; private Color defaultForeground;
@@ -209,28 +210,7 @@ public class FlatSliderUI
* @since TODO * @since TODO
*/ */
protected Object applyStyleProperty( String key, Object value ) { protected Object applyStyleProperty( String key, Object value ) {
Object oldValue; return FlatStyleSupport.applyToAnnotatedObject( this, key, value );
switch( key ) {
case "trackWidth": oldValue = trackWidth; trackWidth = (int) value; break;
case "thumbSize": oldValue = thumbSize; thumbSize = (Dimension) value; break;
case "focusWidth": oldValue = focusWidth; focusWidth = (int) value; break;
case "trackValueColor": oldValue = trackValueColor; trackValueColor = (Color) value; break;
case "trackColor": oldValue = trackColor; trackColor = (Color) value; break;
case "thumbColor": oldValue = thumbColor; thumbColor = (Color) value; break;
case "thumbBorderColor": oldValue = thumbBorderColor; thumbBorderColor = (Color) value; break;
case "focusedColor": oldValue = focusedColor; focusedColor = (Color) value; break;
case "focusedThumbBorderColor": oldValue = focusedThumbBorderColor; focusedThumbBorderColor = (Color) value; break;
case "hoverThumbColor": oldValue = hoverThumbColor; hoverThumbColor = (Color) value; break;
case "pressedThumbColor": oldValue = pressedThumbColor; pressedThumbColor = (Color) value; break;
case "disabledTrackColor": oldValue = disabledTrackColor; disabledTrackColor = (Color) value; break;
case "disabledThumbColor": oldValue = disabledThumbColor; disabledThumbColor = (Color) value; break;
case "disabledThumbBorderColor": oldValue = disabledThumbBorderColor; disabledThumbBorderColor = (Color) value; break;
case "tickColor": oldValue = tickColor; tickColor = (Color) value; break;
default: throw new IllegalArgumentException( "unknown style '" + key + "'" );
}
return oldValue;
} }
@Override @Override

View File

@@ -16,6 +16,12 @@
package com.formdev.flatlaf.ui; package com.formdev.flatlaf.ui;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@@ -34,6 +40,16 @@ import com.formdev.flatlaf.util.StringUtils;
*/ */
public class FlatStyleSupport public class FlatStyleSupport
{ {
/**
* Indicates that a field is intended to be used by FlatLaf styling support.
* <p>
* <strong>Do not rename fields annotated with this annotation.</strong>
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Styleable {
}
/** /**
* Parses styles in CSS syntax ("key1: value1; key2: value2; ..."), * Parses styles in CSS syntax ("key1: value1; key2: value2; ..."),
* converts the value strings into binary and invokes the given function * converts the value strings into binary and invokes the given function
@@ -146,6 +162,59 @@ public class FlatStyleSupport
return FlatLaf.parseDefaultsValue( key, value ); return FlatLaf.parseDefaultsValue( key, value );
} }
/**
* Applies the given value to an annotated field of the given object.
* The field must be annotated with {@link Styleable}.
*
* @param object the object
* @param key the name of the field
* @param value the new value
* @return the old value of the field
* @throws IllegalArgumentException if object does not have a annotated field with given name
* or if value type does not fit to expected type 
*/
public static Object applyToAnnotatedObject( Object obj, String key, Object value )
throws IllegalArgumentException
{
Class<?> cls = obj.getClass();
for(;;) {
try {
Field f = cls.getDeclaredField( key );
if( f.isAnnotationPresent( Styleable.class ) ) {
if( Modifier.isFinal( f.getModifiers() ) )
throw new IllegalArgumentException( "field '" + cls.getName() + "." + key + "' is final" );
try {
// necessary to access protected fields in other packages
f.setAccessible( true );
// get old value and set new value
Object oldValue = f.get( obj );
f.set( obj, value );
return oldValue;
} catch( IllegalAccessException ex ) {
throw new IllegalArgumentException( "failed to access field '" + cls.getName() + "." + key + "'" );
}
}
} catch( NoSuchFieldException ex ) {
// field not found in class --> try superclass
}
cls = cls.getSuperclass();
if( cls == null )
throw newUnknownStyleException( key );
String superclassName = cls.getName();
if( superclassName.startsWith( "java." ) || superclassName.startsWith( "javax." ) )
throw newUnknownStyleException( key );
}
}
public static IllegalArgumentException newUnknownStyleException( String key ) {
return new IllegalArgumentException( "unknown style '" + key + "'" );
}
public static Object getStyle( JComponent c ) { public static Object getStyle( JComponent c ) {
return c.getClientProperty( FlatClientProperties.COMPONENT_STYLE ); return c.getClientProperty( FlatClientProperties.COMPONENT_STYLE );
} }