diff --git a/CHANGELOG.md b/CHANGELOG.md index 435808d2..b7545f86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,12 +28,16 @@ FlatLaf Change Log setting UI default `OptionPane.showIcon` to `true`. (issue #416) - No longer show the Java "duke/cup" icon if no window icon image is set. (issue #416) -- TextField, FormattedTextField and PasswordField: Support leading and trailing - icons (set client property `JTextField.leadingIcon` or - `JTextField.trailingIcon` to a `javax.swing.Icon`). (PR #378; issue #368) -- TextField, FormattedTextField and PasswordField: Support leading and trailing - components (set client property `JTextField.leadingComponent` or - `JTextField.trailingComponent` to a `java.awt.Component`). (PR #386) +- TextField, FormattedTextField and PasswordField: + - Support leading and trailing icons (set client property + `JTextField.leadingIcon` or `JTextField.trailingIcon` to a + `javax.swing.Icon`). (PR #378; issue #368) + - Support leading and trailing components (set client property + `JTextField.leadingComponent` or `JTextField.trailingComponent` to a + `java.awt.Component`). (PR #386) + - Support "clear" (or "cancel") button to empty text field. Only shown if text + field is not empty, editable and enabled. (set client property + `JTextField.showClearButton` to `true`). (PR #TODO) - TextComponents: Double/triple-click-and-drag now extends selection by whole words/lines. - Theming improvements: Reworks core themes to make it easier to create new 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 dd5e1242..ce55df19 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -903,6 +903,17 @@ public interface FlatClientProperties */ String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent"; + /** + * Specifies whether a "clear" (or "cancel") button is shown on the trailing side + * if the text field is not empty, editable and enabled. Default is {@code false}. + *

+ * Component {@link javax.swing.JTextField} (and subclasses)
+ * Value type {@link java.lang.Boolean} + * + * @since 2 + */ + String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton"; + //---- JToggleButton ------------------------------------------------------ /** 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 b6946080..62f9496e 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 @@ -45,10 +45,13 @@ import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.LookAndFeel; import javax.swing.UIManager; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicTextFieldUI; import javax.swing.text.Caret; +import javax.swing.text.Document; import javax.swing.text.JTextComponent; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; @@ -103,6 +106,10 @@ public class FlatTextFieldUI /** @since 2 */ @Styleable protected Icon trailingIcon; /** @since 2 */ protected JComponent leadingComponent; /** @since 2 */ protected JComponent trailingComponent; + /** @since 2 */ protected JComponent clearButton; + + // only used via styling (not in UI defaults, but has likewise client properties) + /** @since 2 */ @Styleable protected boolean showClearButton; private Color oldDisabledBackground; private Color oldInactiveBackground; @@ -110,6 +117,7 @@ public class FlatTextFieldUI private Insets defaultMargin; private FocusListener focusListener; + private DocumentListener documentListener; private Map oldStyleValues; private AtomicBoolean borderShared; @@ -126,6 +134,7 @@ public class FlatTextFieldUI installLeadingComponent(); installTrailingComponent(); + installClearButton(); installStyle(); } @@ -134,6 +143,7 @@ public class FlatTextFieldUI public void uninstallUI( JComponent c ) { uninstallLeadingComponent(); uninstallTrailingComponent(); + uninstallClearButton(); super.uninstallUI( c ); @@ -196,6 +206,11 @@ public class FlatTextFieldUI getComponent().removeFocusListener( focusListener ); focusListener = null; + + if( documentListener != null ) { + getComponent().getDocument().removeDocumentListener( documentListener ); + documentListener = null; + } } @Override @@ -254,9 +269,47 @@ public class FlatTextFieldUI c.revalidate(); c.repaint(); break; + + case TEXT_FIELD_SHOW_CLEAR_BUTTON: + uninstallClearButton(); + installClearButton(); + c.revalidate(); + c.repaint(); + break; + + case "enabled": + case "editable": + updateClearButton(); + break; + + case "document": + if( documentListener != null ) { + if( e.getOldValue() instanceof Document ) + ((Document)e.getOldValue()).removeDocumentListener( documentListener ); + if( e.getNewValue() instanceof Document ) + ((Document)e.getNewValue()).addDocumentListener( documentListener ); + + updateClearButton(); + } + break; } } + /** @since 2 */ + protected void installDocumentListener() { + if( documentListener != null ) + return; + + documentListener = new FlatDocumentListener(); + getComponent().getDocument().addDocumentListener( documentListener ); + } + + /** @since 2 */ + protected void documentChanged( DocumentEvent e ) { + if( clearButton != null ) + updateClearButton(); + } + /** @since 2 */ protected void installStyle() { try { @@ -275,10 +328,15 @@ public class FlatTextFieldUI protected void applyStyle( Object style ) { oldDisabledBackground = disabledBackground; oldInactiveBackground = inactiveBackground; + boolean oldShowClearButton = showClearButton; oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); updateBackground(); + if( showClearButton != oldShowClearButton ) { + uninstallClearButton(); + installClearButton(); + } } /** @since 2 */ @@ -474,10 +532,14 @@ debug*/ size.width += getLeadingIconWidth() + getTrailingIconWidth(); // add width of leading and trailing components - if( leadingComponent != null && leadingComponent.isVisible() ) - size.width += leadingComponent.getPreferredSize().width; - if( trailingComponent != null && trailingComponent.isVisible() ) - size.width += trailingComponent.getPreferredSize().width; + for( JComponent comp : getLeadingComponents() ) { + if( comp != null && comp.isVisible() ) + size.width += comp.getPreferredSize().width; + } + for( JComponent comp : getTrailingComponents() ) { + if( comp != null && comp.isVisible() ) + size.width += comp.getPreferredSize().width; + } return size; } @@ -558,17 +620,24 @@ debug*/ boolean ltr = isLeftToRight(); // remove width of leading/trailing components - JComponent leftComponent = ltr ? leadingComponent : trailingComponent; - JComponent rightComponent = ltr ? trailingComponent : leadingComponent; - boolean leftVisible = leftComponent != null && leftComponent.isVisible(); - boolean rightVisible = rightComponent != null && rightComponent.isVisible(); - if( leftVisible ) { - int w = leftComponent.getPreferredSize().width; - r.x += w; - r.width -= w; + JComponent[] leftComponents = ltr ? getLeadingComponents() : getTrailingComponents(); + JComponent[] rightComponents = ltr ? getTrailingComponents() : getLeadingComponents(); + boolean leftVisible = false; + boolean rightVisible = false; + for( JComponent leftComponent : leftComponents ) { + if( leftComponent != null && leftComponent.isVisible() ) { + int w = leftComponent.getPreferredSize().width; + r.x += w; + r.width -= w; + leftVisible = true; + } + } + for( JComponent rightComponent : rightComponents ) { + if( rightComponent != null && rightComponent.isVisible() ) { + r.width -= rightComponent.getPreferredSize().width; + rightVisible = true; + } } - if( rightVisible ) - r.width -= rightComponent.getPreferredSize().width; // if a leading/trailing icons (or components) are shown, then the left/right margins are reduced // to the top margin, which places the icon nicely centered on left/right side @@ -671,6 +740,76 @@ debug*/ } } + /** @since 2 */ + protected void installClearButton() { + JTextComponent c = getComponent(); + if( clientPropertyBoolean( c, TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton ) ) { + clearButton = createClearButton(); + updateClearButton(); + installDocumentListener(); + installLayout(); + c.add( clearButton ); + } + } + + /** @since 2 */ + protected JComponent createClearButton() { + JButton button = new JButton(); + button.putClientProperty( STYLE_CLASS, "clearButton" ); + button.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON ); + button.setCursor( Cursor.getDefaultCursor() ); + button.addActionListener( e -> { + getComponent().setText( "" ); + } ); + return button; + } + + /** @since 2 */ + protected void uninstallClearButton() { + if( clearButton != null ) { + getComponent().remove( clearButton ); + clearButton = null; + } + } + + /** @since 2 */ + protected void updateClearButton() { + if( clearButton == null ) + return; + + JTextComponent c = getComponent(); + boolean visible = c.isEnabled() && c.isEditable() && c.getDocument().getLength() > 0; + if( visible != clearButton.isVisible() ) { + clearButton.setVisible( visible ); + c.revalidate(); + c.repaint(); + } + } + + /** + * Returns components placed at the leading side of the text field. + * The returned array may contain {@code null}. + * The default implementation returns {@link #leadingComponent}. + * + * @since 2 + */ + protected JComponent[] getLeadingComponents() { + return new JComponent[] { leadingComponent }; + } + + /** + * Returns components placed at the trailing side of the text field. + * The returned array may contain {@code null}. + * The default implementation returns {@link #trailingComponent} and {@link #clearButton}. + *

+ * Note: The components in the array must be in reverse (visual) order. + * + * @since 2 + */ + protected JComponent[] getTrailingComponents() { + return new JComponent[] { trailingComponent, clearButton }; + } + /** @since 2 */ protected void prepareLeadingOrTrailingComponent( JComponent c ) { c.putClientProperty( STYLE_CLASS, "inTextField" ); @@ -686,7 +825,8 @@ debug*/ } } - private void installLayout() { + /** @since 2 */ + protected void installLayout() { JTextComponent c = getComponent(); LayoutManager oldLayout = c.getLayout(); if( !(oldLayout instanceof FlatTextFieldLayout) ) @@ -731,25 +871,30 @@ debug*/ if( delegate != null ) delegate.layoutContainer( parent ); - if( leadingComponent == null && trailingComponent == null ) - return; - int ow = FlatUIUtils.getBorderFocusAndLineWidth( getComponent() ); int h = parent.getHeight() - ow - ow; boolean ltr = isLeftToRight(); - JComponent leftComponent = ltr ? leadingComponent : trailingComponent; - JComponent rightComponent = ltr ? trailingComponent : leadingComponent; + JComponent[] leftComponents = ltr ? getLeadingComponents() : getTrailingComponents(); + JComponent[] rightComponents = ltr ? getTrailingComponents() : getLeadingComponents(); - // layout left component - if( leftComponent != null && leftComponent.isVisible() ) { - int w = leftComponent.getPreferredSize().width; - leftComponent.setBounds( ow, ow, w, h ); + // layout left components + int x = ow; + for( JComponent leftComponent : leftComponents ) { + if( leftComponent != null && leftComponent.isVisible() ) { + int cw = leftComponent.getPreferredSize().width; + leftComponent.setBounds( x, ow, cw, h ); + x += cw; + } } - // layout right component - if( rightComponent != null && rightComponent.isVisible() ) { - int w = rightComponent.getPreferredSize().width; - rightComponent.setBounds( parent.getWidth() - ow - w, ow, w, h ); + // layout right components + x = parent.getWidth() - ow; + for( JComponent rightComponent : rightComponents ) { + if( rightComponent != null && rightComponent.isVisible() ) { + int cw = rightComponent.getPreferredSize().width; + x -= cw; + rightComponent.setBounds( x, ow, cw, h ); + } } } @@ -780,4 +925,24 @@ debug*/ ((LayoutManager2)delegate).invalidateLayout( target ); } } + //---- class FlatDocumentListener ----------------------------------------- + + private class FlatDocumentListener + implements DocumentListener + { + @Override + public void insertUpdate( DocumentEvent e ) { + documentChanged( e ); + } + + @Override + public void removeUpdate( DocumentEvent e ) { + documentChanged( e ); + } + + @Override + public void changedUpdate( DocumentEvent e ) { + documentChanged( e ); + } + } } diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 53879b71..f8ba150b 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -907,3 +907,16 @@ Tree.icon.openColor = @icon [style]ToolBarSeparator.inTextField = \ separatorWidth: 3 + + +#---- clearButton ---- +# for clear/cancel button in text fields + +[style]Button.clearButton = \ + icon: com.formdev.flatlaf.icons.FlatClearIcon; \ + focusable: false; \ + toolbar.margin: 1,1,1,1; \ + toolbar.spacingInsets: 1,1,1,1; \ + background: $TextField.background; \ + toolbar.hoverBackground: $TextField.background; \ + toolbar.pressedBackground: $TextField.background diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java index e663fba6..7842df5d 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java @@ -823,7 +823,8 @@ public class TestFlatStyleableInfo "focusedBackground", Color.class, "iconTextGap", int.class, "leadingIcon", Icon.class, - "trailingIcon", Icon.class + "trailingIcon", Icon.class, + "showClearButton", boolean.class ); // border diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java index b63a234d..700ced80 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java @@ -1011,6 +1011,8 @@ public class TestFlatStyling ui.applyStyle( "leadingIcon: com.formdev.flatlaf.icons.FlatSearchIcon" ); ui.applyStyle( "trailingIcon: com.formdev.flatlaf.icons.FlatClearIcon" ); + ui.applyStyle( "showClearButton: true" ); + // border flatTextBorder( style -> ui.applyStyle( style ) ); diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java index dc9e05e3..a43d40a5 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.java @@ -73,6 +73,10 @@ class BasicComponentsPanel searchToolbar.addSeparator(); searchToolbar.add( regexButton ); compsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT, searchToolbar ); + + // show clear button (if text field is not empty) + compsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_SHOW_CLEAR_BUTTON, true ); + clearTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_SHOW_CLEAR_BUTTON, true ); } private void initComponents() { @@ -173,6 +177,7 @@ class BasicComponentsPanel JTextField iconsTextField = new JTextField(); JLabel compsLabel = new JLabel(); compsTextField = new JTextField(); + clearTextField = new JTextField(); JLabel fontsLabel = new JLabel(); JLabel h00Label = new JLabel(); JLabel h0Label = new JLabel(); @@ -734,6 +739,10 @@ class BasicComponentsPanel add(compsLabel, "cell 0 15"); add(compsTextField, "cell 1 15 2 1,growx"); + //---- clearTextField ---- + clearTextField.setText("clear me"); + add(clearTextField, "cell 3 15,growx"); + //---- fontsLabel ---- fontsLabel.setText("Typography / Fonts:"); add(fontsLabel, "cell 0 16"); @@ -905,5 +914,6 @@ class BasicComponentsPanel // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables private JTextField compsTextField; + private JTextField clearTextField; // JFormDesigner - End of variables declaration //GEN-END:variables } diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd index c5eb1554..b6d9a4b9 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/BasicComponentsPanel.jfd @@ -685,6 +685,15 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 15 2 1,growx" } ) + add( new FormComponent( "javax.swing.JTextField" ) { + name: "clearTextField" + "text": "clear me" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 3 15,growx" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "fontsLabel" "text": "Typography / Fonts:" diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java index 326930f7..c3aa8826 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatFormattedTextField.java @@ -144,6 +144,26 @@ public class FlatFormattedTextField } + /** + * Returns whether a "clear" (or "cancel") button is shown. + * + * @since 2 + */ + public boolean isShowClearButton() { + return getClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, false ); + } + + /** + * Specifies whether a "clear" (or "cancel") button is shown on the trailing side + * if the text field is not empty, editable and enabled. + * + * @since 2 + */ + public void setShowClearButton( boolean showClearButton ) { + putClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton, false ); + } + + /** * Returns whether all text is selected when the text component gains focus. */ diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java index cd7f2374..7c36be76 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatPasswordField.java @@ -144,6 +144,26 @@ public class FlatPasswordField } + /** + * Returns whether a "clear" (or "cancel") button is shown. + * + * @since 2 + */ + public boolean isShowClearButton() { + return getClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, false ); + } + + /** + * Specifies whether a "clear" (or "cancel") button is shown on the trailing side + * if the text field is not empty, editable and enabled. + * + * @since 2 + */ + public void setShowClearButton( boolean showClearButton ) { + putClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton, false ); + } + + /** * Returns whether all text is selected when the text component gains focus. */ diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java index c7747bf5..c2d14a07 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/components/FlatTextField.java @@ -143,6 +143,26 @@ public class FlatTextField } + /** + * Returns whether a "clear" (or "cancel") button is shown. + * + * @since 2 + */ + public boolean isShowClearButton() { + return getClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, false ); + } + + /** + * Specifies whether a "clear" (or "cancel") button is shown on the trailing side + * if the text field is not empty, editable and enabled. + * + * @since 2 + */ + public void setShowClearButton( boolean showClearButton ) { + putClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton, false ); + } + + // NOTE: enum names must be equal to allowed strings public enum SelectAllOnFocusPolicy { never, once, always }; diff --git a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt index 7cf0ed6a..c1741a44 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt @@ -1421,6 +1421,7 @@ ViewportUI com.formdev.flatlaf.ui.FlatViewportUI #---- [style]Button ---- +[style]Button.clearButton icon: com.formdev.flatlaf.icons.FlatClearIcon; focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1; background: $TextField.background; toolbar.hoverBackground: $TextField.background; toolbar.pressedBackground: $TextField.background [style]Button.inTextField focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1; background: $TextField.background; toolbar.hoverBackground: lighten($TextField.background,4%,derived); toolbar.pressedBackground: lighten($TextField.background,6%,derived); toolbar.selectedBackground: lighten($TextField.background,12%,derived) diff --git a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt index c0ae8ece..00d5267e 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt @@ -1426,6 +1426,7 @@ ViewportUI com.formdev.flatlaf.ui.FlatViewportUI #---- [style]Button ---- +[style]Button.clearButton icon: com.formdev.flatlaf.icons.FlatClearIcon; focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1; background: $TextField.background; toolbar.hoverBackground: $TextField.background; toolbar.pressedBackground: $TextField.background [style]Button.inTextField focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1; background: $TextField.background; toolbar.hoverBackground: darken($TextField.background,4%,derived); toolbar.pressedBackground: darken($TextField.background,8%,derived); toolbar.selectedBackground: darken($TextField.background,12%,derived) diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt index be298499..204b1cd8 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt @@ -1439,6 +1439,7 @@ ViewportUI com.formdev.flatlaf.ui.FlatViewportUI #---- [style]Button ---- +[style]Button.clearButton icon: com.formdev.flatlaf.icons.FlatClearIcon; focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1; background: $TextField.background; toolbar.hoverBackground: $TextField.background; toolbar.pressedBackground: $TextField.background [style]Button.inTextField focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1 diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java index a0c66148..e3bfa84b 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.java @@ -121,6 +121,11 @@ public class FlatTextComponentsTest } } + private void showClearButton() { + putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_SHOW_CLEAR_BUTTON, + showClearButtonCheckBox.isSelected() ); + } + private void putTextFieldClientProperty( String key, Object value ) { for( Component c : getComponents() ) { if( c instanceof JTextField ) @@ -168,6 +173,7 @@ public class FlatTextComponentsTest trailingComponentCheckBox = new JCheckBox(); leadingComponentVisibleCheckBox = new JCheckBox(); trailingComponentVisibleCheckBox = new JCheckBox(); + showClearButtonCheckBox = new JCheckBox(); JLabel passwordFieldLabel = new JLabel(); JPasswordField passwordField1 = new JPasswordField(); JPasswordField passwordField3 = new JPasswordField(); @@ -319,6 +325,7 @@ public class FlatTextComponentsTest "[]0" + "[]" + "[]0" + + "[]" + "[]")); //---- button1 ---- @@ -404,6 +411,12 @@ public class FlatTextComponentsTest trailingComponentVisibleCheckBox.setName("trailingComponentVisibleCheckBox"); trailingComponentVisibleCheckBox.addActionListener(e -> trailingComponentVisible()); panel1.add(trailingComponentVisibleCheckBox, "cell 0 10 2 1,alignx left,growx 0"); + + //---- showClearButtonCheckBox ---- + showClearButtonCheckBox.setText("clear button"); + showClearButtonCheckBox.setName("showClearButtonCheckBox"); + showClearButtonCheckBox.addActionListener(e -> showClearButton()); + panel1.add(showClearButtonCheckBox, "cell 0 11 2 1,alignx left,growx 0"); } add(panel1, "cell 4 0 1 10,aligny top,growy 0"); @@ -719,6 +732,7 @@ public class FlatTextComponentsTest private JCheckBox trailingComponentCheckBox; private JCheckBox leadingComponentVisibleCheckBox; private JCheckBox trailingComponentVisibleCheckBox; + private JCheckBox showClearButtonCheckBox; private JTextField textField; private JCheckBox dragEnabledCheckBox; private JTextArea textArea; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd index 2dfcfb7b..06681160 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatTextComponentsTest.jfd @@ -77,7 +77,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "hidemode 3" "$columnConstraints": "[fill][fill]" - "$rowConstraints": "[][][][][][]0[][]0[][]0[]" + "$rowConstraints": "[][][][][][]0[][]0[][]0[][]" } ) { name: "panel1" "border": new javax.swing.border.TitledBorder( "Control" ) @@ -210,6 +210,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 10 2 1,alignx left,growx 0" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "showClearButtonCheckBox" + "text": "clear button" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showClearButton", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 11 2 1,alignx left,growx 0" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 4 0 1 10,aligny top,growy 0" } ) diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index 3257247b..b0340b10 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -1115,6 +1115,7 @@ ViewportUI [style].monospaced [style].semibold [style].small +[style]Button.clearButton [style]Button.inTextField [style]ToggleButton.inTextField [style]ToolBar.inTextField