diff --git a/CHANGELOG.md b/CHANGELOG.md index b25fd9cb..a7ca9f02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ FlatLaf Change Log frames. (issue #94) - Button and ToggleButton: Support round button style (set client property `JButton.buttonType` to `roundRect`). +- ComboBox, Spinner and TextField: Support round border style (set client + property `JComponent.roundRect` to `true`). - Paint nicely rounded buttons, comboboxes, spinners and text fields when setting `Button.arc`, `Component.arc` or `TextComponent.arc` to a large value (e.g. 1000). 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 5d624fe6..66a2646f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -103,6 +103,15 @@ public interface FlatClientProperties */ String MINIMUM_HEIGHT = "JComponent.minimumHeight"; + /** + * Paint the component with round edges. + *

+ * Components {@link javax.swing.JComboBox}, {@link javax.swing.JSpinner}, + * {@link javax.swing.JTextField}, {@link javax.swing.JFormattedTextField} and {@link javax.swing.JPasswordField} + * Value type {@link java.lang.Boolean} + */ + String COMPONENT_ROUND_RECT = "JComponent.roundRect"; + /** * Specifies whether a drop shadow is painted if the component is shown in a popup * or if the component is the owner of another component that is shown in a popup. 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 10b9ee82..af39f30e 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 @@ -208,6 +208,10 @@ public class FlatButtonUI case MINIMUM_HEIGHT: b.revalidate(); break; + + case BUTTON_TYPE: + b.repaint(); + break; } } 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 dba17cc0..8e987a79 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 @@ -243,6 +243,8 @@ public class FlatComboBoxUI editor.applyComponentOrientation( o ); } else if( editor != null && FlatClientProperties.PLACEHOLDER_TEXT.equals( propertyName ) ) editor.repaint(); + else if( FlatClientProperties.COMPONENT_ROUND_RECT.equals( propertyName ) ) + comboBox.repaint(); } }; } 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 5949d19b..b02249a5 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 @@ -34,7 +34,6 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicPasswordFieldUI; import javax.swing.text.Caret; import javax.swing.text.JTextComponent; -import com.formdev.flatlaf.FlatClientProperties; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JPasswordField}. @@ -147,9 +146,7 @@ public class FlatPasswordFieldUI @Override protected void propertyChange( PropertyChangeEvent e ) { super.propertyChange( e ); - - if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) ) - getComponent().repaint(); + FlatTextFieldUI.propertyChange( getComponent(), e ); } @Override diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRoundBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRoundBorder.java index cfcf8f85..58d90230 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRoundBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRoundBorder.java @@ -33,6 +33,6 @@ public class FlatRoundBorder @Override protected int getArc( Component c ) { - return arc; + return FlatUIUtils.isRoundRect( c ) ? Short.MAX_VALUE : arc; } } 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 a67ed692..59d5576c 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 @@ -40,6 +40,7 @@ import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicSpinnerUI; +import com.formdev.flatlaf.FlatClientProperties; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JSpinner}. @@ -394,6 +395,10 @@ public class FlatSpinnerUI case "enabled": updateEditorColors(); break; + + case FlatClientProperties.COMPONENT_ROUND_RECT: + spinner.repaint(); + break; } } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextBorder.java index c34f6e71..2ff587cb 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextBorder.java @@ -33,6 +33,6 @@ public class FlatTextBorder @Override protected int getArc( Component c ) { - return arc; + return FlatUIUtils.isRoundRect( c ) ? Short.MAX_VALUE : arc; } } 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 03795eae..f3c1547f 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 @@ -127,9 +127,16 @@ public class FlatTextFieldUI @Override protected void propertyChange( PropertyChangeEvent e ) { super.propertyChange( e ); + propertyChange( getComponent(), e ); + } - if( FlatClientProperties.PLACEHOLDER_TEXT.equals( e.getPropertyName() ) ) - getComponent().repaint(); + static void propertyChange( JTextComponent c, PropertyChangeEvent e ) { + switch( e.getPropertyName() ) { + case FlatClientProperties.PLACEHOLDER_TEXT: + case FlatClientProperties.COMPONENT_ROUND_RECT: + c.repaint(); + break; + } } @Override 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 91c34d82..eef07f87 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 @@ -143,6 +143,11 @@ public class FlatUIUtils return (KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner() == c); } + public static boolean isRoundRect( Component c ) { + return c instanceof JComponent && FlatClientProperties.clientPropertyBoolean( + (JComponent) c, FlatClientProperties.COMPONENT_ROUND_RECT, false ); + } + /** * Returns the scaled thickness of the outer focus border for the given component. */ diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java index 94c25002..0d8d8055 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.java @@ -19,6 +19,7 @@ package com.formdev.flatlaf.testing; import java.awt.*; import javax.swing.*; import javax.swing.border.*; +import com.formdev.flatlaf.FlatClientProperties; import net.miginfocom.swing.*; /** @@ -63,6 +64,26 @@ public class FlatComponentsTest } } + private void roundRectChanged() { + Boolean roundRect = roundRectCheckBox.isSelected() ? true : null; + + for( Component c : getComponents() ) { + if( c instanceof JComponent ) + ((JComponent)c).putClientProperty( FlatClientProperties.COMPONENT_ROUND_RECT, roundRect ); + } + } + + private void buttonTypeChanged() { + String buttonType = (String) buttonTypeComboBox.getSelectedItem(); + if( "-".equals( buttonType ) ) + buttonType = null; + + for( Component c : getComponents() ) { + if( c instanceof AbstractButton ) + ((AbstractButton)c).putClientProperty( FlatClientProperties.BUTTON_TYPE, buttonType ); + } + } + private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents JLabel labelLabel = new JLabel(); @@ -104,12 +125,14 @@ public class FlatComponentsTest JCheckBox checkBox4 = new JCheckBox(); JToggleButton toggleButton5 = new JToggleButton(); JToggleButton toggleButton8 = new JToggleButton(); + buttonTypeComboBox = new JComboBox<>(); JLabel radioButtonLabel = new JLabel(); JRadioButton radioButton1 = new JRadioButton(); JRadioButton radioButton2 = new JRadioButton(); JRadioButton radioButton3 = new JRadioButton(); JRadioButton radioButton4 = new JRadioButton(); contentAreaFilledCheckBox = new JCheckBox(); + roundRectCheckBox = new JCheckBox(); JLabel comboBoxLabel = new JLabel(); JComboBox comboBox1 = new JComboBox<>(); JComboBox comboBox2 = new JComboBox<>(); @@ -481,6 +504,17 @@ public class FlatComponentsTest toggleButton8.setSelected(true); add(toggleButton8, "cell 5 3"); + //---- buttonTypeComboBox ---- + buttonTypeComboBox.setModel(new DefaultComboBoxModel<>(new String[] { + "-", + "square", + "roundRect", + "tab", + "help" + })); + buttonTypeComboBox.addActionListener(e -> buttonTypeChanged()); + add(buttonTypeComboBox, "cell 6 3"); + //---- radioButtonLabel ---- radioButtonLabel.setText("JRadioButton:"); add(radioButtonLabel, "cell 0 4"); @@ -513,6 +547,11 @@ public class FlatComponentsTest contentAreaFilledCheckBox.addActionListener(e -> contentAreaFilledChanged()); add(contentAreaFilledCheckBox, "cell 5 4"); + //---- roundRectCheckBox ---- + roundRectCheckBox.setText("roundRect"); + roundRectCheckBox.addActionListener(e -> roundRectChanged()); + add(roundRectCheckBox, "cell 6 4"); + //---- comboBoxLabel ---- comboBoxLabel.setText("JComboBox:"); add(comboBoxLabel, "cell 0 5"); @@ -1210,7 +1249,9 @@ public class FlatComponentsTest } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + private JComboBox buttonTypeComboBox; private JCheckBox contentAreaFilledCheckBox; + private JCheckBox roundRectCheckBox; private JProgressBar progressBar3; private JProgressBar progressBar4; private JSlider slider3; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd index 94520f0b..dbab3f4d 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponentsTest.jfd @@ -296,6 +296,23 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 5 3" } ) + add( new FormComponent( "javax.swing.JComboBox" ) { + name: "buttonTypeComboBox" + "model": new javax.swing.DefaultComboBoxModel { + selectedItem: "-" + addElement( "-" ) + addElement( "square" ) + addElement( "roundRect" ) + addElement( "tab" ) + addElement( "help" ) + } + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "buttonTypeChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 6 3" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "radioButtonLabel" "text": "JRadioButton:" @@ -343,6 +360,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 5 4" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "roundRectCheckBox" + "text": "roundRect" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "roundRectChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 6 4" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "comboBoxLabel" "text": "JComboBox:"