From b6be0462a5cb0601c360090f35d2c9a11837e99c Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 25 Sep 2021 14:34:21 +0200 Subject: [PATCH 1/5] Styling: basic support for "classes" (similar to CSS classes) using client property `FlatLaf.styleClass` --- .../formdev/flatlaf/FlatClientProperties.java | 32 ++ .../com/formdev/flatlaf/ui/FlatButtonUI.java | 19 +- .../flatlaf/ui/FlatCheckBoxMenuItemUI.java | 9 +- .../formdev/flatlaf/ui/FlatCheckBoxUI.java | 6 + .../formdev/flatlaf/ui/FlatComboBoxUI.java | 43 +- .../formdev/flatlaf/ui/FlatEditorPaneUI.java | 15 +- .../flatlaf/ui/FlatFormattedTextFieldUI.java | 6 + .../flatlaf/ui/FlatInternalFrameUI.java | 9 +- .../com/formdev/flatlaf/ui/FlatLabelUI.java | 14 +- .../com/formdev/flatlaf/ui/FlatListUI.java | 10 +- .../com/formdev/flatlaf/ui/FlatMenuBarUI.java | 15 +- .../formdev/flatlaf/ui/FlatMenuItemUI.java | 9 +- .../com/formdev/flatlaf/ui/FlatMenuUI.java | 9 +- .../flatlaf/ui/FlatPasswordFieldUI.java | 6 + .../flatlaf/ui/FlatPopupMenuSeparatorUI.java | 6 + .../formdev/flatlaf/ui/FlatPopupMenuUI.java | 14 +- .../formdev/flatlaf/ui/FlatProgressBarUI.java | 10 +- .../flatlaf/ui/FlatRadioButtonMenuItemUI.java | 9 +- .../formdev/flatlaf/ui/FlatRadioButtonUI.java | 18 +- .../formdev/flatlaf/ui/FlatScrollBarUI.java | 10 +- .../formdev/flatlaf/ui/FlatScrollPaneUI.java | 10 +- .../formdev/flatlaf/ui/FlatSeparatorUI.java | 25 +- .../com/formdev/flatlaf/ui/FlatSliderUI.java | 9 +- .../com/formdev/flatlaf/ui/FlatSpinnerUI.java | 10 +- .../formdev/flatlaf/ui/FlatSplitPaneUI.java | 14 +- .../flatlaf/ui/FlatStylingSupport.java | 163 ++++++- .../formdev/flatlaf/ui/FlatTabbedPaneUI.java | 10 +- .../formdev/flatlaf/ui/FlatTableHeaderUI.java | 14 +- .../com/formdev/flatlaf/ui/FlatTableUI.java | 10 +- .../formdev/flatlaf/ui/FlatTextAreaUI.java | 9 +- .../formdev/flatlaf/ui/FlatTextFieldUI.java | 15 +- .../formdev/flatlaf/ui/FlatTextPaneUI.java | 9 +- .../flatlaf/ui/FlatToggleButtonUI.java | 5 + .../flatlaf/ui/FlatToolBarSeparatorUI.java | 20 +- .../com/formdev/flatlaf/ui/FlatToolBarUI.java | 9 +- .../com/formdev/flatlaf/ui/FlatTreeUI.java | 10 +- .../com/formdev/flatlaf/ui/FlatUIUtils.java | 6 +- .../flatlaf/ui/MigLayoutVisualPadding.java | 4 +- .../flatlaf/ui/TestFlatStyleClasses.java | 448 ++++++++++++++++++ 39 files changed, 951 insertions(+), 118 deletions(-) create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java index c601eca4..f4b4e03d 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -145,6 +145,38 @@ public interface FlatClientProperties */ String STYLE = "FlatLaf.style"; + /** + * Specifies the style class(es) of a component as String + * or as {@link java.util.List}<String>. + *

+ * The style rules must be defined in UI defaults either as strings (in CSS syntax) + * or as {@link java.util.Map}<String, Object> (with binary values). + * The key must be in syntax: {@code [style]type.styleClass}, where the type is optional. + * E.g. in FlatLaf properties file: + *

{@code
+	 * [style]Button.primary = borderColor: #08f; background: #08f; foreground: #fff
+	 * [style].secondary = borderColor: #0f8; background: #0f8
+	 * }
+ * or in Java code: + *
{@code
+	 * UIManager.put( "[style]Button.primary", "borderColor: #08f; background: #08f; foreground: #fff" );
+	 * UIManager.put( "[style].secondary", "borderColor: #0f8; background: #0f8" );
+	 * }
+ * The rule "Button.primary" can be applied to buttons only. + * The rule ".secondary" can be applied to any component. + *

+ * To have similar behaviour as in CSS, first the rule without type is applied, + * then the rule with type. + * E.g. setting style class to "foo" on a {@code JButton} uses rules + * from UI default keys "[style].foo" and "[style]Button.foo". + *

+ * Components {@link javax.swing.JComponent}
+ * Value type {@link java.lang.String}, {@code String[]} or {@link java.util.List}<String>
+ * + * @since 2 + */ + String STYLE_CLASS = "FlatLaf.styleClass"; + /** * Specifies minimum width of a component. *

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 0465e7d0..a29c4626 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 @@ -152,6 +152,7 @@ public class FlatButtonUI : new FlatButtonUI( false ); } + /** @since 2 */ protected FlatButtonUI( boolean shared ) { this.shared = shared; } @@ -160,7 +161,7 @@ public class FlatButtonUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( (AbstractButton) c, FlatStylingSupport.getStyle( c ) ); + installStyle( (AbstractButton) c ); } @Override @@ -254,19 +255,29 @@ public class FlatButtonUI break; case STYLE: - Object style = e.getNewValue(); - if( style != null && shared ) { + case STYLE_CLASS: + if( shared && FlatStylingSupport.hasStyleProperty( b ) ) { // unshare component UI if necessary // updateUI() invokes applyStyle() from installUI() b.updateUI(); } else - applyStyle( b, style ); + installStyle( b ); b.revalidate(); b.repaint(); break; } } + /** @since 2 */ + protected void installStyle( AbstractButton b ) { + applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) ); + } + + /** @since 2 */ + String getStyleType() { + return "Button"; + } + /** @since 2 */ protected void applyStyle( AbstractButton b, Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, 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 5db876ba..b78ca31d 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 @@ -72,7 +72,7 @@ public class FlatCheckBoxMenuItemUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( menuItem ) ); + installStyle(); } @Override @@ -98,7 +98,12 @@ public class FlatCheckBoxMenuItemUI @Override protected PropertyChangeListener createPropertyChangeListener( JComponent c ) { - return FlatStylingSupport.createPropertyChangeListener( c, this::applyStyle, super.createPropertyChangeListener( c ) ); + return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) ); + } + + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "CheckBoxMenuItem" ) ); } /** @since 2 */ diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxUI.java index 0c407fd6..354b30b1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCheckBoxUI.java @@ -57,4 +57,10 @@ public class FlatCheckBoxUI public String getPropertyPrefix() { return "CheckBox."; } + + /** @since 2 */ + @Override + String getStyleType() { + return "CheckBox"; + } } 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 1d438c7e..25f086bf 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 @@ -16,6 +16,7 @@ package com.formdev.flatlaf.ui; +import static com.formdev.flatlaf.FlatClientProperties.*; import static com.formdev.flatlaf.util.UIScale.scale; import static com.formdev.flatlaf.util.UIScale.unscale; import java.awt.Color; @@ -69,7 +70,6 @@ import javax.swing.plaf.basic.BasicComboBoxUI; import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.plaf.basic.ComboPopup; import javax.swing.text.JTextComponent; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.util.SystemInfo; @@ -155,7 +155,7 @@ public class FlatComboBoxUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( comboBox ) ); + installStyle(); } @Override @@ -341,16 +341,28 @@ public class FlatComboBoxUI } else if( editor != null && source == comboBox && propertyName == "componentOrientation" ) { ComponentOrientation o = (ComponentOrientation) e.getNewValue(); editor.applyComponentOrientation( o ); - } else if( editor != null && FlatClientProperties.PLACEHOLDER_TEXT.equals( propertyName ) ) - editor.repaint(); - else if( FlatClientProperties.COMPONENT_ROUND_RECT.equals( propertyName ) ) - comboBox.repaint(); - else if( FlatClientProperties.MINIMUM_WIDTH.equals( propertyName ) ) - comboBox.revalidate(); - else if( FlatClientProperties.STYLE.equals( propertyName ) ) { - applyStyle( e.getNewValue() ); - comboBox.revalidate(); - comboBox.repaint(); + } else { + switch( propertyName ) { + case PLACEHOLDER_TEXT: + if( editor != null ) + editor.repaint(); + break; + + case COMPONENT_ROUND_RECT: + comboBox.repaint(); + break; + + case MINIMUM_WIDTH: + comboBox.revalidate(); + break; + + case STYLE: + case STYLE_CLASS: + installStyle(); + comboBox.revalidate(); + comboBox.repaint(); + break; + } } }; } @@ -419,7 +431,7 @@ public class FlatComboBoxUI unscale( Math.max( scale( padding.right ) - insets.right, 0 ) ) ); } - textField.putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, pad ); + textField.putClientProperty( TEXT_FIELD_PADDING, pad ); } private void updateEditorColors() { @@ -438,6 +450,11 @@ public class FlatComboBoxUI return new FlatComboBoxButton(); } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( comboBox, "ComboBox" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { Insets oldPadding = padding; 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 3fe21d52..6c9cb714 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 @@ -25,7 +25,6 @@ import java.awt.Insets; import java.awt.event.FocusListener; import java.beans.PropertyChangeEvent; import java.util.Map; -import java.util.function.Consumer; import javax.swing.JComponent; import javax.swing.JEditorPane; import javax.swing.UIManager; @@ -91,7 +90,7 @@ public class FlatEditorPaneUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -155,23 +154,29 @@ public class FlatEditorPaneUI updateBackground(); super.propertyChange( e ); - propertyChange( getComponent(), e, this::applyStyle ); + propertyChange( getComponent(), e, this::installStyle ); } - static void propertyChange( JTextComponent c, PropertyChangeEvent e, Consumer applyStyle ) { + static void propertyChange( JTextComponent c, PropertyChangeEvent e, Runnable installStyle ) { switch( e.getPropertyName() ) { case FlatClientProperties.MINIMUM_WIDTH: c.revalidate(); break; case FlatClientProperties.STYLE: - applyStyle.accept( e.getNewValue() ); + case FlatClientProperties.STYLE_CLASS: + installStyle.run(); c.revalidate(); c.repaint(); break; } } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "EditorPane" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldDisabledBackground = disabledBackground; diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java index 6e34a643..5f390de8 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java @@ -60,4 +60,10 @@ public class FlatFormattedTextFieldUI protected String getPropertyPrefix() { return "FormattedTextField"; } + + /** @since 2 */ + @Override + String getStyleType() { + return "FormattedTextField"; + } } 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 b11acd16..32460cda 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 @@ -116,7 +116,7 @@ public class FlatInternalFrameUI windowResizer = createWindowResizer(); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -148,10 +148,15 @@ public class FlatInternalFrameUI @Override protected PropertyChangeListener createPropertyChangeListener() { - return FlatStylingSupport.createPropertyChangeListener( frame, this::applyStyle, + return FlatStylingSupport.createPropertyChangeListener( frame, this::installStyle, super.createPropertyChangeListener() ); } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( frame, "InternalFrame" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 e90e4df5..2c16494a 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 @@ -81,7 +81,7 @@ public class FlatLabelUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( (JLabel) c, FlatStylingSupport.getStyle( c ) ); + installStyle( (JLabel) c ); } @Override @@ -117,21 +117,25 @@ public class FlatLabelUI if( name == "text" || name == "font" || name == "foreground" ) { JLabel label = (JLabel) e.getSource(); updateHTMLRenderer( label, label.getText(), true ); - } else if( name.equals( FlatClientProperties.STYLE ) ) { + } else if( name.equals( FlatClientProperties.STYLE ) || name.equals( FlatClientProperties.STYLE_CLASS ) ) { JLabel label = (JLabel) e.getSource(); - Object style = e.getNewValue(); - if( style != null && shared ) { + if( shared && FlatStylingSupport.hasStyleProperty( label ) ) { // unshare component UI if necessary // updateUI() invokes applyStyle() from installUI() label.updateUI(); } else - applyStyle( label, style ); + installStyle( label ); label.revalidate(); label.repaint(); } else super.propertyChange( e ); } + /** @since 2 */ + protected void installStyle( JLabel c ) { + applyStyle( c, FlatStylingSupport.getResolvedStyle( c, "Label" ) ); + } + /** @since 2 */ protected void applyStyle( JLabel c, Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, 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 9e1cb035..956c6b76 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 @@ -91,7 +91,7 @@ public class FlatListUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -151,7 +151,8 @@ public class FlatListUI break; case FlatClientProperties.STYLE: - applyStyle( e.getNewValue() ); + case FlatClientProperties.STYLE_CLASS: + installStyle(); list.revalidate(); list.repaint(); break; @@ -159,6 +160,11 @@ public class FlatListUI }; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( list, "List" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { Color oldSelectionBackground = selectionBackground; 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 2e09ecf4..a0e5280a 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 @@ -39,7 +39,6 @@ import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicMenuBarUI; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; @@ -91,7 +90,7 @@ public class FlatMenuBarUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -113,16 +112,15 @@ public class FlatMenuBarUI protected void installListeners() { super.installListeners(); - propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( - menuBar, this::applyStyle, null ); - menuBar.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( menuBar, this::installStyle, null ); + menuBar.addPropertyChangeListener( propertyChangeListener ); } @Override protected void uninstallListeners() { super.uninstallListeners(); - menuBar.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + menuBar.removePropertyChangeListener( propertyChangeListener ); propertyChangeListener = null; } @@ -138,6 +136,11 @@ public class FlatMenuBarUI map.put( "takeFocus", new TakeFocus() ); } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( menuBar, "MenuBar" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 541d0c5a..0b7b9516 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 @@ -73,7 +73,7 @@ public class FlatMenuItemUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( menuItem ) ); + installStyle(); } @Override @@ -99,7 +99,12 @@ public class FlatMenuItemUI @Override protected PropertyChangeListener createPropertyChangeListener( JComponent c ) { - return FlatStylingSupport.createPropertyChangeListener( c, this::applyStyle, super.createPropertyChangeListener( c ) ); + return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) ); + } + + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "MenuItem" ) ); } /** @since 2 */ 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 2805f529..009c505a 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 @@ -92,7 +92,7 @@ public class FlatMenuUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( menuItem ) ); + installStyle(); } @Override @@ -145,7 +145,12 @@ public class FlatMenuUI @Override protected PropertyChangeListener createPropertyChangeListener( JComponent c ) { - return FlatStylingSupport.createPropertyChangeListener( c, this::applyStyle, super.createPropertyChangeListener( c ) ); + return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) ); + } + + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "Menu" ) ); } /** @since 2 */ 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 56438e23..69c93889 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 @@ -162,6 +162,12 @@ public class FlatPasswordFieldUI } } + /** @since 2 */ + @Override + String getStyleType() { + return "PasswordField"; + } + /** @since 2 */ @Override protected Object applyStyleProperty( String key, Object value ) { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuSeparatorUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuSeparatorUI.java index 136983f9..c0837476 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuSeparatorUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuSeparatorUI.java @@ -53,4 +53,10 @@ public class FlatPopupMenuSeparatorUI protected String getPropertyPrefix() { return "PopupMenuSeparator"; } + + /** @since 2 */ + @Override + String getStyleType() { + return "PopupMenuSeparator"; + } } 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 78d348ed..1b7c1b12 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 @@ -22,7 +22,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JComponent; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicPopupMenuUI; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; /** @@ -53,7 +52,7 @@ public class FlatPopupMenuUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -68,18 +67,23 @@ public class FlatPopupMenuUI protected void installListeners() { super.installListeners(); - propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( popupMenu, this::applyStyle, null ); - popupMenu.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( popupMenu, this::installStyle, null ); + popupMenu.addPropertyChangeListener( propertyChangeListener ); } @Override protected void uninstallListeners() { super.uninstallListeners(); - popupMenu.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + popupMenu.removePropertyChangeListener( propertyChangeListener ); propertyChangeListener = null; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( popupMenu, "PopupMenu" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 bfae831a..9af3a538 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 @@ -78,7 +78,7 @@ public class FlatProgressBarUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( progressBar ) ); + installStyle(); } @Override @@ -112,7 +112,8 @@ public class FlatProgressBarUI break; case STYLE: - applyStyle( e.getNewValue() ); + case STYLE_CLASS: + installStyle(); progressBar.revalidate(); progressBar.repaint(); break; @@ -129,6 +130,11 @@ public class FlatProgressBarUI propertyChangeListener = null; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( progressBar, "ProgressBar" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 0309ae13..5cab968e 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 @@ -72,7 +72,7 @@ public class FlatRadioButtonMenuItemUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( menuItem ) ); + installStyle(); } @Override @@ -98,7 +98,12 @@ public class FlatRadioButtonMenuItemUI @Override protected PropertyChangeListener createPropertyChangeListener( JComponent c ) { - return FlatStylingSupport.createPropertyChangeListener( c, this::applyStyle, super.createPropertyChangeListener( c ) ); + return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) ); + } + + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "RadioButtonMenuItem" ) ); } /** @since 2 */ 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 fbe719b2..75be18d9 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 @@ -90,7 +90,7 @@ public class FlatRadioButtonUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( (AbstractButton) c, FlatStylingSupport.getStyle( c ) ); + installStyle( (AbstractButton) c ); } @Override @@ -134,19 +134,29 @@ public class FlatRadioButtonUI protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) { switch( e.getPropertyName() ) { case FlatClientProperties.STYLE: - Object style = e.getNewValue(); - if( style != null && shared ) { + case FlatClientProperties.STYLE_CLASS: + if( shared && FlatStylingSupport.hasStyleProperty( b ) ) { // unshare component UI if necessary // updateUI() invokes applyStyle() from installUI() b.updateUI(); } else - applyStyle( b, style ); + installStyle( b ); b.revalidate(); b.repaint(); break; } } + /** @since 2 */ + protected void installStyle( AbstractButton b ) { + applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) ); + } + + /** @since 2 */ + String getStyleType() { + return "RadioButton"; + } + /** @since 2 */ protected void applyStyle( AbstractButton b, Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, 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 7e6f23d0..f2f32e40 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 @@ -115,7 +115,7 @@ public class FlatScrollBarUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -199,7 +199,8 @@ public class FlatScrollBarUI break; case FlatClientProperties.STYLE: - applyStyle( e.getNewValue() ); + case FlatClientProperties.STYLE_CLASS: + installStyle(); scrollbar.revalidate(); scrollbar.repaint(); break; @@ -220,6 +221,11 @@ public class FlatScrollBarUI }; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( scrollbar, "ScrollBar" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 c7f65b65..8adb6c6a 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 @@ -87,7 +87,7 @@ public class FlatScrollPaneUI int focusWidth = UIManager.getInt( "Component.focusWidth" ); LookAndFeel.installProperty( c, "opaque", focusWidth == 0 ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); MigLayoutVisualPadding.install( scrollpane ); } @@ -287,7 +287,8 @@ public class FlatScrollPaneUI break; case FlatClientProperties.STYLE: - applyStyle( e.getNewValue() ); + case FlatClientProperties.STYLE_CLASS: + installStyle(); scrollpane.revalidate(); scrollpane.repaint(); break; @@ -301,6 +302,11 @@ public class FlatScrollPaneUI return handler; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( scrollpane, "ScrollPane" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 ebcdfc14..b002b0e5 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 @@ -28,7 +28,6 @@ import javax.swing.JSeparator; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicSeparatorUI; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; @@ -80,7 +79,7 @@ public class FlatSeparatorUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( (JSeparator) c, FlatStylingSupport.getStyle( c ) ); + installStyle( (JSeparator) c ); } @Override @@ -110,29 +109,39 @@ public class FlatSeparatorUI super.installListeners( s ); propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( - s, style -> applyStyle( s, this, style ), null ); - s.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + s, () -> stylePropertyChange( s ), null ); + s.addPropertyChangeListener( propertyChangeListener ); } @Override protected void uninstallListeners( JSeparator s ) { super.uninstallListeners( s ); - s.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + s.removePropertyChangeListener( propertyChangeListener ); propertyChangeListener = null; } - private static void applyStyle( JSeparator s, FlatSeparatorUI ui, Object style ) { - if( style != null && ui.shared ) { + private void stylePropertyChange( JSeparator s ) { + if( shared && FlatStylingSupport.hasStyleProperty( s ) ) { // unshare component UI if necessary // updateUI() invokes applyStyle() from installUI() s.updateUI(); } else - ui.applyStyle( s, style ); + installStyle( s ); s.revalidate(); s.repaint(); } + /** @since 2 */ + protected void installStyle( JSeparator s ) { + applyStyle( s, FlatStylingSupport.getResolvedStyle( s, getStyleType() ) ); + } + + /** @since 2 */ + String getStyleType() { + return "Separator"; + } + /** @since 2 */ protected void applyStyle( JSeparator s, Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, 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 79c09caa..bb65102b 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 @@ -121,7 +121,7 @@ public class FlatSliderUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( slider ) ); + installStyle(); } @Override @@ -188,10 +188,15 @@ public class FlatSliderUI @Override protected PropertyChangeListener createPropertyChangeListener( JSlider slider ) { - return FlatStylingSupport.createPropertyChangeListener( slider, this::applyStyle, + return FlatStylingSupport.createPropertyChangeListener( slider, this::installStyle, super.createPropertyChangeListener( slider ) ); } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( slider, "Slider" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 a0f87b5d..8819b32a 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 @@ -114,7 +114,7 @@ public class FlatSpinnerUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( spinner ) ); + installStyle(); } @Override @@ -190,6 +190,11 @@ public class FlatSpinnerUI return handler; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( spinner, "Spinner" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); @@ -530,7 +535,8 @@ public class FlatSpinnerUI break; case FlatClientProperties.STYLE: - applyStyle( e.getNewValue() ); + case FlatClientProperties.STYLE_CLASS: + installStyle(); spinner.revalidate(); spinner.repaint(); break; 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 667cca3b..6d537a72 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 @@ -34,7 +34,6 @@ import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicSplitPaneDivider; import javax.swing.plaf.basic.BasicSplitPaneUI; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException; @@ -90,7 +89,7 @@ public class FlatSplitPaneUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( splitPane ) ); + installStyle(); } @Override @@ -121,15 +120,15 @@ public class FlatSplitPaneUI protected void installListeners() { super.installListeners(); - propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( splitPane, this::applyStyle, null ); - splitPane.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( splitPane, this::installStyle, null ); + splitPane.addPropertyChangeListener( propertyChangeListener ); } @Override protected void uninstallListeners() { super.uninstallListeners(); - splitPane.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + splitPane.removePropertyChangeListener( propertyChangeListener ); propertyChangeListener = null; } @@ -138,6 +137,11 @@ public class FlatSplitPaneUI return new FlatSplitPaneDivider( this ); } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( splitPane, "SplitPane" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 6afeb8d8..49ab18e3 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 @@ -26,10 +26,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiFunction; -import java.util.function.Consumer; import java.util.function.Predicate; import javax.swing.Icon; import javax.swing.JComponent; @@ -73,6 +73,150 @@ public class FlatStylingSupport Map> getStyleableInfos(); } + + /** + * Returns the style specified in client property {@link FlatClientProperties#STYLE}. + */ + public static Object getStyle( JComponent c ) { + return c.getClientProperty( FlatClientProperties.STYLE ); + } + + /** + * Returns the style class(es) specified in client property {@link FlatClientProperties#STYLE_CLASS}. + */ + public static Object getStyleClass( JComponent c ) { + return c.getClientProperty( FlatClientProperties.STYLE_CLASS ); + } + + static boolean hasStyleProperty( JComponent c ) { + return getStyle( c ) != null || getStyleClass( c ) != null; + } + + public static Object getResolvedStyle( JComponent c, String type ) { + Object style = getStyle( c ); + Object styleClass = getStyleClass( c ); + Object styleForClasses = getStyleForClasses( styleClass, type ); + return joinStyles( styleForClasses, style ); + } + + /** + * Returns the styles for the given style class(es) and the given type. + *

+ * The style rules must be defined in UI defaults either as strings (in CSS syntax) + * or as {@link java.util.Map}<String, Object> (with binary values). + * The key must be in syntax: {@code [style]type.styleClass}, where the type is optional. + * E.g. in FlatLaf properties file: + *

{@code
+	 * [style]Button.primary = borderColor: #08f; background: #08f; foreground: #fff
+	 * [style].secondary = borderColor: #0f8; background: #0f8
+	 * }
+ * or in Java code: + *
{@code
+	 * UIManager.put( "[style]Button.primary", "borderColor: #08f; background: #08f; foreground: #fff" );
+	 * UIManager.put( "[style].secondary", "borderColor: #0f8; background: #0f8" );
+	 * }
+ * The rule "Button.primary" can be applied to buttons only. + * The rule ".secondary" can be applied to any component. + *

+ * To have similar behaviour as in CSS, this method first gets the rule without type, + * then the rule with type and concatenates both rules. + * E.g. invoking this method with parameters styleClass="foo" and type="Button" does following: + *

{@code
+	 * return joinStyles(
+	 *     UIManager.get( "[style].foo" ),
+	 *     UIManager.get( "[style]Button.foo" ) );
+	 * }
+ * + * @param styleClass the style class(es) either as string (single class) + * or as {@code String[]} or {@link java.util.List}<String> (multiple classes) + * @param type the type of the component + * @return the styles + */ + public static Object getStyleForClasses( Object styleClass, String type ) { + if( styleClass == null ) + return null; + + if( styleClass instanceof String ) + return getStyleForClass( (String) styleClass, type ); + else if( styleClass instanceof String[] ) { + Object style = null; + for( String cls : (String[]) styleClass ) + style = joinStyles( style, getStyleForClass( cls, type ) ); + return style; + } else if( styleClass instanceof List ) { + Object style = null; + for( Object cls : (List) styleClass ) + style = joinStyles( style, getStyleForClass( (String) cls, type ) ); + return style; + } else + return null; + } + + private static Object getStyleForClass( String styleClass, String type ) { + return joinStyles( + UIManager.get( "[style]." + styleClass ), + UIManager.get( "[style]" + type + '.' + styleClass ) ); + } + + /** + * Joins two styles. They can be either strings (in CSS syntax) + * or {@link java.util.Map}<String, Object> (with binary values). + *

+ * If both styles are strings, then a joined string is returned. + * If both styles are maps, then a joined map is returned. + * If one style is a map and the other style a string, then the string + * is parsed (using {@link #parse(String)}) to a map and a joined map is returned. + * + * @param style1 first style as string or map, or {@code null} + * @param style2 second style as string or map, or {@code null} + * @return new joined style + */ + @SuppressWarnings( "unchecked" ) + public static Object joinStyles( Object style1, Object style2 ) { + if( style1 == null ) + return style2; + if( style2 == null ) + return style1; + + // join two strings + if( style1 instanceof String && style2 instanceof String ) + return style1 + "; " + style2; + + // convert first style to map + Map map1 = (style1 instanceof String) + ? parse( (String) style1 ) + : (Map) style1; + if( map1 == null ) + return style2; + + // convert second style to map + Map map2 = (style2 instanceof String) + ? parse( (String) style2 ) + : (Map) style2; + if( map2 == null ) + return style1; + + // join two maps + Map map = new HashMap<>( map1 ); + map.putAll( map2 ); + return map; + } + + /** + * Concatenates two styles in CSS syntax. + * + * @param style1 first style, or {@code null} + * @param style2 second style, or {@code null} + * @return concatenation of the two styles separated by a semicolon + */ + public static String concatStyles( String style1, String style2 ) { + if( style1 == null ) + return style2; + if( style2 == null ) + return style1; + return style1 + "; " + style2; + } + /** * Parses styles in CSS syntax ("key1: value1; key2: value2; ..."), * converts the value strings into binary and invokes the given function @@ -408,21 +552,20 @@ public class FlatStylingSupport } } - public static Object getStyle( JComponent c ) { - return c.getClientProperty( FlatClientProperties.STYLE ); - } - static PropertyChangeListener createPropertyChangeListener( JComponent c, - Consumer applyStyle, PropertyChangeListener superListener ) + Runnable installStyle, PropertyChangeListener superListener ) { return e -> { if( superListener != null ) superListener.propertyChange( e ); - if( FlatClientProperties.STYLE.equals( e.getPropertyName() ) ) { - applyStyle.accept( e.getNewValue() ); - c.revalidate(); - c.repaint(); + switch( e.getPropertyName() ) { + case FlatClientProperties.STYLE: + case FlatClientProperties.STYLE_CLASS: + installStyle.run(); + c.revalidate(); + c.repaint(); + break; } }; } 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 f310f997..67d900be 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 @@ -269,7 +269,7 @@ public class FlatTabbedPaneUI super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -572,6 +572,11 @@ public class FlatTabbedPaneUI return new FlatScrollableTabButton( direction ); } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( tabPane, "TabbedPane" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); @@ -2439,7 +2444,8 @@ public class FlatTabbedPaneUI break; case STYLE: - applyStyle( e.getNewValue() ); + case STYLE_CLASS: + installStyle(); tabPane.revalidate(); tabPane.repaint(); break; 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 f8540966..0c0904b5 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 @@ -41,7 +41,6 @@ import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicTableHeaderUI; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumnModel; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.util.UIScale; @@ -104,7 +103,7 @@ public class FlatTableHeaderUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -129,18 +128,23 @@ public class FlatTableHeaderUI protected void installListeners() { super.installListeners(); - propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( header, this::applyStyle, null ); - header.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( header, this::installStyle, null ); + header.addPropertyChangeListener( propertyChangeListener ); } @Override protected void uninstallListeners() { super.uninstallListeners(); - header.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + header.removePropertyChangeListener( propertyChangeListener ); propertyChangeListener = null; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( header, "TableHeader" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 86bc82a0..b3df21f3 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 @@ -126,7 +126,7 @@ public class FlatTableUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -197,7 +197,8 @@ public class FlatTableUI break; case FlatClientProperties.STYLE: - applyStyle( e.getNewValue() ); + case FlatClientProperties.STYLE_CLASS: + installStyle(); table.revalidate(); table.repaint(); break; @@ -235,6 +236,11 @@ public class FlatTableUI }; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( table, "Table" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { Color oldSelectionBackground = selectionBackground; 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 dff2f9d1..244757e3 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 @@ -86,7 +86,7 @@ public class FlatTextAreaUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -143,7 +143,12 @@ public class FlatTextAreaUI updateBackground(); super.propertyChange( e ); - FlatEditorPaneUI.propertyChange( getComponent(), e, this::applyStyle ); + FlatEditorPaneUI.propertyChange( getComponent(), e, this::installStyle ); + } + + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "TextArea" ) ); } /** @since 2 */ 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 51297da0..2e676135 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 @@ -114,7 +114,7 @@ public class FlatTextFieldUI leadingIcon = clientProperty( c, TEXT_FIELD_LEADING_ICON, null, Icon.class ); trailingIcon = clientProperty( c, TEXT_FIELD_TRAILING_ICON, null, Icon.class ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -209,7 +209,8 @@ public class FlatTextFieldUI break; case STYLE: - applyStyle( e.getNewValue() ); + case STYLE_CLASS: + installStyle(); c.revalidate(); c.repaint(); break; @@ -226,6 +227,16 @@ public class FlatTextFieldUI } } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), getStyleType() ) ); + } + + /** @since 2 */ + String getStyleType() { + return "TextField"; + } + /** @since 2 */ protected void applyStyle( Object style ) { oldDisabledBackground = disabledBackground; 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 de5b870c..5aa3b6a1 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 @@ -87,7 +87,7 @@ public class FlatTextPaneUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -151,7 +151,12 @@ public class FlatTextPaneUI updateBackground(); super.propertyChange( e ); - FlatEditorPaneUI.propertyChange( getComponent(), e, this::applyStyle ); + FlatEditorPaneUI.propertyChange( getComponent(), e, this::installStyle ); + } + + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "TextPane" ) ); } /** @since 2 */ diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java index a029e740..89e1492f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatToggleButtonUI.java @@ -96,6 +96,11 @@ public class FlatToggleButtonUI super( shared ); } + @Override + String getStyleType() { + return "ToggleButton"; + } + @Override protected String getPropertyPrefix() { return "ToggleButton."; 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 0978cc99..865fe3a2 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 @@ -31,7 +31,6 @@ import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicToolBarSeparatorUI; -import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; @@ -74,7 +73,7 @@ public class FlatToolBarSeparatorUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle( (JSeparator) c ); } @Override @@ -106,29 +105,34 @@ public class FlatToolBarSeparatorUI super.installListeners( s ); propertyChangeListener = FlatStylingSupport.createPropertyChangeListener( - s, style -> applyStyle( s, this, style ), null ); - s.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + s, () -> stylePropertyChange( s ), null ); + s.addPropertyChangeListener( propertyChangeListener ); } @Override protected void uninstallListeners( JSeparator s ) { super.uninstallListeners( s ); - s.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + s.removePropertyChangeListener( propertyChangeListener ); propertyChangeListener = null; } - private static void applyStyle( JSeparator s, FlatToolBarSeparatorUI ui, Object style ) { - if( style != null && ui.shared ) { + private void stylePropertyChange( JSeparator s ) { + if( shared && FlatStylingSupport.hasStyleProperty( s ) ) { // unshare component UI if necessary // updateUI() invokes applyStyle() from installUI() s.updateUI(); } else - ui.applyStyle( style ); + installStyle( s ); s.revalidate(); s.repaint(); } + /** @since 2 */ + protected void installStyle( JSeparator s ) { + applyStyle( FlatStylingSupport.getResolvedStyle( s, "ToolBarSeparator" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); 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 f863e6c4..291bd0f4 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 @@ -83,7 +83,7 @@ public class FlatToolBarUI if( !focusableButtons ) setButtonsFocusable( false ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -133,7 +133,12 @@ public class FlatToolBarUI @Override protected PropertyChangeListener createPropertyListener() { - return FlatStylingSupport.createPropertyChangeListener( toolBar, this::applyStyle, super.createPropertyListener() ); + return FlatStylingSupport.createPropertyChangeListener( toolBar, this::installStyle, super.createPropertyListener() ); + } + + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( toolBar, "ToolBar" ) ); } /** @since 2 */ 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 68d9b842..531b732e 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 @@ -156,7 +156,7 @@ public class FlatTreeUI public void installUI( JComponent c ) { super.installUI( c ); - applyStyle( FlatStylingSupport.getStyle( c ) ); + installStyle(); } @Override @@ -271,7 +271,8 @@ public class FlatTreeUI break; case STYLE: - applyStyle( e.getNewValue() ); + case STYLE_CLASS: + installStyle(); tree.revalidate(); tree.repaint(); break; @@ -309,6 +310,11 @@ public class FlatTreeUI return bounds; } + /** @since 2 */ + protected void installStyle() { + applyStyle( FlatStylingSupport.getResolvedStyle( tree, "Tree" ) ); + } + /** @since 2 */ protected void applyStyle( Object style ) { oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java index 795fe2c7..fc3777a7 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java @@ -370,14 +370,16 @@ public class FlatUIUtils *
  • an (optional) component border *
  • the (optional) component background * + *

    + * * Each part is painted only if the corresponding part color is not {@code null}. * The parts are painted in this order: - *

    *

      *
    1. background *
    2. focus border *
    3. border *
    + *

    * * Background: * The bounds of the filled round rectangle are @@ -939,7 +941,7 @@ debug*/ * with other components. This is only possible if it does not have styles. */ public static boolean canUseSharedUI( JComponent c ) { - return FlatStylingSupport.getStyle( c ) == null; + return !FlatStylingSupport.hasStyleProperty( c ); } //---- class RepaintFocusListener ----------------------------------------- diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/MigLayoutVisualPadding.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/MigLayoutVisualPadding.java index 7df37989..89389ab9 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/MigLayoutVisualPadding.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/MigLayoutVisualPadding.java @@ -81,7 +81,7 @@ public class MigLayoutVisualPadding return new Insets( focusWidth, focusWidth, focusWidth, focusWidth ); } else return null; - }, "border", FlatClientProperties.STYLE ); + }, "border", FlatClientProperties.STYLE, FlatClientProperties.STYLE_CLASS ); } /** @@ -100,7 +100,7 @@ public class MigLayoutVisualPadding c.addPropertyChangeListener( (FlatMigListener) e -> { String propertyName = e.getPropertyName(); for( String name : propertyNames ) { - if( name == propertyName ) { + if( name.equals( propertyName ) ) { setVisualPadding( c, getPaddingFunction.apply( c ) ); break; } diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java new file mode 100644 index 00000000..d96036f1 --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java @@ -0,0 +1,448 @@ +/* + * 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 java.awt.Color; +import java.awt.Dimension; +import javax.swing.*; +import javax.swing.table.JTableHeader; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.FlatSystemProperties; + +/** + * @author Karl Tauber + */ +public class TestFlatStyleClasses +{ + private static final String BUTTON_PRIMARY = "borderColor: #08f; background: #08f; foreground: #fff"; + private static final String SECONDARY = "borderColor: #0f8; background: #0f8"; + private static final String TOGGLE_BUTTON_SECONDARY = "selectedBackground: #f00"; + private static final String BACKGROUND = "background: #f0f"; + + @BeforeAll + static void setup() { + System.setProperty( FlatSystemProperties.UI_SCALE_ENABLED, "false" ); + TestUtils.setup( false ); + + UIManager.put( "[style]Button.primary", BUTTON_PRIMARY ); + UIManager.put( "[style].secondary", SECONDARY ); + UIManager.put( "[style]ToggleButton.secondary", TOGGLE_BUTTON_SECONDARY ); + UIManager.put( "[style].test", BACKGROUND ); + + UIManager.put( "[style]Button.test", "foreground: #000001" ); + UIManager.put( "[style]CheckBox.test", "foreground: #000002" ); + UIManager.put( "[style]ComboBox.test", "foreground: #000003" ); + UIManager.put( "[style]EditorPane.test", "foreground: #000004" ); + UIManager.put( "[style]FormattedTextField.test", "foreground: #000005" ); + UIManager.put( "[style]InternalFrame.test", "foreground: #000006" ); + UIManager.put( "[style]Label.test", "foreground: #000007" ); + UIManager.put( "[style]List.test", "foreground: #000008" ); + UIManager.put( "[style]MenuBar.test", "foreground: #000009" ); + UIManager.put( "[style]Menu.test", "foreground: #000010" ); + UIManager.put( "[style]MenuItem.test", "foreground: #000011" ); + UIManager.put( "[style]CheckBoxMenuItem.test", "foreground: #000012" ); + UIManager.put( "[style]RadioButtonMenuItem.test", "foreground: #000013" ); + UIManager.put( "[style]PasswordField.test", "foreground: #000014" ); + UIManager.put( "[style]PopupMenu.test", "foreground: #000015" ); + UIManager.put( "[style]PopupMenuSeparator.test", "foreground: #000016" ); + UIManager.put( "[style]ProgressBar.test", "foreground: #000017" ); + UIManager.put( "[style]RadioButton.test", "foreground: #000018" ); + UIManager.put( "[style]ScrollBar.test", "foreground: #000019" ); + UIManager.put( "[style]ScrollPane.test", "foreground: #000020" ); + UIManager.put( "[style]Separator.test", "foreground: #000021" ); + UIManager.put( "[style]Slider.test", "foreground: #000022" ); + UIManager.put( "[style]Spinner.test", "foreground: #000023" ); + UIManager.put( "[style]SplitPane.test", "foreground: #000024" ); + UIManager.put( "[style]TabbedPane.test", "foreground: #000025" ); + UIManager.put( "[style]Table.test", "foreground: #000026" ); + UIManager.put( "[style]TableHeader.test", "foreground: #000027" ); + UIManager.put( "[style]TextArea.test", "foreground: #000028" ); + UIManager.put( "[style]TextField.test", "foreground: #000029" ); + UIManager.put( "[style]TextPane.test", "foreground: #000030" ); + UIManager.put( "[style]ToggleButton.test", "foreground: #000031" ); + UIManager.put( "[style]ToolBar.test", "foreground: #000032" ); + UIManager.put( "[style]Tree.test", "foreground: #000033" ); + + // for shared UIs + UIManager.put( "[style]Button.test2", "foreground: #000100" ); + UIManager.put( "[style]CheckBox.test2", "foreground: #000200" ); + UIManager.put( "[style]Label.test2", "foreground: #000700" ); + UIManager.put( "[style]PopupMenuSeparator.test2", "foreground: #001600" ); + UIManager.put( "[style]RadioButton.test2", "foreground: #001800" ); + UIManager.put( "[style]Separator.test2", "foreground: #002100" ); + UIManager.put( "[style]ToggleButton.test2", "foreground: #003100" ); + + // JToolBar.Separator + UIManager.put( "[style]ToolBarSeparator.toolbar-separator-test", "separatorWidth: 21" ); + UIManager.put( "[style]ToolBarSeparator.toolbar-separator-test2", "separatorWidth: 31" ); + } + + @AfterAll + static void cleanup() { + TestUtils.cleanup(); + System.clearProperty( FlatSystemProperties.UI_SCALE_ENABLED ); + } + + @Test + void styleForClass() { + assertEquals( null, FlatStylingSupport.getStyleForClasses( "foo", "Button" ) ); + + assertEquals( BUTTON_PRIMARY, FlatStylingSupport.getStyleForClasses( "primary", "Button" ) ); + assertEquals( SECONDARY, FlatStylingSupport.getStyleForClasses( "secondary", "Button" ) ); + + assertEquals( + FlatStylingSupport.concatStyles( SECONDARY, TOGGLE_BUTTON_SECONDARY ), + FlatStylingSupport.getStyleForClasses( "secondary", "ToggleButton" ) ); + + assertEquals( + FlatStylingSupport.concatStyles( BUTTON_PRIMARY, SECONDARY ), + FlatStylingSupport.getStyleForClasses( new String[] { "primary", "secondary" }, "Button" ) ); + assertEquals( + FlatStylingSupport.concatStyles( SECONDARY, BUTTON_PRIMARY ), + FlatStylingSupport.getStyleForClasses( new String[] { "secondary", "primary" }, "Button" ) ); + } + + @Test + void apply1() { + JButton c = new JButton(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "primary" ); + + assertEquals( new Color( 0x0088ff ), c.getBackground() ); + assertEquals( Color.white, c.getForeground() ); + } + + @Test + void apply2() { + JButton c = new JButton(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, new String[] { "primary", "secondary" } ); + + assertEquals( new Color( 0x00ff88 ), c.getBackground() ); + assertEquals( Color.white, c.getForeground() ); + } + + @Test + void apply3() { + JButton c = new JButton(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, new String[] { "secondary", "primary" } ); + + assertEquals( new Color( 0x0088ff ), c.getBackground() ); + assertEquals( Color.white, c.getForeground() ); + } + + //---- components --------------------------------------------------------- + + @Test + void button() { + JButton c = new JButton(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000001 ), c.getForeground() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test2" ); + assertEquals( new Color( 0x000100 ), c.getForeground() ); + } + + @Test + void checkBox() { + JCheckBox c = new JCheckBox(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000002 ), c.getForeground() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test2" ); + assertEquals( new Color( 0x000200 ), c.getForeground() ); + } + + @Test + void comboBox() { + JComboBox c = new JComboBox<>(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000003 ), c.getForeground() ); + } + + @Test + void editorPane() { + JEditorPane c = new JEditorPane(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000004 ), c.getForeground() ); + } + + @Test + void formattedTextField() { + JFormattedTextField c = new JFormattedTextField(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000005 ), c.getForeground() ); + } + + @Test + void internalFrame() { + JInternalFrame c = new JInternalFrame(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000006 ), c.getForeground() ); + } + + @Test + void label() { + JLabel c = new JLabel(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000007 ), c.getForeground() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test2" ); + assertEquals( new Color( 0x000700 ), c.getForeground() ); + } + + @Test + void list() { + JList c = new JList<>(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000008 ), c.getForeground() ); + } + + @Test + void menuBar() { + JMenuBar c = new JMenuBar(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000009 ), c.getForeground() ); + } + + @Test + void menu() { + JMenu c = new JMenu(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000010 ), c.getForeground() ); + } + + @Test + void menuItem() { + JMenuItem c = new JMenuItem(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000011 ), c.getForeground() ); + } + + @Test + void checkBoxMenuItem() { + JCheckBoxMenuItem c = new JCheckBoxMenuItem(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000012 ), c.getForeground() ); + } + + @Test + void radioButtonMenuItem() { + JRadioButtonMenuItem c = new JRadioButtonMenuItem(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000013 ), c.getForeground() ); + } + + @Test + void passwordField() { + JPasswordField c = new JPasswordField(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000014 ), c.getForeground() ); + } + + @Test + void popupMenu() { + JPopupMenu c = new JPopupMenu(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000015 ), c.getForeground() ); + } + + @Test + void popupMenuSeparator() { + JPopupMenu.Separator c = new JPopupMenu.Separator(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000016 ), c.getForeground() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test2" ); + assertEquals( new Color( 0x001600 ), c.getForeground() ); + } + + @Test + void progressBar() { + JProgressBar c = new JProgressBar(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000017 ), c.getForeground() ); + } + + @Test + void radioButton() { + JRadioButton c = new JRadioButton(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000018 ), c.getForeground() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test2" ); + assertEquals( new Color( 0x001800 ), c.getForeground() ); + } + + @Test + void scrollBar() { + JScrollBar c = new JScrollBar(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000019 ), c.getForeground() ); + } + + @Test + void scrollPane() { + JScrollPane c = new JScrollPane(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000020 ), c.getForeground() ); + } + + @Test + void separator() { + JSeparator c = new JSeparator(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000021 ), c.getForeground() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test2" ); + assertEquals( new Color( 0x002100 ), c.getForeground() ); + } + + @Test + void slider() { + JSlider c = new JSlider(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000022 ), c.getForeground() ); + } + + @Test + void spinner() { + JSpinner c = new JSpinner(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000023 ), c.getForeground() ); + } + + @Test + void splitPane() { + JSplitPane c = new JSplitPane(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000024 ), c.getForeground() ); + } + + @Test + void tabbedPane() { + JTabbedPane c = new JTabbedPane(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000025 ), c.getForeground() ); + } + + @Test + void table() { + JTable c = new JTable(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000026 ), c.getForeground() ); + } + + @Test + void tableHeader() { + JTableHeader c = new JTableHeader(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000027 ), c.getForeground() ); + } + + @Test + void textArea() { + JTextArea c = new JTextArea(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000028 ), c.getForeground() ); + } + + @Test + void textField() { + JTextField c = new JTextField(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000029 ), c.getForeground() ); + } + + @Test + void textPane() { + JTextPane c = new JTextPane(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000030 ), c.getForeground() ); + } + + @Test + void toggleButton() { + JToggleButton c = new JToggleButton(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000031 ), c.getForeground() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test2" ); + assertEquals( new Color( 0x003100 ), c.getForeground() ); + } + + @Test + void toolBar() { + JToolBar c = new JToolBar(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000032 ), c.getForeground() ); + } + + @Test + void toolBarSeparator() { + JToolBar.Separator c = new JToolBar.Separator(); + assertEquals( new Dimension( 0, 7 ), c.getPreferredSize() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "toolbar-separator-test" ); + assertEquals( new Dimension( 0, 21 ), c.getPreferredSize() ); + + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "toolbar-separator-test2" ); + assertEquals( new Dimension( 0, 31 ), c.getPreferredSize() ); + } + + @Test + void tree() { + JTree c = new JTree(); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" ); + assertEquals( Color.magenta, c.getBackground() ); + assertEquals( new Color( 0x000033 ), c.getForeground() ); + } +} From 1c067d028460e8457a92a0061f76b0b42a664ed5 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sat, 25 Sep 2021 18:32:11 +0200 Subject: [PATCH 2/5] behaviour --> behavior --- .../src/main/java/com/formdev/flatlaf/FlatClientProperties.java | 2 +- .../main/java/com/formdev/flatlaf/ui/FlatStylingSupport.java | 2 +- .../src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java index f4b4e03d..e6aa98f0 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -165,7 +165,7 @@ public interface FlatClientProperties * The rule "Button.primary" can be applied to buttons only. * The rule ".secondary" can be applied to any component. *

    - * To have similar behaviour as in CSS, first the rule without type is applied, + * To have similar behavior as in CSS, first the rule without type is applied, * then the rule with type. * E.g. setting style class to "foo" on a {@code JButton} uses rules * from UI default keys "[style].foo" and "[style]Button.foo". 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 49ab18e3..58774c0c 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 @@ -118,7 +118,7 @@ public class FlatStylingSupport * The rule "Button.primary" can be applied to buttons only. * The rule ".secondary" can be applied to any component. *

    - * To have similar behaviour as in CSS, this method first gets the rule without type, + * To have similar behavior as in CSS, this method first gets the rule without type, * then the rule with type and concatenates both rules. * E.g. invoking this method with parameters styleClass="foo" and type="Button" does following: *

    {@code
    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 2e676135..8dc04234 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
    @@ -320,7 +320,7 @@ debug*/
     		//   - not opaque and
     		//   - border is not a flat border and
     		//   - opaque was explicitly set (to false)
    -		// (same behaviour as in AquaTextFieldUI)
    +		// (same behavior as in AquaTextFieldUI)
     		if( !c.isOpaque() && FlatUIUtils.getOutsideFlatBorder( c ) == null && FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) )
     			return;
     
    
    From 3d8c535ffab323aa244c6b49bfe1ec9ed365742b Mon Sep 17 00:00:00 2001
    From: Karl Tauber 
    Date: Sat, 25 Sep 2021 19:34:46 +0200
    Subject: [PATCH 3/5] Styling: catch runtime exceptions while applying styles
     (and log them) to avoid that wrong/invalid styles could result in "damaged"
     UI
    
    ---
     .../src/main/java/com/formdev/flatlaf/ui/FlatButtonUI.java | 7 ++++++-
     .../com/formdev/flatlaf/ui/FlatCheckBoxMenuItemUI.java     | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatComboBoxUI.java   | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatEditorPaneUI.java | 7 ++++++-
     .../java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java   | 7 ++++++-
     .../src/main/java/com/formdev/flatlaf/ui/FlatLabelUI.java  | 7 ++++++-
     .../src/main/java/com/formdev/flatlaf/ui/FlatListUI.java   | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java    | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatMenuItemUI.java   | 7 ++++++-
     .../src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java   | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java  | 7 ++++++-
     .../java/com/formdev/flatlaf/ui/FlatProgressBarUI.java     | 7 ++++++-
     .../com/formdev/flatlaf/ui/FlatRadioButtonMenuItemUI.java  | 7 ++++++-
     .../java/com/formdev/flatlaf/ui/FlatRadioButtonUI.java     | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatScrollBarUI.java  | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatSeparatorUI.java  | 7 ++++++-
     .../src/main/java/com/formdev/flatlaf/ui/FlatSliderUI.java | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatSpinnerUI.java    | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatSplitPaneUI.java  | 7 ++++++-
     .../java/com/formdev/flatlaf/ui/FlatStylingSupport.java    | 4 +++-
     .../main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java | 7 ++++++-
     .../java/com/formdev/flatlaf/ui/FlatTableHeaderUI.java     | 7 ++++++-
     .../src/main/java/com/formdev/flatlaf/ui/FlatTableUI.java  | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatTextAreaUI.java   | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java  | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatTextPaneUI.java   | 7 ++++++-
     .../com/formdev/flatlaf/ui/FlatToolBarSeparatorUI.java     | 7 ++++++-
     .../main/java/com/formdev/flatlaf/ui/FlatToolBarUI.java    | 7 ++++++-
     .../src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java   | 7 ++++++-
     30 files changed, 177 insertions(+), 30 deletions(-)
    
    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 a29c4626..79f330fe 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
    @@ -51,6 +51,7 @@ import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -270,7 +271,11 @@ public class FlatButtonUI
     
     	/** @since 2 */
     	protected void installStyle( AbstractButton b ) {
    -		applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) );
    +		try {
    +			applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 b78ca31d..8c0ab140 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,6 +28,7 @@ import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JCheckBoxMenuItem}.
    @@ -103,7 +104,11 @@ public class FlatCheckBoxMenuItemUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "CheckBoxMenuItem" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "CheckBoxMenuItem" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 25f086bf..9cb4e22e 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
    @@ -72,6 +72,7 @@ import javax.swing.plaf.basic.ComboPopup;
     import javax.swing.text.JTextComponent;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.SystemInfo;
     
     /**
    @@ -452,7 +453,11 @@ public class FlatComboBoxUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( comboBox, "ComboBox" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( comboBox, "ComboBox" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 6c9cb714..b5386c49 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
    @@ -35,6 +35,7 @@ import com.formdev.flatlaf.FlatClientProperties;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.HiDPIUtils;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
    @@ -174,7 +175,11 @@ public class FlatEditorPaneUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "EditorPane" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "EditorPane" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 32460cda..d000f57d 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
    @@ -38,6 +38,7 @@ import javax.swing.plaf.basic.BasicInternalFrameUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}.
    @@ -154,7 +155,11 @@ public class FlatInternalFrameUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( frame, "InternalFrame" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( frame, "InternalFrame" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 2c16494a..b23a90c6 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
    @@ -39,6 +39,7 @@ import com.formdev.flatlaf.FlatLaf;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.HiDPIUtils;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -133,7 +134,11 @@ public class FlatLabelUI
     
     	/** @since 2 */
     	protected void installStyle( JLabel c ) {
    -		applyStyle( c, FlatStylingSupport.getResolvedStyle( c, "Label" ) );
    +		try {
    +			applyStyle( c, FlatStylingSupport.getResolvedStyle( c, "Label" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 956c6b76..cd0ab3f5 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
    @@ -30,6 +30,7 @@ import javax.swing.plaf.basic.BasicListUI;
     import com.formdev.flatlaf.FlatClientProperties;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JList}.
    @@ -162,7 +163,11 @@ public class FlatListUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( list, "List" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( list, "List" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 a0e5280a..b2ffd44f 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
    @@ -42,6 +42,7 @@ import javax.swing.plaf.basic.BasicMenuBarUI;
     import com.formdev.flatlaf.FlatLaf;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.SystemInfo;
     
     /**
    @@ -138,7 +139,11 @@ public class FlatMenuBarUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( menuBar, "MenuBar" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( menuBar, "MenuBar" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 0b7b9516..785c220b 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
    @@ -29,6 +29,7 @@ import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicMenuItemUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JMenuItem}.
    @@ -104,7 +105,11 @@ public class FlatMenuItemUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "MenuItem" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "MenuItem" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 009c505a..37d819cb 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
    @@ -38,6 +38,7 @@ import javax.swing.plaf.MenuBarUI;
     import javax.swing.plaf.basic.BasicMenuUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JMenu}.
    @@ -150,7 +151,11 @@ public class FlatMenuUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "Menu" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "Menu" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 1b7c1b12..cb3d6169 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
    @@ -23,6 +23,7 @@ import javax.swing.JComponent;
     import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicPopupMenuUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JPopupMenu}.
    @@ -81,7 +82,11 @@ public class FlatPopupMenuUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( popupMenu, "PopupMenu" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( popupMenu, "PopupMenu" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 9af3a538..7a13421b 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
    @@ -35,6 +35,7 @@ import javax.swing.plaf.basic.BasicProgressBarUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.HiDPIUtils;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -132,7 +133,11 @@ public class FlatProgressBarUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( progressBar, "ProgressBar" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( progressBar, "ProgressBar" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 5cab968e..efb99f58 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,6 +28,7 @@ import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JRadioButtonMenuItem}.
    @@ -103,7 +104,11 @@ public class FlatRadioButtonMenuItemUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "RadioButtonMenuItem" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "RadioButtonMenuItem" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 75be18d9..409a2e97 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
    @@ -39,6 +39,7 @@ import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -149,7 +150,11 @@ public class FlatRadioButtonUI
     
     	/** @since 2 */
     	protected void installStyle( AbstractButton b ) {
    -		applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) );
    +		try {
    +			applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 f2f32e40..d05ff897 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
    @@ -39,6 +39,7 @@ import javax.swing.plaf.basic.BasicScrollBarUI;
     import com.formdev.flatlaf.FlatClientProperties;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -223,7 +224,11 @@ public class FlatScrollBarUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( scrollbar, "ScrollBar" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( scrollbar, "ScrollBar" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 8adb6c6a..4b52cd62 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
    @@ -49,6 +49,7 @@ import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicScrollPaneUI;
     import com.formdev.flatlaf.FlatClientProperties;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JScrollPane}.
    @@ -304,7 +305,11 @@ public class FlatScrollPaneUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( scrollpane, "ScrollPane" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( scrollpane, "ScrollPane" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 b002b0e5..e418c23e 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
    @@ -30,6 +30,7 @@ import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicSeparatorUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JSeparator}.
    @@ -134,7 +135,11 @@ public class FlatSeparatorUI
     
     	/** @since 2 */
     	protected void installStyle( JSeparator s ) {
    -		applyStyle( s, FlatStylingSupport.getResolvedStyle( s, getStyleType() ) );
    +		try {
    +			applyStyle( s, FlatStylingSupport.getResolvedStyle( s, getStyleType() ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 bb65102b..84f86b16 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
    @@ -42,6 +42,7 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.Graphics2DProxy;
     import com.formdev.flatlaf.util.HiDPIUtils;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -194,7 +195,11 @@ public class FlatSliderUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( slider, "Slider" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( slider, "Slider" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 8819b32a..42c815d6 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
    @@ -47,6 +47,7 @@ import javax.swing.plaf.basic.BasicSpinnerUI;
     import com.formdev.flatlaf.FlatClientProperties;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JSpinner}.
    @@ -192,7 +193,11 @@ public class FlatSpinnerUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( spinner, "Spinner" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( spinner, "Spinner" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 6d537a72..d2c5c989 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
    @@ -37,6 +37,7 @@ import javax.swing.plaf.basic.BasicSplitPaneUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -139,7 +140,11 @@ public class FlatSplitPaneUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( splitPane, "SplitPane" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( splitPane, "SplitPane" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 58774c0c..de2b9d5c 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
    @@ -506,7 +506,9 @@ public class FlatStylingSupport
     	 * @throws UnknownStyleException if object does not have a annotated field with given name
     	 * @throws IllegalArgumentException if value type does not fit to expected type
     	 */
    -	public static Object applyToAnnotatedObjectOrComponent( Object obj, Object comp, String key, Object value ) {
    +	public static Object applyToAnnotatedObjectOrComponent( Object obj, Object comp, String key, Object value )
    +		throws UnknownStyleException, IllegalArgumentException
    +	{
     		try {
     			return applyToAnnotatedObject( obj, key, value );
     		} catch( UnknownStyleException ex ) {
    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 67d900be..75afa3e0 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
    @@ -93,6 +93,7 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
     import com.formdev.flatlaf.util.Animator;
     import com.formdev.flatlaf.util.CubicBezierEasing;
     import com.formdev.flatlaf.util.JavaCompatibility;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.StringUtils;
     import com.formdev.flatlaf.util.UIScale;
     
    @@ -574,7 +575,11 @@ public class FlatTabbedPaneUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( tabPane, "TabbedPane" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( tabPane, "TabbedPane" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 0c0904b5..8be68cbf 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
    @@ -43,6 +43,7 @@ import javax.swing.table.TableCellRenderer;
     import javax.swing.table.TableColumnModel;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -142,7 +143,11 @@ public class FlatTableHeaderUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( header, "TableHeader" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( header, "TableHeader" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 b3df21f3..930b04b8 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
    @@ -41,6 +41,7 @@ import com.formdev.flatlaf.FlatClientProperties;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.Graphics2DProxy;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.SystemInfo;
     import com.formdev.flatlaf.util.UIScale;
     
    @@ -238,7 +239,11 @@ public class FlatTableUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( table, "Table" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( table, "Table" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 244757e3..569ab1ab 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
    @@ -32,6 +32,7 @@ import javax.swing.plaf.basic.BasicTextAreaUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.HiDPIUtils;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JTextArea}.
    @@ -148,7 +149,11 @@ public class FlatTextAreaUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "TextArea" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "TextArea" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 8dc04234..6814e7f8 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
    @@ -47,6 +47,7 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.HiDPIUtils;
     import com.formdev.flatlaf.util.JavaCompatibility;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JTextField}.
    @@ -229,7 +230,11 @@ public class FlatTextFieldUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), getStyleType() ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), getStyleType() ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 5aa3b6a1..7d43760b 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
    @@ -32,6 +32,7 @@ import javax.swing.plaf.basic.BasicTextPaneUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
     import com.formdev.flatlaf.util.HiDPIUtils;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JTextPane}.
    @@ -156,7 +157,11 @@ public class FlatTextPaneUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "TextPane" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "TextPane" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 865fe3a2..28e3508a 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
    @@ -33,6 +33,7 @@ import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicToolBarSeparatorUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JToolBar.Separator}.
    @@ -130,7 +131,11 @@ public class FlatToolBarSeparatorUI
     
     	/** @since 2 */
     	protected void installStyle( JSeparator s ) {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( s, "ToolBarSeparator" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( s, "ToolBarSeparator" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 291bd0f4..a2f100ac 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
    @@ -31,6 +31,7 @@ import javax.swing.plaf.ComponentUI;
     import javax.swing.plaf.basic.BasicToolBarUI;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     
     /**
      * Provides the Flat LaF UI delegate for {@link javax.swing.JToolBar}.
    @@ -138,7 +139,11 @@ public class FlatToolBarUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( toolBar, "ToolBar" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( toolBar, "ToolBar" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    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 531b732e..03c63d3b 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
    @@ -42,6 +42,7 @@ import javax.swing.tree.DefaultTreeCellRenderer;
     import javax.swing.tree.TreePath;
     import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
     import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
    +import com.formdev.flatlaf.util.LoggingFacade;
     import com.formdev.flatlaf.util.UIScale;
     
     /**
    @@ -312,7 +313,11 @@ public class FlatTreeUI
     
     	/** @since 2 */
     	protected void installStyle() {
    -		applyStyle( FlatStylingSupport.getResolvedStyle( tree, "Tree" ) );
    +		try {
    +			applyStyle( FlatStylingSupport.getResolvedStyle( tree, "Tree" ) );
    +		} catch( RuntimeException ex ) {
    +			LoggingFacade.INSTANCE.logSevere( null, ex );
    +		}
     	}
     
     	/** @since 2 */
    
    From c4b016c9c83b9456f1948dd36a0eb0faf738d974 Mon Sep 17 00:00:00 2001
    From: Karl Tauber 
    Date: Wed, 29 Sep 2021 23:49:40 +0200
    Subject: [PATCH 4/5] Styling: support specifying multiple style classes in
     single string
    
    ---
     .../formdev/flatlaf/FlatClientProperties.java |   4 +-
     .../flatlaf/ui/FlatStylingSupport.java        |   7 +-
     .../com/formdev/flatlaf/util/StringUtils.java |  41 +++-
     .../flatlaf/ui/TestFlatStyleClasses.java      |  22 +-
     .../formdev/flatlaf/util/TestStringUtils.java | 198 ++++++++++++++++++
     5 files changed, 262 insertions(+), 10 deletions(-)
     create mode 100644 flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestStringUtils.java
    
    diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java
    index e6aa98f0..542fe963 100644
    --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java
    +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java
    @@ -146,8 +146,8 @@ public interface FlatClientProperties
     	String STYLE = "FlatLaf.style";
     
     	/**
    -	 * Specifies the style class(es) of a component as String
    -	 * or as {@link java.util.List}<String>.
    +	 * Specifies the style class(es) of a component as String (single class or multiple classes separated by space characters)
    +	 * or as {@code String[]} or {@link java.util.List}<String> (multiple classes).
     	 * 

    * The style rules must be defined in UI defaults either as strings (in CSS syntax) * or as {@link java.util.Map}<String, Object> (with binary values). 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 de2b9d5c..6f21ba2b 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 @@ -127,7 +127,7 @@ public class FlatStylingSupport * UIManager.get( "[style]Button.foo" ) ); * }

    * - * @param styleClass the style class(es) either as string (single class) + * @param styleClass the style class(es) either as string (single class or multiple classes separated by space characters) * or as {@code String[]} or {@link java.util.List}<String> (multiple classes) * @param type the type of the component * @return the styles @@ -136,8 +136,11 @@ public class FlatStylingSupport if( styleClass == null ) return null; + if( styleClass instanceof String && ((String)styleClass).indexOf( ' ' ) >= 0 ) + styleClass = StringUtils.split( (String) styleClass, ' ', true, true ); + if( styleClass instanceof String ) - return getStyleForClass( (String) styleClass, type ); + return getStyleForClass( ((String)styleClass).trim(), type ); else if( styleClass instanceof String[] ) { Object style = null; for( String cls : (String[]) styleClass ) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/StringUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/StringUtils.java index df184d1e..2f952014 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/util/StringUtils.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/util/StringUtils.java @@ -17,6 +17,7 @@ package com.formdev.flatlaf.util; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -46,16 +47,50 @@ public class StringUtils } public static List split( String str, char delim ) { - ArrayList strs = new ArrayList<>(); + return split( str, delim, false, false ); + } + + /** + * Splits a string at the specified delimiter. + * If trimming is enabled, then leading and trailing whitespace characters are removed. + * If excludeEmpty is {@code true}, then only non-empty strings are returned. + * + * @since 2 + */ + public static List split( String str, char delim, boolean trim, boolean excludeEmpty ) { int delimIndex = str.indexOf( delim ); + if( delimIndex < 0 ) { + if( trim ) + str = str.trim(); + return !excludeEmpty || !str.isEmpty() + ? Collections.singletonList( str ) + : Collections.emptyList(); + } + + ArrayList strs = new ArrayList<>(); int index = 0; while( delimIndex >= 0 ) { - strs.add( str.substring( index, delimIndex ) ); + add( strs, str, index, delimIndex, trim, excludeEmpty ); index = delimIndex + 1; delimIndex = str.indexOf( delim, index ); } - strs.add( str.substring( index ) ); + add( strs, str, index, str.length(), trim, excludeEmpty ); return strs; } + + private static void add( List strs, String str, int begin, int end, boolean trim, boolean excludeEmpty ) { + if( trim ) { + // skip leading whitespace + while( begin < end && str.charAt( begin ) <= ' ' ) + begin++; + + // skip trailing whitespace + while( begin < end && str.charAt( end - 1 ) <= ' ' ) + end--; + } + + if( !excludeEmpty || end > begin ) + strs.add( str.substring( begin, end ) ); + } } diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java index d96036f1..20bb9ebe 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleClasses.java @@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui; import static org.junit.jupiter.api.Assertions.assertEquals; import java.awt.Color; import java.awt.Dimension; +import java.util.Arrays; import javax.swing.*; import javax.swing.table.JTableHeader; import org.junit.jupiter.api.AfterAll; @@ -114,10 +115,25 @@ public class TestFlatStyleClasses assertEquals( FlatStylingSupport.concatStyles( BUTTON_PRIMARY, SECONDARY ), - FlatStylingSupport.getStyleForClasses( new String[] { "primary", "secondary" }, "Button" ) ); + FlatStylingSupport.getStyleForClasses( "primary secondary", "Button" ) ); + assertEquals( + FlatStylingSupport.concatStyles( SECONDARY, BUTTON_PRIMARY ), + FlatStylingSupport.getStyleForClasses( "secondary primary", "Button" ) ); + + // String + assertEquals( + FlatStylingSupport.concatStyles( SECONDARY, BUTTON_PRIMARY ), + FlatStylingSupport.getStyleForClasses( " secondary primary bla blu ", "Button" ) ); + + // String[] assertEquals( FlatStylingSupport.concatStyles( SECONDARY, BUTTON_PRIMARY ), FlatStylingSupport.getStyleForClasses( new String[] { "secondary", "primary" }, "Button" ) ); + + // List + assertEquals( + FlatStylingSupport.concatStyles( SECONDARY, BUTTON_PRIMARY ), + FlatStylingSupport.getStyleForClasses( Arrays.asList( "secondary", "primary" ), "Button" ) ); } @Test @@ -132,7 +148,7 @@ public class TestFlatStyleClasses @Test void apply2() { JButton c = new JButton(); - c.putClientProperty( FlatClientProperties.STYLE_CLASS, new String[] { "primary", "secondary" } ); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "primary secondary" ); assertEquals( new Color( 0x00ff88 ), c.getBackground() ); assertEquals( Color.white, c.getForeground() ); @@ -141,7 +157,7 @@ public class TestFlatStyleClasses @Test void apply3() { JButton c = new JButton(); - c.putClientProperty( FlatClientProperties.STYLE_CLASS, new String[] { "secondary", "primary" } ); + c.putClientProperty( FlatClientProperties.STYLE_CLASS, "secondary primary" ); assertEquals( new Color( 0x0088ff ), c.getBackground() ); assertEquals( Color.white, c.getForeground() ); diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestStringUtils.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestStringUtils.java new file mode 100644 index 00000000..136ebbcf --- /dev/null +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/util/TestStringUtils.java @@ -0,0 +1,198 @@ +/* + * 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.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.Arrays; +import org.junit.jupiter.api.Test; + +/** + * @author Karl Tauber + */ +public class TestStringUtils +{ + @Test + void split() { + // empty + assertEquals( + Arrays.asList( "" ), + StringUtils.split( "", ',' ) ); + + // not empty + assertEquals( + Arrays.asList( "a" ), + StringUtils.split( "a", ',' ) ); + assertEquals( + Arrays.asList( "a", "b" ), + StringUtils.split( "a,b", ',' ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a,b,c", ',' ) ); + + // empty parts + assertEquals( + Arrays.asList( "", "b", "c" ), + StringUtils.split( ",b,c", ',' ) ); + assertEquals( + Arrays.asList( "a", "", "c" ), + StringUtils.split( "a,,c", ',' ) ); + assertEquals( + Arrays.asList( "a", "b", "" ), + StringUtils.split( "a,b,", ',' ) ); + + // parts with leading/trailing spaces + assertEquals( + Arrays.asList( "a", " b", " c" ), + StringUtils.split( "a, b, c", ',' ) ); + assertEquals( + Arrays.asList( " a", "b", "c " ), + StringUtils.split( " a,b,c ", ',' ) ); + assertEquals( + Arrays.asList( " a", " b ", "c " ), + StringUtils.split( " a, b ,c ", ',' ) ); + + // space delimiter + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a b c", ' ' ) ); + assertEquals( + Arrays.asList( "a", "", "", "b", "", "c" ), + StringUtils.split( "a b c", ' ' ) ); + + // new line delimiter + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a\nb\nc", '\n' ) ); + assertEquals( + Arrays.asList( "a", "", "", "b", "", "c" ), + StringUtils.split( "a\n\n\nb\n\nc", '\n' ) ); + } + + @Test + void splitTrim() { + // empty + assertEquals( + Arrays.asList( "" ), + StringUtils.split( "", ',', true, false ) ); + + // not empty + assertEquals( + Arrays.asList( "a" ), + StringUtils.split( "a", ',', true, false ) ); + assertEquals( + Arrays.asList( "a", "b" ), + StringUtils.split( "a,b", ',', true, false ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a,b,c", ',', true, false ) ); + + // empty parts + assertEquals( + Arrays.asList( "", "b", "c" ), + StringUtils.split( ",b,c", ',', true, false ) ); + assertEquals( + Arrays.asList( "a", "", "c" ), + StringUtils.split( "a,,c", ',', true, false ) ); + assertEquals( + Arrays.asList( "a", "b", "" ), + StringUtils.split( "a,b,", ',', true, false ) ); + + // parts with leading/trailing spaces + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a, b, c", ',', true, false ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( " a,b,c ", ',', true, false ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( " a, b ,c ", ',', true, false ) ); + + // space delimiter + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a b c", ' ', true, false ) ); + assertEquals( + Arrays.asList( "a", "", "", "b", "", "c" ), + StringUtils.split( "a b c", ' ', true, false ) ); + + // new line delimiter + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a\nb\nc", '\n', true, false ) ); + assertEquals( + Arrays.asList( "a", "", "", "b", "", "c" ), + StringUtils.split( "a\n\n\nb\n\nc", '\n', true, false ) ); + } + + @Test + void splitTrimAndExcludeEmpty() { + // empty + assertEquals( + Arrays.asList(), + StringUtils.split( "", ',', true, true ) ); + + // not empty + assertEquals( + Arrays.asList( "a" ), + StringUtils.split( "a", ',', true, true ) ); + assertEquals( + Arrays.asList( "a", "b" ), + StringUtils.split( "a,b", ',', true, true ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a,b,c", ',', true, true ) ); + + // empty parts + assertEquals( + Arrays.asList( "b", "c" ), + StringUtils.split( ",b,c", ',', true, true ) ); + assertEquals( + Arrays.asList( "a", "c" ), + StringUtils.split( "a,,c", ',', true, true ) ); + assertEquals( + Arrays.asList( "a", "b" ), + StringUtils.split( "a,b,", ',', true, true ) ); + + // parts with leading/trailing spaces + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a, b, c", ',', true, true ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( " a,b,c ", ',', true, true ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( " a, b ,c ", ',', true, true ) ); + + // space delimiter + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a b c", ' ', true, true ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a b c", ' ', true, true ) ); + + // new line delimiter + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a\nb\nc", '\n', true, true ) ); + assertEquals( + Arrays.asList( "a", "b", "c" ), + StringUtils.split( "a\n\n\nb\n\nc", '\n', true, true ) ); + } +} From ac6702fcf7216d77c91fb89978e68c01fbd6907e Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 29 Sep 2021 23:56:41 +0200 Subject: [PATCH 5/5] Styling: Extras: add styleClass getter and setter to component classes --- .../components/FlatStyleableComponent.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatStyleableComponent.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatStyleableComponent.java index d2b3c70c..bdf1fb77 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatStyleableComponent.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatStyleableComponent.java @@ -34,6 +34,8 @@ public interface FlatStyleableComponent /** * Returns the style of a component as String in CSS syntax ("key1: value1; key2: value2; ...") * or {@code null} if no style has been assigned. + * + * @see FlatClientProperties#STYLE */ default String getStyle() { return (String) getClientProperty( FlatClientProperties.STYLE ); @@ -48,6 +50,8 @@ public interface FlatStyleableComponent * The syntax of the CSS values is the same as used in FlatLaf properties files * (https://www.formdev.com/flatlaf/properties-files/), * but some features are not supported (e.g. variables). + * + * @see FlatClientProperties#STYLE */ default void setStyle( String style ) { putClientProperty( FlatClientProperties.STYLE, style ); @@ -57,6 +61,8 @@ public interface FlatStyleableComponent /** * Returns the style of a component as {@link java.util.Map}<String, Object> * or {@code null} if no style has been assigned. + * + * @see FlatClientProperties#STYLE */ @SuppressWarnings( "unchecked" ) default Map getStyleMap() { @@ -70,12 +76,34 @@ public interface FlatStyleableComponent * E.g. for UI default {@code Slider.thumbSize} use key {@code thumbSize}. *

    * The values are not parsed from a string. They must be binary. + * + * @see FlatClientProperties#STYLE */ default void setStyleMap( Map styleMap ) { putClientProperty( FlatClientProperties.STYLE, styleMap ); } + /** + * Returns the style class(es) of a component (separated by space characters) + * or {@code null} if no style class has been assigned. + * + * @see FlatClientProperties#STYLE_CLASS + */ + default String getStyleClass() { + return (String) getClientProperty( FlatClientProperties.STYLE_CLASS ); + } + + /** + * Specifies the style class(es) of a component (separated by space characters). + * + * @see FlatClientProperties#STYLE_CLASS + */ + default void setStyleClass( String styleClass ) { + putClientProperty( FlatClientProperties.STYLE_CLASS, styleClass ); + } + + /** * Overrides {@link JComponent#getClientProperty(Object)}. */