From 52ad15e375077bedd191496aee2ae49c98702405 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sun, 31 Jul 2022 10:57:28 +0200 Subject: [PATCH] Styling: added `StyleableUI.getStyleableValue()` for tooling (e.g. GUI builder) --- .../flatlaf/icons/FlatCapsLockIcon.java | 8 + .../flatlaf/icons/FlatCheckBoxIcon.java | 5 + .../icons/FlatCheckBoxMenuItemIcon.java | 5 + .../formdev/flatlaf/icons/FlatClearIcon.java | 5 + .../flatlaf/icons/FlatHelpButtonIcon.java | 5 + .../flatlaf/icons/FlatMenuArrowIcon.java | 5 + .../formdev/flatlaf/icons/FlatSearchIcon.java | 5 + .../icons/FlatTabbedPaneCloseIcon.java | 5 + .../com/formdev/flatlaf/ui/FlatBorder.java | 6 + .../com/formdev/flatlaf/ui/FlatButtonUI.java | 12 + .../flatlaf/ui/FlatCheckBoxMenuItemUI.java | 15 +- .../formdev/flatlaf/ui/FlatComboBoxUI.java | 6 + .../flatlaf/ui/FlatDropShadowBorder.java | 6 + .../formdev/flatlaf/ui/FlatEditorPaneUI.java | 6 + .../formdev/flatlaf/ui/FlatEmptyBorder.java | 5 + .../flatlaf/ui/FlatInternalFrameUI.java | 23 + .../com/formdev/flatlaf/ui/FlatLabelUI.java | 6 + .../com/formdev/flatlaf/ui/FlatListUI.java | 6 + .../formdev/flatlaf/ui/FlatMenuBarBorder.java | 6 + .../com/formdev/flatlaf/ui/FlatMenuBarUI.java | 6 + .../flatlaf/ui/FlatMenuItemRenderer.java | 13 + .../formdev/flatlaf/ui/FlatMenuItemUI.java | 22 +- .../com/formdev/flatlaf/ui/FlatMenuUI.java | 15 +- .../com/formdev/flatlaf/ui/FlatPanelUI.java | 6 + .../flatlaf/ui/FlatPasswordFieldUI.java | 8 + .../flatlaf/ui/FlatPopupMenuBorder.java | 10 + .../formdev/flatlaf/ui/FlatPopupMenuUI.java | 6 + .../formdev/flatlaf/ui/FlatProgressBarUI.java | 6 + .../flatlaf/ui/FlatRadioButtonMenuItemUI.java | 15 +- .../formdev/flatlaf/ui/FlatRadioButtonUI.java | 13 + .../formdev/flatlaf/ui/FlatScrollBarUI.java | 6 + .../formdev/flatlaf/ui/FlatScrollPaneUI.java | 6 + .../formdev/flatlaf/ui/FlatSeparatorUI.java | 6 + .../com/formdev/flatlaf/ui/FlatSliderUI.java | 6 + .../com/formdev/flatlaf/ui/FlatSpinnerUI.java | 6 + .../formdev/flatlaf/ui/FlatSplitPaneUI.java | 24 +- .../flatlaf/ui/FlatStylingSupport.java | 97 +- .../formdev/flatlaf/ui/FlatTabbedPaneUI.java | 80 ++ .../formdev/flatlaf/ui/FlatTableHeaderUI.java | 16 + .../com/formdev/flatlaf/ui/FlatTableUI.java | 6 + .../formdev/flatlaf/ui/FlatTextAreaUI.java | 6 + .../formdev/flatlaf/ui/FlatTextFieldUI.java | 6 + .../formdev/flatlaf/ui/FlatTextPaneUI.java | 6 + .../flatlaf/ui/FlatToolBarSeparatorUI.java | 6 + .../com/formdev/flatlaf/ui/FlatToolBarUI.java | 6 + .../com/formdev/flatlaf/ui/FlatTreeUI.java | 6 + .../flatlaf/ui/TestFlatStyleableValue.java | 1219 +++++++++++++++++ 47 files changed, 1725 insertions(+), 43 deletions(-) create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java index a25c58b4..933f05de 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java @@ -49,6 +49,14 @@ public class FlatCapsLockIcon } } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + switch( key ) { + case "capsLockIconColor": return color; + default: return null; + } + } + @Override protected void paintIcon( Component c, Graphics2D g ) { /* diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java index f371679c..730a7887 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java @@ -172,6 +172,11 @@ public class FlatCheckBoxIcon return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override protected void paintIcon( Component c, Graphics2D g ) { boolean indeterminate = isIndeterminate( c ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxMenuItemIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxMenuItemIcon.java index 8900db7a..7079572f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxMenuItemIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxMenuItemIcon.java @@ -59,6 +59,11 @@ public class FlatCheckBoxMenuItemIcon return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override protected void paintIcon( Component c, Graphics2D g2 ) { boolean selected = (c instanceof AbstractButton) && ((AbstractButton)c).isSelected(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java index 30f691c4..29044e64 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java @@ -69,6 +69,11 @@ public class FlatClearIcon return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override protected void paintIcon( Component c, Graphics2D g ) { if( !ignoreButtonState && c instanceof AbstractButton ) { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatHelpButtonIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatHelpButtonIcon.java index ed676e60..d415356f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatHelpButtonIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatHelpButtonIcon.java @@ -84,6 +84,11 @@ public class FlatHelpButtonIcon return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override protected void paintIcon( Component c, Graphics2D g2 ) { /* diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java index bf75e736..a0553a8f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatMenuArrowIcon.java @@ -61,6 +61,11 @@ public class FlatMenuArrowIcon return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override protected void paintIcon( Component c, Graphics2D g ) { if( c != null && !c.getComponentOrientation().isLeftToRight() ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java index e9f72ffa..007e9718 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java @@ -67,6 +67,11 @@ public class FlatSearchIcon return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override protected void paintIcon( Component c, Graphics2D g ) { /* diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTabbedPaneCloseIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTabbedPaneCloseIcon.java index 4b228e13..6f6220d6 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTabbedPaneCloseIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTabbedPaneCloseIcon.java @@ -76,6 +76,11 @@ public class FlatTabbedPaneCloseIcon return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override protected void paintIcon( Component c, Graphics2D g ) { // paint background diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java index 636ada15..11d2cbfb 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatBorder.java @@ -101,6 +101,12 @@ public class FlatBorder return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { Graphics2D g2 = (Graphics2D) g.create(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java index a8abf33b..e7a02584 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java @@ -366,6 +366,18 @@ public class FlatButtonUI return infos; } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + if( key.startsWith( "help." ) ) { + return (helpButtonIcon instanceof FlatHelpButtonIcon) + ? ((FlatHelpButtonIcon)helpButtonIcon).getStyleableValue( key.substring( "help.".length() ) ) + : null; + } + + return FlatStylingSupport.getAnnotatedStyleableValue( this, c.getBorder(), key ); + } + static boolean isContentAreaFilled( Component c ) { return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled(); } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxMenuItemUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxMenuItemUI.java index 21549b5a..db75c0a1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxMenuItemUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxMenuItemUI.java @@ -28,7 +28,6 @@ import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI; import javax.swing.plaf.basic.BasicMenuItemUI; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; -import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException; import com.formdev.flatlaf.util.LoggingFacade; /** @@ -126,13 +125,7 @@ public class FlatCheckBoxMenuItemUI /** @since 2 */ protected Object applyStyleProperty( String key, Object value ) { - try { - return renderer.applyStyleProperty( key, value ); - } catch ( UnknownStyleException ex ) { - // ignore - } - - return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, menuItem, key, value ); + return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value ); } /** @since 2 */ @@ -141,6 +134,12 @@ public class FlatCheckBoxMenuItemUI return FlatMenuItemUI.getStyleableInfos( this, renderer ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatMenuItemUI.getStyleableValue( this, renderer, key ); + } + @Override protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) { return renderer.getPreferredMenuItemSize(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java index b73cbdd4..e2303bcf 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java @@ -505,6 +505,12 @@ public class FlatComboBoxUI return FlatStylingSupport.getAnnotatedStyleableInfos( this, comboBox.getBorder() ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, comboBox.getBorder(), key ); + } + @Override public void update( Graphics g, JComponent c ) { float focusWidth = FlatUIUtils.getBorderFocusWidth( c ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java index 6970d7ea..6914daf9 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java @@ -107,6 +107,12 @@ public class FlatDropShadowBorder return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { if( shadowSize <= 0 ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEditorPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEditorPaneUI.java index 66defaa2..5d85c065 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEditorPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEditorPaneUI.java @@ -209,6 +209,12 @@ public class FlatEditorPaneUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + private void updateBackground() { FlatTextFieldUI.updateBackground( getComponent(), background, disabledBackground, inactiveBackground, diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java index 09725f83..1dd1950b 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java @@ -76,4 +76,9 @@ public class FlatEmptyBorder right = insets.right; return oldInsets; } + + /** @since 2.5 */ + public Insets getStyleableValue() { + return new Insets( top, left, bottom, right ); + } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java index 2db28a82..bc5c41e9 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java @@ -179,6 +179,12 @@ public class FlatInternalFrameUI return FlatStylingSupport.getAnnotatedStyleableInfos( this, frame.getBorder() ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, frame.getBorder(), key ); + } + @Override public void update( Graphics g, JComponent c ) { // The internal frame actually should be opaque and fill its background, @@ -253,6 +259,23 @@ public class FlatInternalFrameUI return infos; } + /** @since 2.5 */ + @Override + public Object getStyleableValue( String key ) { + switch( key ) { + case "borderMargins": return getStyleableValue(); + + case "activeDropShadowColor": return activeDropShadowBorder.getStyleableValue( "shadowColor" ); + case "activeDropShadowInsets": return activeDropShadowBorder.getStyleableValue( "shadowInsets" ); + case "activeDropShadowOpacity": return activeDropShadowBorder.getStyleableValue( "shadowOpacity" ); + case "inactiveDropShadowColor": return inactiveDropShadowBorder.getStyleableValue( "shadowColor" ); + case "inactiveDropShadowInsets": return inactiveDropShadowBorder.getStyleableValue( "shadowInsets" ); + case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.getStyleableValue( "shadowOpacity" ); + } + + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public Insets getBorderInsets( Component c, Insets insets ) { if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java index 157fd759..cbf01434 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java @@ -158,6 +158,12 @@ public class FlatLabelUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + /** * Checks whether text contains HTML tags that use "absolute-size" keywords * (e.g. "x-large") for font-size in default style sheet diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java index 638e8cce..9440d2dd 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java @@ -209,6 +209,12 @@ public class FlatListUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + /** * Toggle selection colors from focused to inactive and vice versa. * diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java index 6ba8d159..e454c25f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarBorder.java @@ -51,6 +51,12 @@ public class FlatMenuBarBorder return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { if( !showBottomSeparator( c ) ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java index e167c368..f3ef6855 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java @@ -174,6 +174,12 @@ public class FlatMenuBarUI return FlatStylingSupport.getAnnotatedStyleableInfos( this, menuBar.getBorder() ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, menuBar.getBorder(), key ); + } + @Override public void update( Graphics g, JComponent c ) { // paint background diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java index 153bc16c..82ccf79f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemRenderer.java @@ -169,6 +169,19 @@ public class FlatMenuItemRenderer return infos; } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + if( key.startsWith( "icon." ) ) { + String key2 = key.substring( "icon.".length() ); + if( checkIcon instanceof FlatCheckBoxMenuItemIcon ) + return ((FlatCheckBoxMenuItemIcon)checkIcon).getStyleableValue( key2 ); + if( arrowIcon instanceof FlatMenuArrowIcon ) + return ((FlatMenuArrowIcon)arrowIcon).getStyleableValue( key2 ); + } + + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + protected Dimension getPreferredMenuItemSize() { int width = 0; int height = 0; diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemUI.java index aaaec9d8..07d2d50c 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemUI.java @@ -22,6 +22,7 @@ import java.beans.PropertyChangeListener; import java.util.Map; import javax.swing.Icon; import javax.swing.JComponent; +import javax.swing.JMenuItem; import javax.swing.LookAndFeel; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicMenuItemUI; @@ -125,13 +126,19 @@ public class FlatMenuItemUI /** @since 2 */ protected Object applyStyleProperty( String key, Object value ) { + return applyStyleProperty( menuItem, this, renderer, key, value ); + } + + static Object applyStyleProperty( JMenuItem menuItem, BasicMenuItemUI ui, + FlatMenuItemRenderer renderer, String key, Object value ) + { try { return renderer.applyStyleProperty( key, value ); } catch ( UnknownStyleException ex ) { // ignore } - return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, menuItem, key, value ); + return FlatStylingSupport.applyToAnnotatedObjectOrComponent( ui, menuItem, key, value ); } /** @since 2 */ @@ -146,6 +153,19 @@ public class FlatMenuItemUI return infos; } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return getStyleableValue( this, renderer, key ); + } + + static Object getStyleableValue( BasicMenuItemUI ui, FlatMenuItemRenderer renderer, String key ) { + Object value = renderer.getStyleableValue( key ); + if( value == null ) + value = FlatStylingSupport.getAnnotatedStyleableValue( ui, key ); + return value; + } + @Override protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) { return renderer.getPreferredMenuItemSize(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java index 477a1792..97de06d1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java @@ -39,7 +39,6 @@ import javax.swing.plaf.basic.BasicMenuItemUI; import javax.swing.plaf.basic.BasicMenuUI; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; -import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException; import com.formdev.flatlaf.util.LoggingFacade; /** @@ -174,13 +173,7 @@ public class FlatMenuUI /** @since 2 */ protected Object applyStyleProperty( String key, Object value ) { - try { - return renderer.applyStyleProperty( key, value ); - } catch ( UnknownStyleException ex ) { - // ignore - } - - return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, menuItem, key, value ); + return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value ); } /** @since 2 */ @@ -189,6 +182,12 @@ public class FlatMenuUI return FlatMenuItemUI.getStyleableInfos( this, renderer ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatMenuItemUI.getStyleableValue( this, renderer, key ); + } + @Override public Dimension getMinimumSize( JComponent c ) { // avoid that top-level menus (in menu bar) are made smaller if horizontal space is rare diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPanelUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPanelUI.java index 5718611d..c9db1fa2 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPanelUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPanelUI.java @@ -127,6 +127,12 @@ public class FlatPanelUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public void update( Graphics g, JComponent c ) { // fill background diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java index 4e7c7679..91536014 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java @@ -233,6 +233,14 @@ public class FlatPasswordFieldUI return infos; } + @Override + public Object getStyleableValue( JComponent c, String key ) { + if( key.equals( "capsLockIconColor" ) && capsLockIcon instanceof FlatCapsLockIcon ) + return ((FlatCapsLockIcon)capsLockIcon).getStyleableValue( key ); + + return super.getStyleableValue( c, key ); + } + @Override public View create( Element elem ) { return new PasswordView( elem ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java index a8cbc11e..fb00b60f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java @@ -66,6 +66,16 @@ public class FlatPopupMenuBorder return infos; } + /** @since 2.5 */ + @Override + public Object getStyleableValue( String key ) { + switch( key ) { + case "borderInsets": return getStyleableValue(); + case "borderColor": return borderColor; + } + return null; + } + @Override public Color getLineColor() { return (borderColor != null) ? borderColor : super.getLineColor(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java index 2ea093a5..7e24ea32 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java @@ -184,6 +184,12 @@ public class FlatPopupMenuUI return FlatStylingSupport.getAnnotatedStyleableInfos( this, popupMenu.getBorder() ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, popupMenu.getBorder(), key ); + } + @Override public Popup getPopup( JPopupMenu popup, int x, int y ) { // do not add scroller to combobox popups or to popups that already have a scroll pane diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java index 0d43b7fd..58d02190 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatProgressBarUI.java @@ -160,6 +160,12 @@ public class FlatProgressBarUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public Dimension getPreferredSize( JComponent c ) { Dimension size = super.getPreferredSize( c ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonMenuItemUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonMenuItemUI.java index d77832e4..714087ba 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonMenuItemUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonMenuItemUI.java @@ -28,7 +28,6 @@ import javax.swing.plaf.basic.BasicMenuItemUI; import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; -import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException; import com.formdev.flatlaf.util.LoggingFacade; /** @@ -126,13 +125,7 @@ public class FlatRadioButtonMenuItemUI /** @since 2 */ protected Object applyStyleProperty( String key, Object value ) { - try { - return renderer.applyStyleProperty( key, value ); - } catch ( UnknownStyleException ex ) { - // ignore - } - - return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, menuItem, key, value ); + return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value ); } /** @since 2 */ @@ -141,6 +134,12 @@ public class FlatRadioButtonMenuItemUI return FlatMenuItemUI.getStyleableInfos( this, renderer ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatMenuItemUI.getStyleableValue( this, renderer, key ); + } + @Override protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) { return renderer.getPreferredMenuItemSize(); 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 75aafe7b..26fea08e 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 @@ -199,6 +199,19 @@ public class FlatRadioButtonUI return infos; } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + // style icon + if( key.startsWith( "icon." ) ) { + return (icon instanceof FlatCheckBoxIcon) + ? ((FlatCheckBoxIcon)icon).getStyleableValue( key.substring( "icon.".length() ) ) + : null; + } + + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + private static final Insets tempInsets = new Insets( 0, 0, 0, 0 ); @Override diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollBarUI.java index 8d9c8838..fa5d6253 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollBarUI.java @@ -262,6 +262,12 @@ public class FlatScrollBarUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public Dimension getPreferredSize( JComponent c ) { return UIScale.scale( super.getPreferredSize( c ) ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java index 60144c98..f79e1265 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java @@ -343,6 +343,12 @@ public class FlatScrollPaneUI return FlatStylingSupport.getAnnotatedStyleableInfos( this, scrollpane.getBorder() ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, scrollpane.getBorder(), key ); + } + @Override protected void updateViewport( PropertyChangeEvent e ) { super.updateViewport( e ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSeparatorUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSeparatorUI.java index ac02e4b9..b93ce6b9 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSeparatorUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSeparatorUI.java @@ -170,6 +170,12 @@ public class FlatSeparatorUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public void paint( Graphics g, JComponent c ) { Graphics2D g2 = (Graphics2D) g.create(); 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 96f6b8b3..e7bb62b7 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 @@ -222,6 +222,12 @@ public class FlatSliderUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public int getBaseline( JComponent c, int width, int height ) { if( c == null ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java index 0e4605e9..d2b44fa9 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java @@ -223,6 +223,12 @@ public class FlatSpinnerUI return FlatStylingSupport.getAnnotatedStyleableInfos( this, spinner.getBorder() ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, spinner.getBorder(), key ); + } + @Override protected JComponent createEditor() { JComponent editor = super.createEditor(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java index 0f3d5992..43c8ddea 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java @@ -183,6 +183,17 @@ public class FlatSplitPaneUI return infos; } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + if( divider instanceof FlatSplitPaneDivider ) { + Object value = ((FlatSplitPaneDivider)divider).getStyleableValue( key ); + if( value != null ) + return value; + } + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + //---- class FlatSplitPaneDivider ----------------------------------------- protected class FlatSplitPaneDivider @@ -200,20 +211,21 @@ public class FlatSplitPaneUI setLayout( new FlatDividerLayout() ); } - /** - * @since 2 - */ + /** @since 2 */ protected Object applyStyleProperty( String key, Object value ) { return FlatStylingSupport.applyToAnnotatedObject( this, key, value ); } - /** - * @since 2 - */ + /** @since 2 */ public Map> getStyleableInfos() { return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + public Object getStyleableValue( String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + void updateStyle() { if( leftButton instanceof FlatOneTouchButton ) ((FlatOneTouchButton)leftButton).updateStyle(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStylingSupport.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStylingSupport.java index 148e5998..82351f02 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStylingSupport.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStylingSupport.java @@ -97,12 +97,14 @@ public class FlatStylingSupport /** @since 2 */ public interface StyleableUI { Map> getStyleableInfos( JComponent c ); + /** @since 2.5 */ Object getStyleableValue( JComponent c, String key ); } /** @since 2 */ public interface StyleableBorder { Object applyStyleProperty( String key, Object value ); Map> getStyleableInfos(); + /** @since 2.5 */ Object getStyleableValue( String key ); } @@ -396,21 +398,25 @@ public class FlatStylingSupport public static Object applyToAnnotatedObject( Object obj, String key, Object value ) throws UnknownStyleException, IllegalArgumentException { - String fieldName = key; - int dotIndex = key.indexOf( '.' ); - if( dotIndex >= 0 ) { - // remove first dot in key and change subsequent character to uppercase - fieldName = key.substring( 0, dotIndex ) - + Character.toUpperCase( key.charAt( dotIndex + 1 ) ) - + key.substring( dotIndex + 2 ); - } + String fieldName = keyToFieldName( key ); return applyToField( obj, fieldName, key, value, field -> { Styleable styleable = field.getAnnotation( Styleable.class ); - return styleable != null && styleable.dot() == (dotIndex >= 0); + return styleable != null && styleable.dot() == (fieldName != key); } ); } + private static String keyToFieldName( String key ) { + int dotIndex = key.indexOf( '.' ); + if( dotIndex < 0 ) + return key; + + // remove first dot in key and change subsequent character to uppercase + return key.substring( 0, dotIndex ) + + Character.toUpperCase( key.charAt( dotIndex + 1 ) ) + + key.substring( dotIndex + 2 ); + } + /** * Applies the given value to a field of the given object. * @@ -460,8 +466,7 @@ public class FlatStylingSupport } private static Object applyToField( Field f, Object obj, Object value ) { - if( !isValidField( f ) ) - throw new IllegalArgumentException( "field '" + f.getDeclaringClass().getName() + "." + f.getName() + "' is final or static" ); + checkValidField( f ); try { // necessary to access protected fields in other packages @@ -472,10 +477,30 @@ public class FlatStylingSupport f.set( obj, convertToEnum( value, f.getType() ) ); return oldValue; } catch( IllegalAccessException ex ) { - throw new IllegalArgumentException( "failed to access field '" + f.getDeclaringClass().getName() + "." + f.getName() + "'", ex ); + throw newFieldAccessFailed( f, ex ); } } + private static Object getFieldValue( Field f, Object obj ) { + checkValidField( f ); + + try { + f.setAccessible( true ); + return f.get( obj ); + } catch( IllegalAccessException ex ) { + throw newFieldAccessFailed( f, ex ); + } + } + + private static IllegalArgumentException newFieldAccessFailed( Field f, IllegalAccessException ex ) { + return new IllegalArgumentException( "failed to access field '" + f.getDeclaringClass().getName() + "." + f.getName() + "'", ex ); + } + + private static void checkValidField( Field f ) { + if( !isValidField( f ) ) + throw new IllegalArgumentException( "field '" + f.getDeclaringClass().getName() + "." + f.getName() + "' is final or static" ); + } + private static boolean isValidField( Field f ) { int modifiers = f.getModifiers(); return (modifiers & (Modifier.FINAL|Modifier.STATIC)) == 0 && !f.isSynthetic(); @@ -752,6 +777,54 @@ public class FlatStylingSupport infos.put( keyPrefix.concat( e.getKey() ), e.getValue() ); } + public static Object getAnnotatedStyleableValue( Object obj, String key ) { + String fieldName = keyToFieldName( key ); + Class cls = obj.getClass(); + + for(;;) { + try { + // find field annotated with 'Styleable' + Field f = cls.getDeclaredField( fieldName ); + Styleable styleable = f.getAnnotation( Styleable.class ); + if( styleable != null ) { + if( styleable.dot() != (fieldName != key) ) + throw new IllegalArgumentException( "'Styleable.dot' on field '" + fieldName + "' does not match key '" + key + "'" ); + if( styleable.type() != Void.class ) + throw new IllegalArgumentException( "'Styleable.type' on field '" + fieldName + "' not supported" ); + + return getFieldValue( f, obj ); + } + } catch( NoSuchFieldException ex ) { + // field not found in class --> try superclass + } + + // find field specified in 'StyleableField' annotation + for( StyleableField styleableField : cls.getAnnotationsByType( StyleableField.class ) ) { + if( key.equals( styleableField.key() ) ) { + Field f = getStyleableField( styleableField ); + return getFieldValue( f, obj ); + } + } + + cls = cls.getSuperclass(); + if( cls == null ) + return null; + + String superclassName = cls.getName(); + if( superclassName.startsWith( "java." ) || superclassName.startsWith( "javax." ) ) + return null; + } + } + + public static Object getAnnotatedStyleableValue( Object obj, Border border, String key ) { + if( border instanceof StyleableBorder ) { + Object value = ((StyleableBorder)border).getStyleableValue( key ); + if( value != null ) + return value; + } + return getAnnotatedStyleableValue( obj, key ); + } + //---- class UnknownStyleException ---------------------------------------- public static class UnknownStyleException diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java index bbe45782..db7506e8 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java @@ -687,6 +687,76 @@ public class FlatTabbedPaneUI return infos; } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + // close icon + if( key.startsWith( "close" ) ) { + return (closeIcon instanceof FlatTabbedPaneCloseIcon) + ? ((FlatTabbedPaneCloseIcon)closeIcon).getStyleableValue( key ) + : null; + } + + switch( key ) { + // BasicTabbedPaneUI + case "tabInsets": return tabInsets; + case "tabAreaInsets": return tabAreaInsets; + case "textIconGap": return textIconGapUnscaled; + + // FlatTabbedPaneUI + case "tabType": + switch( tabType ) { + default: + case TAB_TYPE_UNDERLINED: return TABBED_PANE_TAB_TYPE_UNDERLINED; + case TAB_TYPE_CARD: return TABBED_PANE_TAB_TYPE_CARD; + } + + case "tabsPopupPolicy": + switch( tabsPopupPolicy ) { + default: + case AS_NEEDED: return TABBED_PANE_POLICY_AS_NEEDED; + case NEVER: return TABBED_PANE_POLICY_NEVER; + } + + case "scrollButtonsPolicy": + switch( scrollButtonsPolicy ) { + default: + case AS_NEEDED_SINGLE: return TABBED_PANE_POLICY_AS_NEEDED_SINGLE; + case AS_NEEDED: return TABBED_PANE_POLICY_AS_NEEDED; + case NEVER: return TABBED_PANE_POLICY_NEVER; + } + + case "scrollButtonsPlacement": + switch( scrollButtonsPlacement ) { + default: + case BOTH: return TABBED_PANE_PLACEMENT_BOTH; + case TRAILING: return TABBED_PANE_PLACEMENT_TRAILING; + } + + case "tabAreaAlignment": return alignmentToString( tabAreaAlignment, TABBED_PANE_ALIGN_LEADING ); + case "tabAlignment": return alignmentToString( tabAlignment, TABBED_PANE_ALIGN_CENTER ); + + case "tabWidthMode": + switch( tabWidthMode ) { + default: + case WIDTH_MODE_PREFERRED: return TABBED_PANE_TAB_WIDTH_MODE_PREFERRED; + case WIDTH_MODE_EQUAL: return TABBED_PANE_TAB_WIDTH_MODE_EQUAL; + case WIDTH_MODE_COMPACT: return TABBED_PANE_TAB_WIDTH_MODE_COMPACT; + } + + case "tabIconPlacement": + switch( tabIconPlacement ) { + default: + case LEADING: return "leading"; + case TRAILING: return "trailing"; + case TOP: return "top"; + case BOTTOM: return "bottom"; + } + } + + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + protected void setRolloverTab( int x, int y ) { setRolloverTab( tabForCoordinate( tabPane, x, y ) ); } @@ -1685,6 +1755,16 @@ public class FlatTabbedPaneUI } } + private static String alignmentToString( int value, String defaultValue ) { + switch( value ) { + case LEADING: return TABBED_PANE_ALIGN_LEADING; + case TRAILING: return TABBED_PANE_ALIGN_TRAILING; + case CENTER: return TABBED_PANE_ALIGN_CENTER; + case FILL: return TABBED_PANE_ALIGN_FILL; + default: return defaultValue; + } + } + protected static int parseTabWidthMode( String str ) { if( str == null ) return WIDTH_MODE_PREFERRED; diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableHeaderUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableHeaderUI.java index b7cc6770..d749f698 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableHeaderUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableHeaderUI.java @@ -171,6 +171,22 @@ public class FlatTableHeaderUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + if( key.equals( "sortIconPosition" ) ) { + switch( sortIconPosition ) { + default: + case SwingConstants.RIGHT: return "right"; + case SwingConstants.LEFT: return "left"; + case SwingConstants.TOP: return "top"; + case SwingConstants.BOTTOM: return "bottom"; + } + } + + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + private static int parseSortIconPosition( String str ) { if( str == null ) str = ""; diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java index 6f70b220..80465d09 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java @@ -286,6 +286,12 @@ public class FlatTableUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + /** * Toggle selection colors from focused to inactive and vice versa. * diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextAreaUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextAreaUI.java index 4b8241c7..c8724f1e 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextAreaUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextAreaUI.java @@ -183,6 +183,12 @@ public class FlatTextAreaUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + private void updateBackground() { FlatTextFieldUI.updateBackground( getComponent(), background, disabledBackground, inactiveBackground, diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java index feba4915..3426b10a 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java @@ -354,6 +354,12 @@ public class FlatTextFieldUI return FlatStylingSupport.getAnnotatedStyleableInfos( this, getComponent().getBorder() ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, getComponent().getBorder(), key ); + } + private void updateBackground() { updateBackground( getComponent(), background, disabledBackground, inactiveBackground, diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextPaneUI.java index bd55c311..85628479 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextPaneUI.java @@ -191,6 +191,12 @@ public class FlatTextPaneUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + private void updateBackground() { FlatTextFieldUI.updateBackground( getComponent(), background, disabledBackground, inactiveBackground, diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarSeparatorUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarSeparatorUI.java index 5f3bfa27..ae277db7 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarSeparatorUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarSeparatorUI.java @@ -160,6 +160,12 @@ public class FlatToolBarSeparatorUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + @Override public Dimension getPreferredSize( JComponent c ) { Dimension size = ((JToolBar.Separator)c).getSeparatorSize(); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java index fa241700..1d53dacc 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java @@ -201,6 +201,12 @@ public class FlatToolBarUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + /** @since 1.4 */ protected void setButtonsFocusable( boolean focusable ) { for( Component c : toolBar.getComponents() ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java index ee610c2d..73bf0ab3 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java @@ -340,6 +340,12 @@ public class FlatTreeUI return FlatStylingSupport.getAnnotatedStyleableInfos( this ); } + /** @since 2.5 */ + @Override + public Object getStyleableValue( JComponent c, String key ) { + return FlatStylingSupport.getAnnotatedStyleableValue( this, key ); + } + /** * Same as super.paintRow(), but supports wide selection and uses * inactive selection background/foreground if tree is not focused. diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java new file mode 100644 index 00000000..97efbb4b --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java @@ -0,0 +1,1219 @@ +/* + * 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.ui; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Insets; +import java.lang.reflect.Method; +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JEditorPane; +import javax.swing.JFormattedTextField; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JPopupMenu; +import javax.swing.JProgressBar; +import javax.swing.JRadioButton; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JTextPane; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.JTree; +import javax.swing.table.JTableHeader; +import javax.swing.text.JTextComponent; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import com.formdev.flatlaf.icons.FlatCheckBoxIcon; +import com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon; +import com.formdev.flatlaf.icons.FlatClearIcon; +import com.formdev.flatlaf.icons.FlatHelpButtonIcon; +import com.formdev.flatlaf.icons.FlatMenuArrowIcon; +import com.formdev.flatlaf.icons.FlatRadioButtonIcon; +import com.formdev.flatlaf.icons.FlatRadioButtonMenuItemIcon; +import com.formdev.flatlaf.icons.FlatSearchIcon; +import com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon; +import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; + +/** + * @author Karl Tauber + */ +public class TestFlatStyleableValue +{ + @BeforeAll + static void setup() { + TestUtils.setup( false ); + } + + @AfterAll + static void cleanup() { + TestUtils.cleanup(); + } + + private void testString( JComponent c, StyleableUI ui, String key, String value ) { + applyStyle( c, ui, String.format( "%s: %s", key, value ) ); + assertEquals( value, ui.getStyleableValue( c, key ) ); + } + + private void testBoolean( JComponent c, StyleableUI ui, String key, boolean value ) { + applyStyle( c, ui, String.format( "%s: %s", key, value ) ); + assertEquals( value, ui.getStyleableValue( c, key ) ); + } + + private void testInteger( JComponent c, StyleableUI ui, String key, int value ) { + applyStyle( c, ui, String.format( "%s: %d", key, value ) ); + assertEquals( value, ui.getStyleableValue( c, key ) ); + } + + private void testFloat( JComponent c, StyleableUI ui, String key, float value ) { + applyStyle( c, ui, String.format( "%s: %f", key, value ) ); + assertEquals( value, ui.getStyleableValue( c, key ) ); + } + + private void testColor( JComponent c, StyleableUI ui, String key, int rgb ) { + applyStyle( c, ui, String.format( "%s: #%06x", key, rgb ) ); + assertEquals( new Color( rgb ), ui.getStyleableValue( c, key ) ); + } + + private void testInsets( JComponent c, StyleableUI ui, String key, int top, int left, int bottom, int right ) { + applyStyle( c,ui, String.format( "%s: %d,%d,%d,%d", key, top, left, bottom, right ) ); + assertEquals( new Insets( top, left, bottom, right ), ui.getStyleableValue( c, key ) ); + } + + private void testDimension( JComponent c, StyleableUI ui, String key, int width, int height ) { + applyStyle( c,ui, String.format( "%s: %d,%d", key, width, height ) ); + assertEquals( new Dimension( width, height ), ui.getStyleableValue( c, key ) ); + } + + private void testFont( JComponent c, StyleableUI ui, String key, String style, Font expectedFont ) { + applyStyle( c,ui, String.format( "%s: %s", key, style ) ); + assertEquals( expectedFont, ui.getStyleableValue( c, key ) ); + } + + private void testIcon( JComponent c, StyleableUI ui, String key, String classname, Icon expectedIcon ) { + applyStyle( c,ui, String.format( "%s: %s", key, classname ) ); + assertEquals( expectedIcon, ui.getStyleableValue( c, key ) ); + } + + private void applyStyle( JComponent c, StyleableUI ui, String style ) { + Method m = findMethod( ui, "applyStyle", Object.class ); + if( m == null ) + m = findMethod( ui, "applyStyle", c.getClass(), Object.class ); + if( m == null ) + m = findMethod( ui, "applyStyle", c.getClass().getSuperclass(), Object.class ); + if( m == null ) + m = findMethod( ui, "applyStyle", c.getClass().getSuperclass().getSuperclass(), Object.class ); + if( m == null ) { + Assertions.fail( "missing method '" + ui.getClass() + + ".applyStyle( Object )' or 'applyStyle( " + c.getClass().getSimpleName() + + ", Object )'" ); + return; + } + + try { + m.setAccessible( true ); + if( m.getParameterCount() == 1 ) + m.invoke( ui, style ); + else + m.invoke( ui, c, style ); + } catch( Exception ex ) { + Assertions.fail( "failed to invoke 'applyStyle()'", ex ); + } + } + + private Method findMethod( StyleableUI ui, String name, Class... parameterTypes ) { + for( Class cls = ui.getClass(); cls != null; cls = cls.getSuperclass() ) { + try { + return cls.getDeclaredMethod( name, parameterTypes ); + } catch( Exception ex ) { + // ignore + } + } + return null; + } + + private void testValue( Object obj, String key, Object value ) { + try { + Method m = obj.getClass().getMethod( "applyStyleProperty", String.class, Object.class ); + m.invoke( obj, key, value ); + + m = obj.getClass().getMethod( "getStyleableValue", String.class ); + Object actualValue = m.invoke( obj, key ); + + assertEquals( value, actualValue ); + } catch( Exception ex ) { + Assertions.fail( ex ); + } + } + + //---- components --------------------------------------------------------- + + @Test + void button() { + JButton c = new JButton(); + FlatButtonUI ui = (FlatButtonUI) c.getUI(); + + button( c, ui ); + + //---- FlatHelpButtonIcon ---- + + testInteger( c, ui, "help.focusWidth", 123 ); + testColor( c, ui, "help.focusColor", 0x123456 ); + testFloat( c, ui, "help.innerFocusWidth", 1.23f ); + testInteger( c, ui, "help.borderWidth", 123 ); + + testColor( c, ui, "help.borderColor", 0x123456 ); + testColor( c, ui, "help.disabledBorderColor", 0x354678 ); + testColor( c, ui, "help.focusedBorderColor", 0x123456 ); + testColor( c, ui, "help.hoverBorderColor", 0x123456 ); + testColor( c, ui, "help.background", 0x132456 ); + testColor( c, ui, "help.disabledBackground", 0x123456 ); + testColor( c, ui, "help.focusedBackground", 0x123456 ); + testColor( c, ui, "help.hoverBackground", 0x123456 ); + testColor( c, ui, "help.pressedBackground", 0x123456 ); + testColor( c, ui, "help.questionMarkColor", 0x123456 ); + testColor( c, ui, "help.disabledQuestionMarkColor", 0x123456 ); + } + + private void button( AbstractButton c, FlatButtonUI ui ) { + testInteger( c, ui, "minimumWidth", 123 ); + + testColor( c, ui, "focusedBackground", 0x123456 ); + testColor( c, ui, "focusedForeground", 0x123456 ); + testColor( c, ui, "hoverBackground", 0x123456 ); + testColor( c, ui, "hoverForeground", 0x123456 ); + testColor( c, ui, "pressedBackground", 0x123456 ); + testColor( c, ui, "pressedForeground", 0x123456 ); + testColor( c, ui, "selectedBackground", 0x123456 ); + testColor( c, ui, "selectedForeground", 0x123456 ); + testColor( c, ui, "disabledBackground", 0x123456 ); + testColor( c, ui, "disabledText", 0x123456 ); + testColor( c, ui, "disabledSelectedBackground", 0x123456 ); + testColor( c, ui, "disabledSelectedForeground", 0x123456 ); + + testColor( c, ui, "default.background", 0x123456 ); + testColor( c, ui, "default.foreground", 0x123456 ); + testColor( c, ui, "default.focusedBackground", 0x123456 ); + testColor( c, ui, "default.focusedForeground", 0x123456 ); + testColor( c, ui, "default.hoverBackground", 0x123456 ); + testColor( c, ui, "default.hoverForeground", 0x123456 ); + testColor( c, ui, "default.pressedBackground", 0x123456 ); + testColor( c, ui, "default.pressedForeground", 0x123456 ); + testBoolean( c, ui, "default.boldText", true ); + + testBoolean( c, ui, "paintShadow", true ); + testInteger( c, ui, "shadowWidth", 123 ); + testColor( c, ui, "shadowColor", 0x123456 ); + testColor( c, ui, "default.shadowColor", 0x123456 ); + + testInsets( c, ui, "toolbar.spacingInsets", 1,2,3,4 ); + testColor( c, ui, "toolbar.hoverBackground", 0x123456 ); + testColor( c, ui, "toolbar.hoverForeground", 0x123456 ); + testColor( c, ui, "toolbar.pressedBackground", 0x123456 ); + testColor( c, ui, "toolbar.pressedForeground", 0x123456 ); + testColor( c, ui, "toolbar.selectedBackground", 0x123456 ); + testColor( c, ui, "toolbar.selectedForeground", 0x123456 ); + testColor( c, ui, "toolbar.disabledSelectedBackground", 0x123456 ); + testColor( c, ui, "toolbar.disabledSelectedForeground", 0x123456 ); + + testString( c, ui, "buttonType", "help" ); + testBoolean( c, ui, "squareSize", true ); + testInteger( c, ui, "minimumHeight", 123 ); + + // border + flatButtonBorder( c, ui ); + } + + @Test + void checkBox() { + JCheckBox c = new JCheckBox(); + FlatCheckBoxUI ui = (FlatCheckBoxUI) c.getUI(); + + // FlatCheckBoxUI extends FlatRadioButtonUI + radioButton( ui, c ); + } + + @Test + void comboBox() { + JComboBox c = new JComboBox<>(); + FlatComboBoxUI ui = (FlatComboBoxUI) c.getUI(); + + testInsets( c, ui, "padding", 1,2,3,4 ); + + testInteger( c, ui, "minimumWidth", 123 ); + testInteger( c, ui, "editorColumns", 123 ); + testString( c, ui, "buttonStyle", "auto" ); + testString( c, ui, "arrowType", "chevron" ); + + testColor( c, ui, "editableBackground", 123456 ); + testColor( c, ui, "focusedBackground", 0x123456 ); + testColor( c, ui, "disabledBackground", 0x123456 ); + testColor( c, ui, "disabledForeground", 0x123456 ); + + testColor( c, ui, "buttonBackground", 0x123456 ); + testColor( c, ui, "buttonFocusedBackground", 0x123456 ); + testColor( c, ui, "buttonEditableBackground", 0x123456 ); + testFloat( c, ui, "buttonSeparatorWidth", 1.23f ); + testColor( c, ui, "buttonSeparatorColor", 0x123456 ); + testColor( c, ui, "buttonDisabledSeparatorColor", 0x123456 ); + testColor( c, ui, "buttonArrowColor", 0x123456 ); + testColor( c, ui, "buttonDisabledArrowColor", 0x123456 ); + testColor( c, ui, "buttonHoverArrowColor", 0x123456 ); + testColor( c, ui, "buttonPressedArrowColor", 0x123456 ); + + testColor( c, ui, "popupBackground", 0x123456 ); + + // border + flatRoundBorder( c, ui ); + } + + @Test + void editorPane() { + JEditorPane c = new JEditorPane(); + FlatEditorPaneUI ui = (FlatEditorPaneUI) c.getUI(); + + testInteger( c, ui, "minimumWidth", 123 ); + testColor( c, ui, "disabledBackground", 0x123456 ); + testColor( c, ui, "inactiveBackground", 0x123456 ); + testColor( c, ui, "focusedBackground", 0x123456 ); + } + + @Test + void formattedTextField() { + JFormattedTextField c = new JFormattedTextField(); + FlatFormattedTextFieldUI ui = (FlatFormattedTextFieldUI) c.getUI(); + + // FlatFormattedTextFieldUI extends FlatTextFieldUI + textField( c, ui ); + } + + @Test + void internalFrame() { + JInternalFrame c = new JInternalFrame(); + FlatInternalFrameUI ui = (FlatInternalFrameUI) c.getUI(); + + testColor( c, ui, "activeBorderColor", 0x123456 ); + testColor( c, ui, "inactiveBorderColor", 0x123456 ); + testInteger( c, ui, "borderLineWidth", 123 ); + testBoolean( c, ui, "dropShadowPainted", false ); + testInsets( c, ui, "borderMargins", 1,2,3,4 ); + + testColor( c, ui, "activeDropShadowColor", 0x123456 ); + testInsets( c, ui, "activeDropShadowInsets", 1,2,3,4 ); + testFloat( c, ui, "activeDropShadowOpacity", 1.23f ); + testColor( c, ui, "inactiveDropShadowColor", 0x123456 ); + testInsets( c, ui, "inactiveDropShadowInsets", 1,2,3,4 ); + testFloat( c, ui, "inactiveDropShadowOpacity", 1.23f ); + } + + @Test + void label() { + JLabel c = new JLabel(); + FlatLabelUI ui = (FlatLabelUI) c.getUI(); + + testColor( c, ui, "disabledForeground", 0x123456 ); + } + + @Test + void list() { + JList c = new JList<>(); + FlatListUI ui = (FlatListUI) c.getUI(); + + testColor( c, ui, "selectionBackground", 0x123456 ); + testColor( c, ui, "selectionForeground", 0x123456 ); + testColor( c, ui, "selectionInactiveBackground", 0x123456 ); + testColor( c, ui, "selectionInactiveForeground", 0x123456 ); + + // FlatListCellBorder + testInsets( c, ui, "cellMargins", 1,2,3,4 ); + testColor( c, ui, "cellFocusColor", 0x123456 ); + testBoolean( c, ui, "showCellFocusIndicator", true ); + } + + @Test + void menuBar() { + JMenuBar c = new JMenuBar(); + FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI(); + + testInsets( c, ui, "itemMargins", 1,2,3,4 ); + testColor( c, ui, "hoverBackground", 0x123456 ); + testColor( c, ui, "underlineSelectionBackground", 0x123456 ); + testColor( c, ui, "underlineSelectionColor", 0x123456 ); + testInteger( c, ui, "underlineSelectionHeight", 123 ); + + // FlatMenuBarBorder + testColor( c, ui, "borderColor", 0x123456 ); + } + + @Test + void menu() { + JMenu c = new JMenu(); + FlatMenuUI ui = (FlatMenuUI) c.getUI(); + + menuItem( c, ui ); + menuItem_arrowIcon( c, ui ); + } + + @Test + void menuItem() { + JMenuItem c = new JMenuItem(); + FlatMenuItemUI ui = (FlatMenuItemUI) c.getUI(); + + menuItem( c, ui ); + } + + @Test + void checkBoxMenuItem() { + JCheckBoxMenuItem c = new JCheckBoxMenuItem(); + FlatCheckBoxMenuItemUI ui = (FlatCheckBoxMenuItemUI) c.getUI(); + + menuItem( c, ui ); + menuItem_checkIcon( c, ui ); + } + + @Test + void radioButtonMenuItem() { + JRadioButtonMenuItem c = new JRadioButtonMenuItem(); + FlatRadioButtonMenuItemUI ui = (FlatRadioButtonMenuItemUI) c.getUI(); + + menuItem( c, ui ); + menuItem_checkIcon( c, ui ); + } + + private void menuItem( JComponent c, StyleableUI ui ) { + testColor( c, ui, "selectionBackground", 0x123456 ); + testColor( c, ui, "selectionForeground", 0x123456 ); + testColor( c, ui, "disabledForeground", 0x123456 ); + testColor( c, ui, "acceleratorForeground", 0x123456 ); + testColor( c, ui, "acceleratorSelectionForeground", 0x123456 ); + testFont( c, ui, "acceleratorFont", "italic 12 monospaced", new Font( "monospaced", Font.ITALIC, 12 ) ); + + menuItemRenderer( c, ui ); + } + + private void menuItemRenderer( JComponent c, StyleableUI ui ) { + testBoolean( c, ui, "verticallyAlignText", false ); + testInteger( c, ui, "minimumWidth", 123 ); + testDimension( c, ui, "minimumIconSize", 1,2 ); + testInteger( c, ui, "textAcceleratorGap", 123 ); + testInteger( c, ui, "textNoAcceleratorGap", 123 ); + testInteger( c, ui, "acceleratorArrowGap", 123 ); + + testColor( c, ui, "checkBackground", 0x123456 ); + testInsets( c, ui, "checkMargins", 1,2,3,4 ); + + testColor( c, ui, "underlineSelectionBackground", 0x123456 ); + testColor( c, ui, "underlineSelectionCheckBackground", 0x123456 ); + testColor( c, ui, "underlineSelectionColor", 0x123456 ); + testInteger( c, ui, "underlineSelectionHeight", 123 ); + } + + private void menuItem_checkIcon( JComponent c, StyleableUI ui ) { + testColor( c, ui, "icon.checkmarkColor", 0x123456 ); + testColor( c, ui, "icon.disabledCheckmarkColor", 0x123456 ); + testColor( c, ui, "selectionForeground", 0x123456 ); + } + + private void menuItem_arrowIcon( JComponent c, StyleableUI ui ) { + testString( c, ui, "icon.arrowType", "chevron" ); + testColor( c, ui, "icon.arrowColor", 0x123456 ); + testColor( c, ui, "icon.disabledArrowColor", 0x123456 ); + testColor( c, ui, "selectionForeground", 0x123456 ); + } + + @Test + void panel() { + JPanel c = new JPanel(); + FlatPanelUI ui = (FlatPanelUI) c.getUI(); + + testInteger( c, ui, "arc", 123 ); + } + + @Test + void passwordField() { + JPasswordField c = new JPasswordField(); + FlatPasswordFieldUI ui = (FlatPasswordFieldUI) c.getUI(); + + // FlatPasswordFieldUI extends FlatTextFieldUI + textField( c, ui ); + + testBoolean( c, ui, "showCapsLock", true ); + testBoolean( c, ui, "showRevealButton", true ); + + // capsLockIcon + testColor( c, ui, "capsLockIconColor", 0x123456 ); + + // border + flatTextBorder( c, ui ); + } + + @Test + void popupMenu() { + JPopupMenu c = new JPopupMenu(); + FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI(); + + testString( c, ui, "arrowType", "chevron" ); + testColor( c, ui, "scrollArrowColor", 0x123456 ); + testColor( c, ui, "hoverScrollArrowBackground", 0x123456 ); + + testInsets( c, ui, "borderInsets", 1,2,3,4 ); + testColor( c, ui, "borderColor", 0x123456 ); + } + + @Test + void popupMenuSeparator() { + JPopupMenu.Separator c = new JPopupMenu.Separator(); + FlatPopupMenuSeparatorUI ui = (FlatPopupMenuSeparatorUI) c.getUI(); + + // FlatPopupMenuSeparatorUI extends FlatSeparatorUI + separator( ui, c ); + } + + @Test + void progressBar() { + JProgressBar c = new JProgressBar(); + FlatProgressBarUI ui = (FlatProgressBarUI) c.getUI(); + + testInteger( c, ui, "arc", 123 ); + testDimension( c, ui, "horizontalSize", 1,2 ); + testDimension( c, ui, "verticalSize", 1,2 ); + + testBoolean( c, ui, "largeHeight", true ); + testBoolean( c, ui, "square", true ); + } + + @Test + void radioButton() { + JRadioButton c = new JRadioButton(); + FlatRadioButtonUI ui = (FlatRadioButtonUI) c.getUI(); + + assertTrue( ui.getDefaultIcon() instanceof FlatRadioButtonIcon ); + + radioButton( ui, c ); + + testFloat( c, ui, "icon.centerDiameter", 1.23f ); + } + + private void radioButton( FlatRadioButtonUI ui, AbstractButton b ) { + testColor( b, ui, "disabledText", 0x123456 ); + + //---- icon ---- + + testFloat( b, ui, "icon.focusWidth", 1.23f ); + testColor( b, ui, "icon.focusColor", 0x123456 ); + testFloat( b, ui, "icon.borderWidth", 1.23f ); + testFloat( b, ui, "icon.selectedBorderWidth", 1.23f ); + testFloat( b, ui, "icon.disabledSelectedBorderWidth", 1.23f ); + testInteger( b, ui, "icon.arc", 123 ); + + // enabled + testColor( b, ui, "icon.borderColor", 0x123456 ); + testColor( b, ui, "icon.background", 0x901324 ); + testColor( b, ui, "icon.selectedBorderColor", 0x123456 ); + testColor( b, ui, "icon.selectedBackground", 0x123456 ); + testColor( b, ui, "icon.checkmarkColor", 0x123456 ); + + // disabled + testColor( b, ui, "icon.disabledBorderColor", 0x123456 ); + testColor( b, ui, "icon.disabledBackground", 0x123456 ); + testColor( b, ui, "icon.disabledSelectedBorderColor", 0x123456 ); + testColor( b, ui, "icon.disabledSelectedBackground", 0x123456 ); + testColor( b, ui, "icon.disabledCheckmarkColor", 0x123456 ); + + // focused + testColor( b, ui, "icon.focusedBorderColor", 0x123456 ); + testColor( b, ui, "icon.focusedBackground", 0x123456 ); + testColor( b, ui, "icon.focusedSelectedBorderColor", 0x123456 ); + testColor( b, ui, "icon.focusedSelectedBackground", 0x123456 ); + testColor( b, ui, "icon.focusedCheckmarkColor", 0x123456 ); + + // hover + testColor( b, ui, "icon.hoverBorderColor", 0x123456 ); + testColor( b, ui, "icon.hoverBackground", 0x123456 ); + testColor( b, ui, "icon.hoverSelectedBorderColor", 0x123456 ); + testColor( b, ui, "icon.hoverSelectedBackground", 0x123456 ); + testColor( b, ui, "icon.hoverCheckmarkColor", 0x123456 ); + + // pressed + testColor( b, ui, "icon.pressedBorderColor", 0x123456 ); + testColor( b, ui, "icon.pressedBackground", 0x123456 ); + testColor( b, ui, "icon.pressedSelectedBorderColor", 0x123456 ); + testColor( b, ui, "icon.pressedSelectedBackground", 0x123456 ); + testColor( b, ui, "icon.pressedCheckmarkColor", 0x123456 ); + } + + @Test + void scrollBar() { + JScrollBar c = new JScrollBar(); + FlatScrollBarUI ui = (FlatScrollBarUI) c.getUI(); + + testColor( c, ui, "track", 0x123456 ); + testColor( c, ui, "thumb", 0x123456 ); + testInteger( c, ui, "width", 123 ); + testDimension( c, ui, "minimumThumbSize", 1,2 ); + testDimension( c, ui, "maximumThumbSize", 1,2 ); + testBoolean( c, ui, "allowsAbsolutePositioning", true ); + + testDimension( c, ui, "minimumButtonSize", 1,2 ); + testInsets( c, ui, "trackInsets", 1,2,3,4 ); + testInsets( c, ui, "thumbInsets", 1,2,3,4 ); + testInteger( c, ui, "trackArc", 123 ); + testInteger( c, ui, "thumbArc", 123 ); + testColor( c, ui, "hoverTrackColor", 0x123456 ); + testColor( c, ui, "hoverThumbColor", 0x123456 ); + testBoolean( c, ui, "hoverThumbWithTrack", true ); + testColor( c, ui, "pressedTrackColor", 0x123456 ); + testColor( c, ui, "pressedThumbColor", 0x123456 ); + testBoolean( c, ui, "pressedThumbWithTrack", true ); + + testBoolean( c, ui, "showButtons", true ); + testString( c, ui, "arrowType", "chevron" ); + testColor( c, ui, "buttonArrowColor", 0x123456 ); + testColor( c, ui, "buttonDisabledArrowColor", 0x123456 ); + testColor( c, ui, "hoverButtonBackground", 0x123456 ); + testColor( c, ui, "pressedButtonBackground", 0x123456 ); + } + + @Test + void scrollPane() { + JScrollPane c = new JScrollPane(); + FlatScrollPaneUI ui = (FlatScrollPaneUI) c.getUI(); + + // border + flatBorder( c, ui ); + + testBoolean( c, ui, "showButtons", true ); + } + + @Test + void separator() { + JSeparator c = new JSeparator(); + FlatSeparatorUI ui = (FlatSeparatorUI) c.getUI(); + + separator( ui, c ); + } + + private void separator( FlatSeparatorUI ui, JSeparator c ) { + testInteger( c, ui, "height", 123 ); + testInteger( c, ui, "stripeWidth", 123 ); + testInteger( c, ui, "stripeIndent", 123 ); + } + + @Test + void slider() { + JSlider c = new JSlider(); + FlatSliderUI ui = (FlatSliderUI) c.getUI(); + + testInteger( c, ui, "trackWidth", 123 ); + testDimension( c, ui, "thumbSize", 1,2 ); + testInteger( c, ui, "focusWidth", 123 ); + testFloat( c, ui, "thumbBorderWidth", 1.23f ); + + testColor( c, ui, "trackValueColor", 0x123456 ); + testColor( c, ui, "trackColor", 0x123456 ); + testColor( c, ui, "thumbColor", 0x123456 ); + testColor( c, ui, "thumbBorderColor", 0x123456 ); + testColor( c, ui, "focusedColor", 0x123456 ); + testColor( c, ui, "focusedThumbBorderColor", 0x123456 ); + testColor( c, ui, "hoverThumbColor", 0x123456 ); + testColor( c, ui, "pressedThumbColor", 0x123456 ); + testColor( c, ui, "disabledTrackColor", 0x123456 ); + testColor( c, ui, "disabledThumbColor", 0x123456 ); + testColor( c, ui, "disabledThumbBorderColor", 0x123456 ); + testColor( c, ui, "tickColor", 0x123456 ); + } + + @Test + void spinner() { + JSpinner c = new JSpinner(); + FlatSpinnerUI ui = (FlatSpinnerUI) c.getUI(); + + testInteger( c, ui, "minimumWidth", 123 ); + testString( c, ui, "buttonStyle", "button" ); + testString( c, ui, "arrowType", "chevron" ); + testColor( c, ui, "disabledBackground", 0x123456 ); + testColor( c, ui, "disabledForeground", 0x123456 ); + testColor( c, ui, "focusedBackground", 0x123456 ); + testColor( c, ui, "buttonBackground", 0x123456 ); + testFloat( c, ui, "buttonSeparatorWidth", 1.23f ); + testColor( c, ui, "buttonSeparatorColor", 0x123456 ); + testColor( c, ui, "buttonDisabledSeparatorColor", 0x123456 ); + testColor( c, ui, "buttonArrowColor", 0x123456 ); + testColor( c, ui, "buttonDisabledArrowColor", 0x123456 ); + testColor( c, ui, "buttonHoverArrowColor", 0x123456 ); + testColor( c, ui, "buttonPressedArrowColor", 0x123456 ); + testInsets( c, ui, "padding", 1,2,3,4 ); + + // border + flatRoundBorder( c, ui ); + } + + @Test + void splitPane() { + JSplitPane c = new JSplitPane(); + FlatSplitPaneUI ui = (FlatSplitPaneUI) c.getUI(); + + testString( c, ui, "arrowType", "chevron" ); + testColor( c, ui, "oneTouchArrowColor", 0x123456 ); + testColor( c, ui, "oneTouchHoverArrowColor", 0x123456 ); + testColor( c, ui, "oneTouchPressedArrowColor", 0x123456 ); + + testString( c, ui, "style", "grip" ); + testColor( c, ui, "gripColor", 0x123456 ); + testInteger( c, ui, "gripDotCount", 123 ); + testInteger( c, ui, "gripDotSize", 123 ); + testInteger( c, ui, "gripGap", 123 ); + } + + @Test + void tabbedPane() { + JTabbedPane c = new JTabbedPane(); + FlatTabbedPaneUI ui = (FlatTabbedPaneUI) c.getUI(); + + testInsets( c, ui, "tabInsets", 1,2,3,4 ); + testInsets( c, ui, "tabAreaInsets", 1,2,3,4 ); + testInteger( c, ui, "textIconGap", 123 ); + + testColor( c, ui, "disabledForeground", 0x123456 ); + + testColor( c, ui, "selectedBackground", 0x123456 ); + testColor( c, ui, "selectedForeground", 0x123456 ); + testColor( c, ui, "underlineColor", 0x123456 ); + testColor( c, ui, "inactiveUnderlineColor", 0x123456 ); + testColor( c, ui, "disabledUnderlineColor", 0x123456 ); + testColor( c, ui, "hoverColor", 0x123456 ); + testColor( c, ui, "focusColor", 0x123456 ); + testColor( c, ui, "tabSeparatorColor", 0x123456 ); + testColor( c, ui, "contentAreaColor", 0x123456 ); + + testInteger( c, ui, "minimumTabWidth", 123 ); + testInteger( c, ui, "maximumTabWidth", 123 ); + testInteger( c, ui, "tabHeight", 123 ); + testInteger( c, ui, "tabSelectionHeight", 123 ); + testInteger( c, ui, "cardTabSelectionHeight", 123 ); + testInteger( c, ui, "contentSeparatorHeight", 123 ); + testBoolean( c, ui, "showTabSeparators", false ); + testBoolean( c, ui, "tabSeparatorsFullHeight", false ); + testBoolean( c, ui, "hasFullBorder", false ); + testBoolean( c, ui, "tabsOpaque", false ); + + testString( c, ui, "tabType", "card" ); + testString( c, ui, "tabsPopupPolicy", "asNeeded" ); + testString( c, ui, "scrollButtonsPolicy", "asNeeded" ); + testString( c, ui, "scrollButtonsPlacement", "both" ); + + testString( c, ui, "tabAreaAlignment", "leading" ); + testString( c, ui, "tabAlignment", "center" ); + testString( c, ui, "tabWidthMode", "preferred" ); + + testString( c, ui, "arrowType", "chevron" ); + testInsets( c, ui, "buttonInsets", 1,2,3,4 ); + testInteger( c, ui, "buttonArc", 123 ); + testColor( c, ui, "buttonHoverBackground", 0x123456 ); + testColor( c, ui, "buttonPressedBackground", 0x123456 ); + + testString( c, ui, "moreTabsButtonToolTipText", "Gimme more" ); + testString( c, ui, "tabCloseToolTipText", "Close me" ); + + testBoolean( c, ui, "showContentSeparator", true ); + testBoolean( c, ui, "hideTabAreaWithOneTab", true ); + testBoolean( c, ui, "tabClosable", true ); + testString( c, ui, "tabIconPlacement", "top" ); + + // FlatTabbedPaneCloseIcon + testDimension( c, ui, "closeSize", 1,2 ); + testInteger( c, ui, "closeArc", 123 ); + testFloat( c, ui, "closeCrossPlainSize", 1.23f ); + testFloat( c, ui, "closeCrossFilledSize", 1.23f ); + testFloat( c, ui, "closeCrossLineWidth", 1.23f ); + testColor( c, ui, "closeBackground", 0x123456 ); + testColor( c, ui, "closeForeground", 0x123456 ); + testColor( c, ui, "closeHoverBackground", 0x123456 ); + testColor( c, ui, "closeHoverForeground", 0x123456 ); + testColor( c, ui, "closePressedBackground", 0x123456 ); + testColor( c, ui, "closePressedForeground", 0x123456 ); + } + + @Test + void table() { + JTable c = new JTable(); + FlatTableUI ui = (FlatTableUI) c.getUI(); + + testBoolean( c, ui, "showTrailingVerticalLine", true ); + testColor( c, ui, "selectionBackground", 0x123456 ); + testColor( c, ui, "selectionForeground", 0x123456 ); + testColor( c, ui, "selectionInactiveBackground", 0x123456 ); + testColor( c, ui, "selectionInactiveForeground", 0x901324 ); + + // FlatTableCellBorder + testInsets( c, ui, "cellMargins", 1,2,3,4 ); + testColor( c, ui, "cellFocusColor", 0x123456 ); + testBoolean( c, ui, "showCellFocusIndicator", true ); + } + + @Test + void tableHeader() { + JTableHeader c = new JTableHeader(); + FlatTableHeaderUI ui = (FlatTableHeaderUI) c.getUI(); + + testColor( c, ui, "bottomSeparatorColor", 0x123456 ); + testInteger( c, ui, "height", 123 ); + testString( c, ui, "sortIconPosition", "top" ); + + // FlatTableHeaderBorder + testInsets( c, ui, "cellMargins", 1,2,3,4 ); + testColor( c, ui, "separatorColor", 0x123456 ); + testBoolean( c, ui, "showTrailingVerticalLine", true ); + + // FlatAscendingSortIcon and FlatDescendingSortIcon + testString( c, ui, "arrowType", "chevron" ); + testColor( c, ui, "sortIconColor", 0x123456 ); + } + + @Test + void textArea() { + JTextArea c = new JTextArea(); + FlatTextAreaUI ui = (FlatTextAreaUI) c.getUI(); + + testInteger( c, ui, "minimumWidth", 123 ); + testColor( c, ui, "disabledBackground", 0x123456 ); + testColor( c, ui, "inactiveBackground", 0x123456 ); + testColor( c, ui, "focusedBackground", 0x123456 ); + } + + @Test + void textField() { + JTextField c = new JTextField(); + FlatTextFieldUI ui = (FlatTextFieldUI) c.getUI(); + + textField( c, ui ); + } + + private void textField( JTextComponent c, FlatTextFieldUI ui ) { + testInteger( c, ui, "minimumWidth", 123 ); + testColor( c, ui, "disabledBackground", 0x123456 ); + testColor( c, ui, "inactiveBackground", 0x123456 ); + testColor( c, ui, "placeholderForeground", 0x123456 ); + testColor( c, ui, "focusedBackground", 0x123456 ); + testInteger( c, ui, "iconTextGap", 123 ); + testIcon( c, ui, "leadingIcon", TestIcon.class.getName(), new TestIcon() ); + testIcon( c, ui, "trailingIcon", TestIcon.class.getName(), new TestIcon() ); + + testBoolean( c, ui, "showClearButton", true ); + + // border + flatTextBorder( c, ui ); + } + + @Test + void textPane() { + JTextPane c = new JTextPane(); + FlatTextPaneUI ui = (FlatTextPaneUI) c.getUI(); + + testInteger( c, ui, "minimumWidth", 123 ); + testColor( c, ui, "disabledBackground", 0x123456 ); + testColor( c, ui, "inactiveBackground", 0x123456 ); + testColor( c, ui, "focusedBackground", 0x123456 ); + } + + @Test + void toggleButton() { + JToggleButton b = new JToggleButton(); + FlatToggleButtonUI ui = (FlatToggleButtonUI) b.getUI(); + + // FlatToggleButtonUI extends FlatButtonUI + button( b, ui ); + + testInteger( b, ui, "tab.underlineHeight", 123 ); + testColor( b, ui, "tab.underlineColor", 0x123456 ); + testColor( b, ui, "tab.disabledUnderlineColor", 0x123456 ); + testColor( b, ui, "tab.selectedBackground", 0x123456 ); + testColor( b, ui, "tab.selectedForeground", 0x123456 ); + testColor( b, ui, "tab.hoverBackground", 0x123456 ); + testColor( b, ui, "tab.hoverForeground", 0x123456 ); + testColor( b, ui, "tab.focusBackground", 0x123456 ); + testColor( b, ui, "tab.focusForeground", 0x123456 ); + } + + @Test + void toolBar() { + JToolBar c = new JToolBar(); + FlatToolBarUI ui = (FlatToolBarUI) c.getUI(); + + testBoolean( c, ui, "focusableButtons", true ); + testBoolean( c, ui, "arrowKeysOnlyNavigation", true ); + + testInsets( c, ui, "borderMargins", 1,2,3,4 ); + testColor( c, ui, "gripColor", 0x123456 ); + } + + @Test + void toolBarSeparator() { + JToolBar.Separator c = new JToolBar.Separator(); + FlatToolBarSeparatorUI ui = (FlatToolBarSeparatorUI) c.getUI(); + + testInteger( c, ui, "separatorWidth", 123 ); + testColor( c, ui, "separatorColor", 0x123456 ); + } + + @Test + void tree() { + JTree c = new JTree(); + FlatTreeUI ui = (FlatTreeUI) c.getUI(); + + testColor( c, ui, "selectionBackground", 0x123456 ); + testColor( c, ui, "selectionForeground", 0x123456 ); + testColor( c, ui, "selectionInactiveBackground", 0x123456 ); + testColor( c, ui, "selectionInactiveForeground", 0x123456 ); + testColor( c, ui, "selectionBorderColor", 0x123456 ); + testBoolean( c, ui, "wideSelection", true ); + testBoolean( c, ui, "showCellFocusIndicator", true ); + + testBoolean( c, ui, "paintSelection", false ); + + // icons + testString( c, ui, "icon.arrowType", "chevron" ); + testColor( c, ui, "icon.expandedColor", 0x123456 ); + testColor( c, ui, "icon.collapsedColor", 0x123456 ); + testColor( c, ui, "icon.leafColor", 0x123456 ); + testColor( c, ui, "icon.closedColor", 0x123456 ); + testColor( c, ui, "icon.openColor", 0x123456 ); + } + + //---- component borders -------------------------------------------------- + + private void flatButtonBorder( JComponent c, StyleableUI ui ) { + flatBorder( c, ui ); + + testInteger( c, ui, "arc", 123 ); + + testColor( c, ui, "borderColor", 0x123456 ); + testColor( c, ui, "disabledBorderColor", 0x123456 ); + testColor( c, ui, "focusedBorderColor", 0x123456 ); + testColor( c, ui, "hoverBorderColor", 0x123456 ); + + testFloat( c, ui, "default.borderWidth", 1.23f ); + testColor( c, ui, "default.borderColor", 0x123456 ); + testColor( c, ui, "default.focusedBorderColor", 0x123456 ); + testColor( c, ui, "default.focusColor", 0x123456 ); + testColor( c, ui, "default.hoverBorderColor", 0x123456 ); + + testFloat( c, ui, "toolbar.focusWidth", 1.23f ); + testColor( c, ui, "toolbar.focusColor", 0x123456 ); + testInsets( c, ui, "toolbar.margin", 1,2,3,4 ); + testInsets( c, ui, "toolbar.spacingInsets", 1,2,3,4 ); + } + + private void flatRoundBorder( JComponent c, StyleableUI ui ) { + flatBorder( c, ui ); + + testInteger( c, ui, "arc", 123 ); + + testBoolean( c, ui, "roundRect", true ); + } + + private void flatTextBorder( JComponent c, StyleableUI ui ) { + flatBorder( c, ui ); + + testInteger( c, ui, "arc", 123 ); + + testBoolean( c, ui, "roundRect", true ); + } + + private void flatBorder( JComponent c, StyleableUI ui ) { + testInteger( c, ui, "focusWidth", 123 ); + testFloat( c, ui, "innerFocusWidth", 1.23f ); + testFloat( c, ui, "innerOutlineWidth", 1.23f ); + testFloat( c, ui, "borderWidth", 1.23f ); + + testColor( c, ui, "focusColor", 0x123456 ); + testColor( c, ui, "borderColor", 0x123456 ); + testColor( c, ui, "disabledBorderColor", 0x123456 ); + testColor( c, ui, "focusedBorderColor", 0x123456 ); + + testColor( c, ui, "error.borderColor", 0x123456 ); + testColor( c, ui, "error.focusedBorderColor", 0x123456 ); + testColor( c, ui, "warning.borderColor", 0x123456 ); + testColor( c, ui, "warning.focusedBorderColor", 0x123456 ); + testColor( c, ui, "custom.borderColor", 0x123456 ); + + testString( c, ui, "outline", "error" ); + testColor( c, ui, "outlineColor", 0x123456 ); + testColor( c, ui, "outlineFocusedColor", 0x123456 ); + } + + //---- borders ------------------------------------------------------------ + + @Test + void flatButtonBorder() { + FlatButtonBorder border = new FlatButtonBorder(); + + // FlatButtonBorder extends FlatBorder + flatBorder( border ); + + testValue( border, "arc", 6 ); + + testValue( border, "borderColor", Color.WHITE ); + testValue( border, "disabledBorderColor", Color.WHITE ); + testValue( border, "focusedBorderColor", Color.WHITE ); + testValue( border, "hoverBorderColor", Color.WHITE ); + + testValue( border, "default.borderWidth", 2f ); + testValue( border, "default.borderColor", Color.WHITE ); + testValue( border, "default.focusedBorderColor", Color.WHITE ); + testValue( border, "default.focusColor", Color.WHITE ); + testValue( border, "default.hoverBorderColor", Color.WHITE ); + + testValue( border, "toolbar.focusWidth", 1.5f ); + testValue( border, "toolbar.focusColor", Color.WHITE ); + testValue( border, "toolbar.margin", new Insets( 1, 2, 3, 4 ) ); + testValue( border, "toolbar.spacingInsets", new Insets( 1, 2, 3, 4 ) ); + } + + @Test + void flatRoundBorder() { + FlatRoundBorder border = new FlatRoundBorder(); + + // FlatRoundBorder extends FlatBorder + flatBorder( border ); + + testValue( border, "arc", 6 ); + } + + @Test + void flatTextBorder() { + FlatTextBorder border = new FlatTextBorder(); + + // FlatTextBorder extends FlatBorder + flatBorder( border ); + + testValue( border, "arc", 6 ); + } + + @Test + void flatBorder() { + FlatBorder border = new FlatBorder(); + + flatBorder( border ); + } + + private void flatBorder( FlatBorder border ) { + testValue( border, "focusWidth", 2 ); + testValue( border, "innerFocusWidth", 0.5f ); + testValue( border, "innerOutlineWidth", 1.5f ); + testValue( border, "borderWidth", 1f ); + + testValue( border, "focusColor", Color.WHITE ); + testValue( border, "borderColor", Color.WHITE ); + testValue( border, "disabledBorderColor", Color.WHITE ); + testValue( border, "focusedBorderColor", Color.WHITE ); + + testValue( border, "error.borderColor", Color.WHITE ); + testValue( border, "error.focusedBorderColor", Color.WHITE ); + testValue( border, "warning.borderColor", Color.WHITE ); + testValue( border, "warning.focusedBorderColor", Color.WHITE ); + testValue( border, "custom.borderColor", Color.WHITE ); + } + + //---- icons -------------------------------------------------------------- + + @Test + void flatCheckBoxIcon() { + FlatCheckBoxIcon icon = new FlatCheckBoxIcon(); + + flatCheckBoxIcon( icon ); + } + + @Test + void flatRadioButtonIcon() { + FlatRadioButtonIcon icon = new FlatRadioButtonIcon(); + + // FlatRadioButtonIcon extends FlatCheckBoxIcon + flatCheckBoxIcon( icon ); + + testValue( icon, "centerDiameter", 8f ); + } + + private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { + testValue( icon, "focusWidth", 1.5f ); + testValue( icon, "focusColor", Color.WHITE ); + testValue( icon, "borderWidth", 1.5f ); + testValue( icon, "selectedBorderWidth", 1.5f ); + testValue( icon, "disabledSelectedBorderWidth", 1.5f ); + testValue( icon, "arc", 5 ); + + // enabled + testValue( icon, "borderColor", Color.WHITE ); + testValue( icon, "background", Color.WHITE ); + testValue( icon, "selectedBorderColor", Color.WHITE ); + testValue( icon, "selectedBackground", Color.WHITE ); + testValue( icon, "checkmarkColor", Color.WHITE ); + + // disabled + testValue( icon, "disabledBorderColor", Color.WHITE ); + testValue( icon, "disabledBackground", Color.WHITE ); + testValue( icon, "disabledSelectedBorderColor", Color.WHITE ); + testValue( icon, "disabledSelectedBackground", Color.WHITE ); + testValue( icon, "disabledCheckmarkColor", Color.WHITE ); + + // focused + testValue( icon, "focusedBorderColor", Color.WHITE ); + testValue( icon, "focusedBackground", Color.WHITE ); + testValue( icon, "focusedSelectedBorderColor", Color.WHITE ); + testValue( icon, "focusedSelectedBackground", Color.WHITE ); + testValue( icon, "focusedCheckmarkColor", Color.WHITE ); + + // hover + testValue( icon, "hoverBorderColor", Color.WHITE ); + testValue( icon, "hoverBackground", Color.WHITE ); + testValue( icon, "hoverSelectedBorderColor", Color.WHITE ); + testValue( icon, "hoverSelectedBackground", Color.WHITE ); + testValue( icon, "hoverCheckmarkColor", Color.WHITE ); + + // pressed + testValue( icon, "pressedBorderColor", Color.WHITE ); + testValue( icon, "pressedBackground", Color.WHITE ); + testValue( icon, "pressedSelectedBorderColor", Color.WHITE ); + testValue( icon, "pressedSelectedBackground", Color.WHITE ); + testValue( icon, "pressedCheckmarkColor", Color.WHITE ); + } + + @Test + void flatCheckBoxMenuItemIcon() { + FlatCheckBoxMenuItemIcon icon = new FlatCheckBoxMenuItemIcon(); + + flatCheckBoxMenuItemIcon( icon ); + } + + @Test + void flatRadioButtonMenuItemIcon() { + FlatRadioButtonMenuItemIcon icon = new FlatRadioButtonMenuItemIcon(); + + // FlatRadioButtonMenuItemIcon extends FlatCheckBoxMenuItemIcon + flatCheckBoxMenuItemIcon( icon ); + } + + private void flatCheckBoxMenuItemIcon( FlatCheckBoxMenuItemIcon icon ) { + testValue( icon, "checkmarkColor", Color.WHITE ); + testValue( icon, "disabledCheckmarkColor", Color.WHITE ); + testValue( icon, "selectionForeground", Color.WHITE ); + } + + @Test + void flatMenuArrowIcon() { + FlatMenuArrowIcon icon = new FlatMenuArrowIcon(); + + testValue( icon, "arrowType", "chevron" ); + testValue( icon, "arrowColor", Color.WHITE ); + testValue( icon, "disabledArrowColor", Color.WHITE ); + testValue( icon, "selectionForeground", Color.WHITE ); + } + + @Test + void flatHelpButtonIcon() { + FlatHelpButtonIcon icon = new FlatHelpButtonIcon(); + + testValue( icon, "focusWidth", 2 ); + testValue( icon, "focusColor", Color.WHITE ); + testValue( icon, "innerFocusWidth", 0.5f ); + testValue( icon, "borderWidth", 1 ); + + testValue( icon, "borderColor", Color.WHITE ); + testValue( icon, "disabledBorderColor", Color.WHITE ); + testValue( icon, "focusedBorderColor", Color.WHITE ); + testValue( icon, "hoverBorderColor", Color.WHITE ); + testValue( icon, "background", Color.WHITE ); + testValue( icon, "disabledBackground", Color.WHITE ); + testValue( icon, "focusedBackground", Color.WHITE ); + testValue( icon, "hoverBackground", Color.WHITE ); + testValue( icon, "pressedBackground", Color.WHITE ); + testValue( icon, "questionMarkColor", Color.WHITE ); + testValue( icon, "disabledQuestionMarkColor", Color.WHITE ); + } + + @Test + void flatClearIcon() { + FlatClearIcon icon = new FlatClearIcon(); + + testValue( icon, "clearIconColor", Color.WHITE ); + testValue( icon, "clearIconHoverColor", Color.WHITE ); + testValue( icon, "clearIconPressedColor", Color.WHITE ); + } + + @Test + void flatSearchIcon() { + FlatSearchIcon icon = new FlatSearchIcon(); + + flatSearchIcon( icon ); + } + + @Test + void flatSearchWithHistoryIcon() { + FlatSearchWithHistoryIcon icon = new FlatSearchWithHistoryIcon(); + + flatSearchIcon( icon ); + } + + private void flatSearchIcon( FlatSearchIcon icon ) { + testValue( icon, "searchIconColor", Color.WHITE ); + testValue( icon, "searchIconHoverColor", Color.WHITE ); + testValue( icon, "searchIconPressedColor", Color.WHITE ); + } + + //---- class TestIcon ----------------------------------------------------- + + public static class TestIcon + implements Icon + { + @Override public void paintIcon( Component c, Graphics g, int x, int y ) {} + @Override public int getIconWidth() { return 0; } + @Override public int getIconHeight() { return 0; } + + @Override + public boolean equals( Object obj ) { + return obj instanceof TestIcon; + } + } +}