diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonUI.java index 880d904e..60f9cdaf 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonUI.java @@ -36,6 +36,7 @@ import javax.swing.plaf.basic.BasicButtonListener; import javax.swing.plaf.basic.BasicRadioButtonUI; import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.icons.FlatCheckBoxIcon; +import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable; import com.formdev.flatlaf.util.UIScale; /** @@ -62,7 +63,7 @@ public class FlatRadioButtonUI extends BasicRadioButtonUI { protected int iconTextGap; - protected Color disabledText; + @Styleable protected Color disabledText; private Color defaultBackground; @@ -158,15 +159,9 @@ public class FlatRadioButtonUI * @since TODO */ protected Object applyStyleProperty( String key, Object value ) { - Object oldValue; - switch( key ) { - case "disabledText": oldValue = disabledText; disabledText = (Color) value; break; + //TODO style icon - //TODO style icon - - default: throw new IllegalArgumentException( "unknown style '" + key + "'" ); - } - return oldValue; + return FlatStyleSupport.applyToAnnotatedObject( this, key, value ); } private static Insets tempInsets = new Insets( 0, 0, 0, 0 ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSliderUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSliderUI.java index 8bf7ea23..82005439 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSliderUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSliderUI.java @@ -37,6 +37,7 @@ import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicSliderUI; import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable; import com.formdev.flatlaf.util.Graphics2DProxy; import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.UIScale; @@ -78,23 +79,23 @@ import com.formdev.flatlaf.util.UIScale; public class FlatSliderUI extends BasicSliderUI { - protected int trackWidth; - protected Dimension thumbSize; - protected int focusWidth; + @Styleable protected int trackWidth; + @Styleable protected Dimension thumbSize; + @Styleable protected int focusWidth; - protected Color trackValueColor; - protected Color trackColor; - protected Color thumbColor; - protected Color thumbBorderColor; + @Styleable protected Color trackValueColor; + @Styleable protected Color trackColor; + @Styleable protected Color thumbColor; + @Styleable protected Color thumbBorderColor; protected Color focusBaseColor; - protected Color focusedColor; - protected Color focusedThumbBorderColor; - protected Color hoverThumbColor; - protected Color pressedThumbColor; - protected Color disabledTrackColor; - protected Color disabledThumbColor; - protected Color disabledThumbBorderColor; - protected Color tickColor; + @Styleable protected Color focusedColor; + @Styleable protected Color focusedThumbBorderColor; + @Styleable protected Color hoverThumbColor; + @Styleable protected Color pressedThumbColor; + @Styleable protected Color disabledTrackColor; + @Styleable protected Color disabledThumbColor; + @Styleable protected Color disabledThumbBorderColor; + @Styleable protected Color tickColor; private Color defaultBackground; private Color defaultForeground; @@ -209,28 +210,7 @@ public class FlatSliderUI * @since TODO */ protected Object applyStyleProperty( String key, Object value ) { - Object oldValue; - 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; + return FlatStyleSupport.applyToAnnotatedObject( this, key, value ); } @Override diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStyleSupport.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStyleSupport.java index efb7853a..f86974ab 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStyleSupport.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStyleSupport.java @@ -16,6 +16,12 @@ 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.LinkedHashMap; import java.util.Map; @@ -34,6 +40,16 @@ import com.formdev.flatlaf.util.StringUtils; */ public class FlatStyleSupport { + /** + * Indicates that a field is intended to be used by FlatLaf styling support. + *
+ * Do not rename fields annotated with this annotation. + */ + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + public @interface Styleable { + } + /** * Parses styles in CSS syntax ("key1: value1; key2: value2; ..."), * converts the value strings into binary and invokes the given function @@ -146,6 +162,59 @@ public class FlatStyleSupport 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 ) { return c.getClientProperty( FlatClientProperties.COMPONENT_STYLE ); }