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 cbbbeec1c..13fae8a65 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStylingSupport.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatStylingSupport.java @@ -97,7 +97,8 @@ 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 ); + Object styleForType = getStyleForType( type ); + return joinStyles( joinStyles( styleForType, styleForClasses ), style ); } /** @@ -162,6 +163,28 @@ private static Object getStyleForClass( String styleClass, String type ) { UIManager.get( "[style]" + type + '.' + styleClass ) ); } + /** + * Returns the styles for 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}. + * E.g. in FlatLaf properties file: + *
{@code
+ * [style]Button = borderColor: #08f; background: #08f; foreground: #fff
+ * }
+ * or in Java code:
+ * {@code
+ * UIManager.put( "[style]Button", "borderColor: #08f; background: #08f; foreground: #fff" );
+ * }
+ *
+ * @param type the type of the component
+ * @return the styles
+ */
+ public static Object getStyleForType( String type ) {
+ return UIManager.get( "[style]" + type );
+ }
+
/**
* Joins two styles. They can be either strings (in CSS syntax)
* or {@link java.util.Map}<String, Object> (with binary values).
@@ -462,22 +485,34 @@ private static Object applyToProperty( Object obj, String name, Object value )
String getterName = buildMethodName( "get", name );
String setterName = buildMethodName( "set", name );
- try {
- Method getter;
+ for(;;) {
try {
- getter = cls.getMethod( getterName );
+ Method getter;
+ try {
+ getter = cls.getMethod( getterName );
+ } catch( NoSuchMethodException ex ) {
+ getter = cls.getMethod( buildMethodName( "is", name ) );
+ }
+ Method setter = cls.getMethod( setterName, getter.getReturnType() );
+ Object oldValue = getter.invoke( obj );
+ setter.invoke( obj, convertToEnum( value, getter.getReturnType() ) );
+ return oldValue;
} catch( NoSuchMethodException ex ) {
- getter = cls.getMethod( buildMethodName( "is", name ) );
+ throw new UnknownStyleException( name );
+ } catch( Exception ex ) {
+ if( ex instanceof IllegalAccessException ) {
+ // this may happen for private subclasses of public Swing classes
+ // that override public property getter/setter
+ // e.g. class JSlider.SmartHashtable.LabelUIResource.getForeground()
+ // --> try again with superclass
+ cls = cls.getSuperclass();
+ if( cls != null && cls != Object.class )
+ continue;
+ }
+
+ throw new IllegalArgumentException( "failed to invoke property methods '" + cls.getName() + "."
+ + getterName + "()' or '" + setterName + "(...)'", ex );
}
- Method setter = cls.getMethod( setterName, getter.getReturnType() );
- Object oldValue = getter.invoke( obj );
- setter.invoke( obj, convertToEnum( value, getter.getReturnType() ) );
- return oldValue;
- } catch( NoSuchMethodException ex ) {
- throw new UnknownStyleException( name );
- } catch( Exception ex ) {
- throw new IllegalArgumentException( "failed to invoke property methods '" + cls.getName() + "."
- + getterName + "()' or '" + setterName + "(...)'", ex );
}
}
diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleType.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleType.java
new file mode 100644
index 000000000..aeef84a39
--- /dev/null
+++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleType.java
@@ -0,0 +1,306 @@
+/*
+ * 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.FlatSystemProperties;
+
+/**
+ * @author Karl Tauber
+ */
+public class TestFlatStyleType
+{
+ @BeforeAll
+ static void setup() {
+ System.setProperty( FlatSystemProperties.UI_SCALE_ENABLED, "false" );
+ TestUtils.setup( false );
+
+ UIManager.put( "[style]Button", "foreground: #000001" );
+ UIManager.put( "[style]CheckBox", "foreground: #000002" );
+ UIManager.put( "[style]ComboBox", "foreground: #000003" );
+ UIManager.put( "[style]EditorPane", "foreground: #000004" );
+ UIManager.put( "[style]FormattedTextField", "foreground: #000005" );
+ UIManager.put( "[style]InternalFrame", "foreground: #000006" );
+ UIManager.put( "[style]Label", "foreground: #000007" );
+ UIManager.put( "[style]List", "foreground: #000008" );
+ UIManager.put( "[style]MenuBar", "foreground: #000009" );
+ UIManager.put( "[style]Menu", "foreground: #000010" );
+ UIManager.put( "[style]MenuItem", "foreground: #000011" );
+ UIManager.put( "[style]CheckBoxMenuItem", "foreground: #000012" );
+ UIManager.put( "[style]RadioButtonMenuItem", "foreground: #000013" );
+ UIManager.put( "[style]PasswordField", "foreground: #000014" );
+ UIManager.put( "[style]PopupMenu", "foreground: #000015" );
+ UIManager.put( "[style]PopupMenuSeparator", "foreground: #000016" );
+ UIManager.put( "[style]ProgressBar", "foreground: #000017" );
+ UIManager.put( "[style]RadioButton", "foreground: #000018" );
+ UIManager.put( "[style]ScrollBar", "foreground: #000019" );
+ UIManager.put( "[style]ScrollPane", "foreground: #000020" );
+ UIManager.put( "[style]Separator", "foreground: #000021" );
+ UIManager.put( "[style]Slider", "foreground: #000022" );
+ UIManager.put( "[style]Spinner", "foreground: #000023" );
+ UIManager.put( "[style]SplitPane", "foreground: #000024" );
+ UIManager.put( "[style]TabbedPane", "foreground: #000025" );
+ UIManager.put( "[style]Table", "foreground: #000026" );
+ UIManager.put( "[style]TableHeader", "foreground: #000027" );
+ UIManager.put( "[style]TextArea", "foreground: #000028" );
+ UIManager.put( "[style]TextField", "foreground: #000029" );
+ UIManager.put( "[style]TextPane", "foreground: #000030" );
+ UIManager.put( "[style]ToggleButton", "foreground: #000031" );
+ UIManager.put( "[style]ToolBar", "foreground: #000032" );
+ UIManager.put( "[style]Tree", "foreground: #000033" );
+
+ // JToolBar.Separator
+ UIManager.put( "[style]ToolBarSeparator", "separatorWidth: 21" );
+ }
+
+ @AfterAll
+ static void cleanup() {
+ TestUtils.cleanup();
+ System.clearProperty( FlatSystemProperties.UI_SCALE_ENABLED );
+ }
+
+ @Test
+ void styleForType() {
+ assertEquals( "foreground: #000001", FlatStylingSupport.getStyleForType( "Button" ) );
+ }
+
+ //---- components ---------------------------------------------------------
+
+ @Test
+ void button() {
+ JButton c = new JButton();
+ assertEquals( new Color( 0x000001 ), c.getForeground() );
+ }
+
+ @Test
+ void checkBox() {
+ JCheckBox c = new JCheckBox();
+ assertEquals( new Color( 0x000002 ), c.getForeground() );
+ }
+
+ @Test
+ void comboBox() {
+ JComboBox