From f93d035e4ebf2ad58f8543814471b7471d67a1c6 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 3 Sep 2021 22:24:46 +0200 Subject: [PATCH 1/5] TextField: support leading and trailing components --- CHANGELOG.md | 5 +- .../formdev/flatlaf/FlatClientProperties.java | 48 ++++- .../formdev/flatlaf/ui/FlatTextFieldUI.java | 193 +++++++++++++++++- .../com/formdev/flatlaf/ui/FlatUIUtils.java | 26 +++ .../components/FlatFormattedTextField.java | 59 ++++++ .../extras/components/FlatPasswordField.java | 59 ++++++ .../extras/components/FlatTextField.java | 59 ++++++ .../testing/FlatTextComponentsTest.java | 63 +++++- .../testing/FlatTextComponentsTest.jfd | 22 +- 9 files changed, 515 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da6f25ae..435808d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,10 @@ FlatLaf Change Log (issue #416) - TextField, FormattedTextField and PasswordField: Support leading and trailing icons (set client property `JTextField.leadingIcon` or - `JTextField.trailingIcon` to an `Icon`). (PR #378; issue #368) + `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) - 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 4af43c96..ed3f3acc 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -763,9 +763,9 @@ public interface FlatClientProperties /** * Specifies a component that will be placed at the leading edge of the tabs area. *

- * For top and bottom tab placement, the layed out component size will be + * For top and bottom tab placement, the laid out component size will be * the preferred component width and the tab area height.
- * For left and right tab placement, the layed out component size will be + * For left and right tab placement, the laid out component size will be * the tab area width and the preferred component height. *

* Component {@link javax.swing.JTabbedPane}
@@ -776,9 +776,9 @@ public interface FlatClientProperties /** * Specifies a component that will be placed at the trailing edge of the tabs area. *

- * For top and bottom tab placement, the layed out component size will be + * For top and bottom tab placement, the laid out component size will be * the available horizontal space (minimum is preferred component width) and the tab area height.
- * For left and right tab placement, the layed out component size will be + * For left and right tab placement, the laid out component size will be * the tab area width and the available vertical space (minimum is preferred component height). *

* Component {@link javax.swing.JTabbedPane}
@@ -863,6 +863,46 @@ public interface FlatClientProperties */ String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon"; + /** + * Specifies a component that will be placed at the leading edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #OUTLINE}. + *

+ * Component {@link javax.swing.JTextField} (and subclasses)
+ * Value type {@link java.awt.Component} + * + * @since 2 + */ + String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent"; + + /** + * Specifies a component that will be placed at the trailing edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #OUTLINE}. + *

+ * Component {@link javax.swing.JTextField} (and subclasses)
+ * Value type {@link java.awt.Component} + * + * @since 2 + */ + String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent"; + //---- 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 6814e7f8..60db8663 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 @@ -19,12 +19,15 @@ package com.formdev.flatlaf.ui; import static com.formdev.flatlaf.FlatClientProperties.*; import static com.formdev.flatlaf.util.UIScale.scale; import java.awt.Color; +import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.LayoutManager2; import java.awt.Rectangle; import java.awt.event.FocusListener; import java.beans.PropertyChangeEvent; @@ -94,6 +97,8 @@ public class FlatTextFieldUI /** @since 2 */ @Styleable protected Icon leadingIcon; /** @since 2 */ @Styleable protected Icon trailingIcon; + /** @since 2 */ protected Component leadingComponent; + /** @since 2 */ protected Component trailingComponent; private Color oldDisabledBackground; private Color oldInactiveBackground; @@ -115,11 +120,17 @@ public class FlatTextFieldUI leadingIcon = clientProperty( c, TEXT_FIELD_LEADING_ICON, null, Icon.class ); trailingIcon = clientProperty( c, TEXT_FIELD_TRAILING_ICON, null, Icon.class ); + installLeadingComponent(); + installTrailingComponent(); + installStyle(); } @Override public void uninstallUI( JComponent c ) { + uninstallLeadingComponent(); + uninstallTrailingComponent(); + super.uninstallUI( c ); leadingIcon = null; @@ -225,6 +236,20 @@ public class FlatTextFieldUI trailingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null; c.repaint(); break; + + case TEXT_FIELD_LEADING_COMPONENT: + uninstallLeadingComponent(); + installLeadingComponent(); + c.revalidate(); + c.repaint(); + break; + + case TEXT_FIELD_TRAILING_COMPONENT: + uninstallTrailingComponent(); + installTrailingComponent(); + c.revalidate(); + c.repaint(); + break; } } @@ -444,6 +469,12 @@ debug*/ // add width of leading and trailing icons 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; + return size; } @@ -510,7 +541,8 @@ debug*/ /** * Returns the rectangle used to paint leading and trailing icons. * It invokes {@code super.getVisibleEditorRect()} and reduces left and/or - * right margin if the text field has leading or trailing icons. + * right margin if the text field has leading or trailing icons or components. + * Also the preferred widths of leading and trailing components are removed. * * @since 2 */ @@ -519,10 +551,24 @@ debug*/ if( r == null ) return null; - // if a leading/trailing icon is shown, then the left/right margin is reduced - // to the top margin, which places the icon nicely centered on left/right side boolean ltr = isLeftToRight(); - if( ltr ? hasLeadingIcon() : hasTrailingIcon() ) { + + // remove width of leading/trailing components + Component leftComponent = ltr ? leadingComponent : trailingComponent; + Component rightComponent = ltr ? trailingComponent : leadingComponent; + if( leftComponent != null ) { + int w = leftComponent.getPreferredSize().width; + r.x += w; + r.width -= w; + } + if( rightComponent != null ) + 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 + if( (ltr ? hasLeadingIcon() : hasTrailingIcon()) || + (leftComponent != null && leftComponent.isVisible()) ) + { // reduce left margin Insets margin = getComponent().getMargin(); int newLeftMargin = Math.min( margin.left, margin.top ); @@ -532,7 +578,9 @@ debug*/ r.width += diff; } } - if( ltr ? hasTrailingIcon() : hasLeadingIcon() ) { + if( (ltr ? hasTrailingIcon() : hasLeadingIcon()) || + (rightComponent != null && rightComponent.isVisible()) ) + { // reduce right margin Insets margin = getComponent().getMargin(); int newRightMargin = Math.min( margin.right, margin.top ); @@ -540,6 +588,10 @@ debug*/ r.width += scale( margin.right - newRightMargin ); } + // make sure that width and height are not negative + r.width = Math.max( r.width, 0 ); + r.height = Math.max( r.height, 0 ); + return r; } @@ -578,4 +630,135 @@ debug*/ if( caret instanceof FlatCaret ) ((FlatCaret)caret).scrollCaretToVisible(); } + + /** @since 2 */ + protected void installLeadingComponent() { + JTextComponent c = getComponent(); + leadingComponent = clientProperty( c, TEXT_FIELD_LEADING_COMPONENT, null, Component.class ); + if( leadingComponent != null ) { + installLayout(); + c.add( leadingComponent ); + } + } + + /** @since 2 */ + protected void installTrailingComponent() { + JTextComponent c = getComponent(); + trailingComponent = clientProperty( c, TEXT_FIELD_TRAILING_COMPONENT, null, Component.class ); + if( trailingComponent != null ) { + installLayout(); + c.add( trailingComponent ); + } + } + + /** @since 2 */ + protected void uninstallLeadingComponent() { + if( leadingComponent != null ) { + getComponent().remove( leadingComponent ); + leadingComponent = null; + } + } + + /** @since 2 */ + protected void uninstallTrailingComponent() { + if( trailingComponent != null ) { + getComponent().remove( trailingComponent ); + trailingComponent = null; + } + } + + private void installLayout() { + JTextComponent c = getComponent(); + LayoutManager oldLayout = c.getLayout(); + if( !(oldLayout instanceof FlatTextFieldLayout) ) + c.setLayout( new FlatTextFieldLayout( oldLayout ) ); + } + + //---- class FlatTextFieldLayout ------------------------------------------ + + private class FlatTextFieldLayout + implements LayoutManager2, UIResource + { + private final LayoutManager delegate; + + FlatTextFieldLayout( LayoutManager delegate ) { + this.delegate = delegate; + } + + @Override + public void addLayoutComponent( String name, Component comp ) { + if( delegate != null ) + delegate.addLayoutComponent( name, comp ); + } + + @Override + public void removeLayoutComponent( Component comp ) { + if( delegate != null ) + delegate.removeLayoutComponent( comp ); + } + + @Override + public Dimension preferredLayoutSize( Container parent ) { + return (delegate != null) ? delegate.preferredLayoutSize( parent ) : null; + } + + @Override + public Dimension minimumLayoutSize( Container parent ) { + return (delegate != null) ? delegate.minimumLayoutSize( parent ) : null; + } + + @Override + public void layoutContainer( Container parent ) { + 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(); + Component leftComponent = ltr ? leadingComponent : trailingComponent; + Component rightComponent = ltr ? trailingComponent : leadingComponent; + + // layout left component + if( leftComponent != null && leftComponent.isVisible() ) { + int w = leftComponent.getPreferredSize().width; + leftComponent.setBounds( ow, ow, w, h ); + } + + // layout right component + if( rightComponent != null && rightComponent.isVisible() ) { + int w = rightComponent.getPreferredSize().width; + rightComponent.setBounds( parent.getWidth() - ow - w, ow, w, h ); + } + } + + @Override + public void addLayoutComponent( Component comp, Object constraints ) { + if( delegate instanceof LayoutManager2 ) + ((LayoutManager2)delegate).addLayoutComponent( comp, constraints ); + } + + @Override + public Dimension maximumLayoutSize( Container target ) { + return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).maximumLayoutSize( target ) : null; + } + + @Override + public float getLayoutAlignmentX( Container target ) { + return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).getLayoutAlignmentX( target ) : 0.5f; + } + + @Override + public float getLayoutAlignmentY( Container target ) { + return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).getLayoutAlignmentY( target ) : 0.5f; + } + + @Override + public void invalidateLayout( Container target ) { + if( delegate instanceof LayoutManager2 ) + ((LayoutManager2)delegate).invalidateLayout( target ); + } + } } 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 2c5cd1b9..fda0c1c8 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 @@ -278,6 +278,32 @@ public class FlatUIUtils : 0; } + /** + * Returns the scaled line thickness used to compute the border insets. + * + * @since 2 + */ + public static float getBorderLineWidth( JComponent c ) { + FlatBorder border = getOutsideFlatBorder( c ); + return (border != null) + ? UIScale.scale( (float) border.getLineWidth( c ) ) + : 0; + } + + /** + * Returns the scaled thickness of the border. + * This includes the outer focus border and the actual component border. + * + * @since 2 + */ + public static int getBorderFocusAndLineWidth( JComponent c ) { + FlatBorder border = getOutsideFlatBorder( c ); + return (border != null) + ? Math.round( UIScale.scale( (float) border.getFocusWidth( c ) ) + + UIScale.scale( (float) border.getLineWidth( c ) ) ) + : 0; + } + /** * Returns the scaled arc diameter of the border for the given component. */ 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 b8f1a270..54126d8d 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 @@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; +import java.awt.Component; import java.awt.Insets; import javax.swing.Icon; import javax.swing.JFormattedTextField; @@ -85,6 +86,64 @@ public class FlatFormattedTextField } + /** + * Returns a component that will be placed at the leading edge of the text field. + * + * @since 2 + */ + public Component getLeadingComponent() { + return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); + } + + /** + * Specifies a component that will be placed at the leading edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #setOutline(Object)}. + * + * @since 2 + */ + public void setLeadingComponent( Component leadingComponent ) { + putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent ); + } + + + /** + * Returns a component that will be placed at the trailing edge of the text field. + * + * @since 2 + */ + public Component getTrailingComponent() { + return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); + } + + /** + * Specifies a component that will be placed at the trailing edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #setOutline(Object)}. + * + * @since 2 + */ + public void setTrailingComponent( Component trailingComponent ) { + putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent ); + } + + /** * 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 1078d368..392db28e 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 @@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; +import java.awt.Component; import java.awt.Insets; import javax.swing.Icon; import javax.swing.JPasswordField; @@ -85,6 +86,64 @@ public class FlatPasswordField } + /** + * Returns a component that will be placed at the leading edge of the text field. + * + * @since 2 + */ + public Component getLeadingComponent() { + return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); + } + + /** + * Specifies a component that will be placed at the leading edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #setOutline(Object)}. + * + * @since 2 + */ + public void setLeadingComponent( Component leadingComponent ) { + putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent ); + } + + + /** + * Returns a component that will be placed at the trailing edge of the text field. + * + * @since 2 + */ + public Component getTrailingComponent() { + return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); + } + + /** + * Specifies a component that will be placed at the trailing edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #setOutline(Object)}. + * + * @since 2 + */ + public void setTrailingComponent( Component trailingComponent ) { + putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent ); + } + + /** * 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 31d8850d..9bd0f98a 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 @@ -18,6 +18,7 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; +import java.awt.Component; import java.awt.Insets; import javax.swing.Icon; import javax.swing.JTextField; @@ -84,6 +85,64 @@ public class FlatTextField } + /** + * Returns a component that will be placed at the leading edge of the text field. + * + * @since 2 + */ + public Component getLeadingComponent() { + return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); + } + + /** + * Specifies a component that will be placed at the leading edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #setOutline(Object)}. + * + * @since 2 + */ + public void setLeadingComponent( Component leadingComponent ) { + putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent ); + } + + + /** + * Returns a component that will be placed at the trailing edge of the text field. + * + * @since 2 + */ + public Component getTrailingComponent() { + return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); + } + + /** + * Specifies a component that will be placed at the trailing edge of the text field. + *

+ * The component will be positioned inside and aligned to the visible text field border. + * There is no gap between the visible border and the component. + * The laid out component size will be the preferred component width + * and the inner text field height. + *

+ * The component should be not opaque because the text field border is painted + * slightly inside the usually visible border in some cases. + * E.g. when focused (in some themes) or when an outline color is specified + * (see {@link #setOutline(Object)}. + * + * @since 2 + */ + public void setTrailingComponent( Component trailingComponent ) { + putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent ); + } + + // NOTE: enum names must be equal to allowed strings public enum SelectAllOnFocusPolicy { never, once, always }; 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 e72cb16b..1af9ec05 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 @@ -21,6 +21,7 @@ import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; +import java.util.function.Supplier; import javax.swing.*; import javax.swing.border.*; import javax.swing.text.DefaultEditorKit; @@ -58,26 +59,54 @@ public class FlatTextComponentsTest if( padding.equals( new Insets( 0, 0, 0, 0 ) ) ) padding = null; - for( Component c : getComponents() ) { - if( c instanceof JTextField ) - ((JTextField)c).putClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, padding ); - } + putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_PADDING, padding ); } private void leadingIcon() { - applyIcon( FlatClientProperties.TEXT_FIELD_LEADING_ICON, leadingIconCheckBox.isSelected() + putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_ICON, leadingIconCheckBox.isSelected() ? new TestIcon( 8, 16, Color.blue ) : null ); } private void trailingIcon() { - applyIcon( FlatClientProperties.TEXT_FIELD_TRAILING_ICON, trailingIconCheckBox.isSelected() + putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_ICON, trailingIconCheckBox.isSelected() ? new TestIcon( 24, 12, Color.magenta ) : null ); } - private void applyIcon( String key, Icon icon ) { + private void leadingComponent() { + putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_COMPONENT, () -> { + if( !leadingComponentCheckBox.isSelected() ) + return null; + + JLabel l = new JLabel( "lead" ); + l.setOpaque( true ); + l.setBackground( Color.green ); + return l; + } ); + } + + private void trailingComponent() { + putTextFieldClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT, () -> { + if( !trailingComponentCheckBox.isSelected() ) + return null; + + JLabel l = new JLabel( "tr" ); + l.setOpaque( true ); + l.setBackground( Color.magenta ); + return l; + } ); + } + + private void putTextFieldClientProperty( String key, Object value ) { for( Component c : getComponents() ) { if( c instanceof JTextField ) - ((JTextField)c).putClientProperty( key, icon ); + ((JTextField)c).putClientProperty( key, value ); + } + } + + private void putTextFieldClientProperty( String key, Supplier value ) { + for( Component c : getComponents() ) { + if( c instanceof JTextField ) + ((JTextField)c).putClientProperty( key, value.get() ); } } @@ -110,6 +139,8 @@ public class FlatTextComponentsTest bottomPaddingField = new JSpinner(); leadingIconCheckBox = new JCheckBox(); trailingIconCheckBox = new JCheckBox(); + leadingComponentCheckBox = new JCheckBox(); + trailingComponentCheckBox = new JCheckBox(); JLabel passwordFieldLabel = new JLabel(); JPasswordField passwordField1 = new JPasswordField(); JPasswordField passwordField3 = new JPasswordField(); @@ -256,7 +287,9 @@ public class FlatTextComponentsTest "[]" + "[]" + "[]" + + "[]0" + "[]" + + "[]0" + "[]")); //---- button1 ---- @@ -316,6 +349,18 @@ public class FlatTextComponentsTest trailingIconCheckBox.setName("trailingIconCheckBox"); trailingIconCheckBox.addActionListener(e -> trailingIcon()); panel1.add(trailingIconCheckBox, "cell 0 6 2 1,alignx left,growx 0"); + + //---- leadingComponentCheckBox ---- + leadingComponentCheckBox.setText("leading component"); + leadingComponentCheckBox.setName("leadingComponentCheckBox"); + leadingComponentCheckBox.addActionListener(e -> leadingComponent()); + panel1.add(leadingComponentCheckBox, "cell 0 7 2 1,alignx left,growx 0"); + + //---- trailingComponentCheckBox ---- + trailingComponentCheckBox.setText("trailing component"); + trailingComponentCheckBox.setName("trailingComponentCheckBox"); + trailingComponentCheckBox.addActionListener(e -> trailingComponent()); + panel1.add(trailingComponentCheckBox, "cell 0 8 2 1,alignx left,growx 0"); } add(panel1, "cell 4 0 1 6,aligny top,growy 0"); @@ -627,6 +672,8 @@ public class FlatTextComponentsTest private JSpinner bottomPaddingField; private JCheckBox leadingIconCheckBox; private JCheckBox trailingIconCheckBox; + private JCheckBox leadingComponentCheckBox; + private JCheckBox trailingComponentCheckBox; 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 5a340765..6eac474e 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": "[][][][][][][]" + "$rowConstraints": "[][][][][][]0[][]0[]" } ) { name: "panel1" "border": new javax.swing.border.TitledBorder( "Control" ) @@ -168,6 +168,26 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 6 2 1,alignx left,growx 0" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "leadingComponentCheckBox" + "text": "leading component" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "leadingComponent", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 7 2 1,alignx left,growx 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "trailingComponentCheckBox" + "text": "trailing component" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "trailingComponent", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 8 2 1,alignx left,growx 0" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 4 0 1 6,aligny top,growy 0" } ) From 51be7ad832a7365cab5a7ff773d7df3f68010a57 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sun, 12 Dec 2021 00:42:15 +0100 Subject: [PATCH 2/5] TextField: require JComponent for leading and trailing components (to allow setting a style class client property) --- .../formdev/flatlaf/FlatClientProperties.java | 4 ++-- .../com/formdev/flatlaf/ui/FlatTextFieldUI.java | 16 ++++++++-------- .../components/FlatFormattedTextField.java | 14 +++++++------- .../extras/components/FlatPasswordField.java | 14 +++++++------- .../flatlaf/extras/components/FlatTextField.java | 14 +++++++------- 5 files changed, 31 insertions(+), 31 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 ed3f3acc..dd5e1242 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -877,7 +877,7 @@ public interface FlatClientProperties * (see {@link #OUTLINE}. *

* Component {@link javax.swing.JTextField} (and subclasses)
- * Value type {@link java.awt.Component} + * Value type {@link javax.swing.JComponent} * * @since 2 */ @@ -897,7 +897,7 @@ public interface FlatClientProperties * (see {@link #OUTLINE}. *

* Component {@link javax.swing.JTextField} (and subclasses)
- * Value type {@link java.awt.Component} + * Value type {@link javax.swing.JComponent} * * @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 60db8663..3f939472 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 @@ -97,8 +97,8 @@ public class FlatTextFieldUI /** @since 2 */ @Styleable protected Icon leadingIcon; /** @since 2 */ @Styleable protected Icon trailingIcon; - /** @since 2 */ protected Component leadingComponent; - /** @since 2 */ protected Component trailingComponent; + /** @since 2 */ protected JComponent leadingComponent; + /** @since 2 */ protected JComponent trailingComponent; private Color oldDisabledBackground; private Color oldInactiveBackground; @@ -554,8 +554,8 @@ debug*/ boolean ltr = isLeftToRight(); // remove width of leading/trailing components - Component leftComponent = ltr ? leadingComponent : trailingComponent; - Component rightComponent = ltr ? trailingComponent : leadingComponent; + JComponent leftComponent = ltr ? leadingComponent : trailingComponent; + JComponent rightComponent = ltr ? trailingComponent : leadingComponent; if( leftComponent != null ) { int w = leftComponent.getPreferredSize().width; r.x += w; @@ -634,7 +634,7 @@ debug*/ /** @since 2 */ protected void installLeadingComponent() { JTextComponent c = getComponent(); - leadingComponent = clientProperty( c, TEXT_FIELD_LEADING_COMPONENT, null, Component.class ); + leadingComponent = clientProperty( c, TEXT_FIELD_LEADING_COMPONENT, null, JComponent.class ); if( leadingComponent != null ) { installLayout(); c.add( leadingComponent ); @@ -644,7 +644,7 @@ debug*/ /** @since 2 */ protected void installTrailingComponent() { JTextComponent c = getComponent(); - trailingComponent = clientProperty( c, TEXT_FIELD_TRAILING_COMPONENT, null, Component.class ); + trailingComponent = clientProperty( c, TEXT_FIELD_TRAILING_COMPONENT, null, JComponent.class ); if( trailingComponent != null ) { installLayout(); c.add( trailingComponent ); @@ -718,8 +718,8 @@ debug*/ int ow = FlatUIUtils.getBorderFocusAndLineWidth( getComponent() ); int h = parent.getHeight() - ow - ow; boolean ltr = isLeftToRight(); - Component leftComponent = ltr ? leadingComponent : trailingComponent; - Component rightComponent = ltr ? trailingComponent : leadingComponent; + JComponent leftComponent = ltr ? leadingComponent : trailingComponent; + JComponent rightComponent = ltr ? trailingComponent : leadingComponent; // layout left component if( leftComponent != null && leftComponent.isVisible() ) { 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 54126d8d..326930f7 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 @@ -18,9 +18,9 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; -import java.awt.Component; import java.awt.Insets; import javax.swing.Icon; +import javax.swing.JComponent; import javax.swing.JFormattedTextField; import com.formdev.flatlaf.extras.components.FlatTextField.SelectAllOnFocusPolicy; @@ -91,8 +91,8 @@ public class FlatFormattedTextField * * @since 2 */ - public Component getLeadingComponent() { - return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); + public JComponent getLeadingComponent() { + return (JComponent) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); } /** @@ -110,7 +110,7 @@ public class FlatFormattedTextField * * @since 2 */ - public void setLeadingComponent( Component leadingComponent ) { + public void setLeadingComponent( JComponent leadingComponent ) { putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent ); } @@ -120,8 +120,8 @@ public class FlatFormattedTextField * * @since 2 */ - public Component getTrailingComponent() { - return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); + public JComponent getTrailingComponent() { + return (JComponent) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); } /** @@ -139,7 +139,7 @@ public class FlatFormattedTextField * * @since 2 */ - public void setTrailingComponent( Component trailingComponent ) { + public void setTrailingComponent( JComponent trailingComponent ) { putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent ); } 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 392db28e..cd7f2374 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 @@ -18,9 +18,9 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; -import java.awt.Component; import java.awt.Insets; import javax.swing.Icon; +import javax.swing.JComponent; import javax.swing.JPasswordField; import com.formdev.flatlaf.extras.components.FlatTextField.SelectAllOnFocusPolicy; @@ -91,8 +91,8 @@ public class FlatPasswordField * * @since 2 */ - public Component getLeadingComponent() { - return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); + public JComponent getLeadingComponent() { + return (JComponent) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); } /** @@ -110,7 +110,7 @@ public class FlatPasswordField * * @since 2 */ - public void setLeadingComponent( Component leadingComponent ) { + public void setLeadingComponent( JComponent leadingComponent ) { putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent ); } @@ -120,8 +120,8 @@ public class FlatPasswordField * * @since 2 */ - public Component getTrailingComponent() { - return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); + public JComponent getTrailingComponent() { + return (JComponent) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); } /** @@ -139,7 +139,7 @@ public class FlatPasswordField * * @since 2 */ - public void setTrailingComponent( Component trailingComponent ) { + public void setTrailingComponent( JComponent trailingComponent ) { putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent ); } 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 9bd0f98a..c7747bf5 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 @@ -18,9 +18,9 @@ package com.formdev.flatlaf.extras.components; import static com.formdev.flatlaf.FlatClientProperties.*; import java.awt.Color; -import java.awt.Component; import java.awt.Insets; import javax.swing.Icon; +import javax.swing.JComponent; import javax.swing.JTextField; /** @@ -90,8 +90,8 @@ public class FlatTextField * * @since 2 */ - public Component getLeadingComponent() { - return (Component) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); + public JComponent getLeadingComponent() { + return (JComponent) getClientProperty( TEXT_FIELD_LEADING_COMPONENT ); } /** @@ -109,7 +109,7 @@ public class FlatTextField * * @since 2 */ - public void setLeadingComponent( Component leadingComponent ) { + public void setLeadingComponent( JComponent leadingComponent ) { putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent ); } @@ -119,8 +119,8 @@ public class FlatTextField * * @since 2 */ - public Component getTrailingComponent() { - return (Component) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); + public JComponent getTrailingComponent() { + return (JComponent) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT ); } /** @@ -138,7 +138,7 @@ public class FlatTextField * * @since 2 */ - public void setTrailingComponent( Component trailingComponent ) { + public void setTrailingComponent( JComponent trailingComponent ) { putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent ); } From 1b3cc223daaba6dddf8a14691387c59e3c2f8f0c Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Sun, 12 Dec 2021 18:43:29 +0100 Subject: [PATCH 3/5] TextField: added styles for buttons and toolbars in leading and trailing components (smaller margins/insets, better hover/pressed/selected colors) --- .../com/formdev/flatlaf/UIDefaultsLoader.java | 6 ++++ .../formdev/flatlaf/ui/FlatTextFieldUI.java | 35 ++++++++++++++----- .../formdev/flatlaf/FlatDarkLaf.properties | 16 +++++++++ .../com/formdev/flatlaf/FlatLaf.properties | 18 ++++++++++ .../formdev/flatlaf/FlatLightLaf.properties | 16 +++++++++ .../dumps/uidefaults/FlatDarkLaf_1.8.0.txt | 20 +++++++++++ .../dumps/uidefaults/FlatLightLaf_1.8.0.txt | 20 +++++++++++ .../dumps/uidefaults/FlatTestLaf_1.8.0.txt | 20 +++++++++++ .../flatlaf/testing/FlatTestLaf.properties | 12 +++++++ .../flatlaf/themeeditor/FlatLafUIKeys.txt | 4 +++ 10 files changed, 159 insertions(+), 8 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java index 8e641c95..165c407f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/UIDefaultsLoader.java @@ -364,6 +364,12 @@ class UIDefaultsLoader if( resultValueType == null ) resultValueType = tempResultValueType; + // do not parse styles here + if( key.startsWith( "[style]" ) ) { + resultValueType[0] = ValueType.STRING; + return value; + } + value = value.trim(); // null 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 3f939472..b6946080 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 @@ -21,6 +21,7 @@ import static com.formdev.flatlaf.util.UIScale.scale; import java.awt.Color; import java.awt.Component; import java.awt.Container; +import java.awt.Cursor; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics; @@ -35,10 +36,13 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.Icon; +import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JSpinner; import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; @@ -556,19 +560,19 @@ debug*/ // remove width of leading/trailing components JComponent leftComponent = ltr ? leadingComponent : trailingComponent; JComponent rightComponent = ltr ? trailingComponent : leadingComponent; - if( leftComponent != null ) { + 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; } - if( rightComponent != null ) + 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 - if( (ltr ? hasLeadingIcon() : hasTrailingIcon()) || - (leftComponent != null && leftComponent.isVisible()) ) - { + if( leftVisible || (ltr ? hasLeadingIcon() : hasTrailingIcon()) ) { // reduce left margin Insets margin = getComponent().getMargin(); int newLeftMargin = Math.min( margin.left, margin.top ); @@ -578,9 +582,7 @@ debug*/ r.width += diff; } } - if( (ltr ? hasTrailingIcon() : hasLeadingIcon()) || - (rightComponent != null && rightComponent.isVisible()) ) - { + if( rightVisible || (ltr ? hasTrailingIcon() : hasLeadingIcon()) ) { // reduce right margin Insets margin = getComponent().getMargin(); int newRightMargin = Math.min( margin.right, margin.top ); @@ -636,6 +638,7 @@ debug*/ JTextComponent c = getComponent(); leadingComponent = clientProperty( c, TEXT_FIELD_LEADING_COMPONENT, null, JComponent.class ); if( leadingComponent != null ) { + prepareLeadingOrTrailingComponent( leadingComponent ); installLayout(); c.add( leadingComponent ); } @@ -646,6 +649,7 @@ debug*/ JTextComponent c = getComponent(); trailingComponent = clientProperty( c, TEXT_FIELD_TRAILING_COMPONENT, null, JComponent.class ); if( trailingComponent != null ) { + prepareLeadingOrTrailingComponent( trailingComponent ); installLayout(); c.add( trailingComponent ); } @@ -667,6 +671,21 @@ debug*/ } } + /** @since 2 */ + protected void prepareLeadingOrTrailingComponent( JComponent c ) { + c.putClientProperty( STYLE_CLASS, "inTextField" ); + c.setCursor( Cursor.getDefaultCursor() ); + + if( c instanceof JButton || c instanceof JToggleButton ) + c.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON ); + else if( c instanceof JToolBar ) { + for( Component child : c.getComponents() ) { + if( child instanceof JComponent ) + ((JComponent)child).putClientProperty( STYLE_CLASS, "inTextField" ); + } + } + } + private void installLayout() { JTextComponent c = getComponent(); LayoutManager oldLayout = c.getLayout(); diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties index 82c080a7..9307635e 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties @@ -355,3 +355,19 @@ ToolTip.background = shade(@background,50%) #---- Tree ---- Tree.hash = lighten($Tree.background,5%) + + + +#---- Styles ------------------------------------------------------------------ + +#---- inTextField ---- +# for leading/trailing components in text fields + +[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-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties index 33340e78..53879b71 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties @@ -227,6 +227,7 @@ Button.defaultButtonFollowsFocus = false Button.borderWidth = 1 Button.default.borderWidth = 1 +# for buttons in toolbars Button.toolbar.margin = 3,3,3,3 Button.toolbar.spacingInsets = 1,2,1,2 @@ -889,3 +890,20 @@ Tree.icon.collapsedColor = @icon Tree.icon.leafColor = @icon Tree.icon.closedColor = @icon Tree.icon.openColor = @icon + + + +#---- Styles ------------------------------------------------------------------ + +#---- inTextField ---- +# for leading/trailing components in text fields + +[style]ToggleButton.inTextField = $[style]Button.inTextField + +[style]ToolBar.inTextField = \ + floatable: false; \ + opaque: false; \ + borderMargins: 0,0,0,0 + +[style]ToolBarSeparator.inTextField = \ + separatorWidth: 3 diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties index a0ab8a28..9be66470 100644 --- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties +++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties @@ -362,3 +362,19 @@ ToolTip.background = lighten(@background,3%) #---- Tree ---- Tree.hash = darken($Tree.background,10%) + + + +#---- Styles ------------------------------------------------------------------ + +#---- inTextField ---- +# for leading/trailing components in text fields + +[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/FlatDarkLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt index 5d305543..7cf0ed6a 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatDarkLaf_1.8.0.txt @@ -1419,6 +1419,26 @@ ViewportUI com.formdev.flatlaf.ui.FlatViewportUI [style].small font: $small.font +#---- [style]Button ---- + +[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) + + +#---- [style]ToggleButton ---- + +[style]ToggleButton.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) + + +#---- [style]ToolBar ---- + +[style]ToolBar.inTextField floatable: false; opaque: false; borderMargins: 0,0,0,0 + + +#---- [style]ToolBarSeparator ---- + +[style]ToolBarSeparator.inTextField separatorWidth: 3 + + #---- ---- activeCaption #434e60 HSL 217 18 32 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt index d9efdd96..c0ae8ece 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatLightLaf_1.8.0.txt @@ -1424,6 +1424,26 @@ ViewportUI com.formdev.flatlaf.ui.FlatViewportUI [style].small font: $small.font +#---- [style]Button ---- + +[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) + + +#---- [style]ToggleButton ---- + +[style]ToggleButton.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) + + +#---- [style]ToolBar ---- + +[style]ToolBar.inTextField floatable: false; opaque: false; borderMargins: 0,0,0,0 + + +#---- [style]ToolBarSeparator ---- + +[style]ToolBarSeparator.inTextField separatorWidth: 3 + + #---- ---- activeCaption #99b4d1 HSL 211 38 71 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt index 43836b5f..be298499 100644 --- a/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt +++ b/flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0.txt @@ -1437,6 +1437,26 @@ ViewportUI com.formdev.flatlaf.ui.FlatViewportUI [style].small font: $small.font +#---- [style]Button ---- + +[style]Button.inTextField focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1 + + +#---- [style]ToggleButton ---- + +[style]ToggleButton.inTextField focusable: false; toolbar.margin: 1,1,1,1; toolbar.spacingInsets: 1,1,1,1 + + +#---- [style]ToolBar ---- + +[style]ToolBar.inTextField floatable: false; opaque: false; borderMargins: 0,0,0,0 + + +#---- [style]ToolBarSeparator ---- + +[style]ToolBarSeparator.inTextField separatorWidth: 3 + + #---- ---- activeCaption #99b4d1 HSL 211 38 71 javax.swing.plaf.ColorUIResource [UI] diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties index 9e47fa47..98fd7fdb 100644 --- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties +++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/FlatTestLaf.properties @@ -443,3 +443,15 @@ Tree.paintLines = true Tree.hash = #f00 Tree.editorBorder = 1,1,1,1,#f00 Tree.editorBorderSelectionColor = #00f + + + +#---- Styles ------------------------------------------------------------------ + +#---- inTextField ---- +# for leading/trailing components in text fields + +[style]Button.inTextField = \ + focusable: false; \ + toolbar.margin: 1,1,1,1; \ + toolbar.spacingInsets: 1,1,1,1 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 c9e7c778..3257247b 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,10 @@ ViewportUI [style].monospaced [style].semibold [style].small +[style]Button.inTextField +[style]ToggleButton.inTextField +[style]ToolBar.inTextField +[style]ToolBarSeparator.inTextField activeCaption activeCaptionBorder activeCaptionText From 73c37b2018197185d54a4ea722c77e569b6a70a0 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 13 Dec 2021 00:47:23 +0100 Subject: [PATCH 4/5] Search/clear icons: option to ignore button state (hover/pressed) for usage where button background changes color on hover/pressed --- .../com/formdev/flatlaf/icons/FlatClearIcon.java | 10 +++++++++- .../com/formdev/flatlaf/icons/FlatSearchIcon.java | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java index edce46f9..30f691c4 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatClearIcon.java @@ -47,8 +47,16 @@ public class FlatClearIcon @Styleable protected Color clearIconHoverColor = UIManager.getColor( "SearchField.clearIconHoverColor" ); @Styleable protected Color clearIconPressedColor = UIManager.getColor( "SearchField.clearIconPressedColor" ); + private final boolean ignoreButtonState; + public FlatClearIcon() { + this( false ); + } + + /** @since 2 */ + public FlatClearIcon( boolean ignoreButtonState ) { super( 16, 16, null ); + this.ignoreButtonState = ignoreButtonState; } /** @since 2 */ @@ -63,7 +71,7 @@ public class FlatClearIcon @Override protected void paintIcon( Component c, Graphics2D g ) { - if( c instanceof AbstractButton ) { + if( !ignoreButtonState && c instanceof AbstractButton ) { ButtonModel model = ((AbstractButton)c).getModel(); if( model.isPressed() || model.isRollover() ) { /* diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java index 89fd7af0..e9f72ffa 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java @@ -45,8 +45,16 @@ public class FlatSearchIcon @Styleable protected Color searchIconHoverColor = UIManager.getColor( "SearchField.searchIconHoverColor" ); @Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" ); + private final boolean ignoreButtonState; + public FlatSearchIcon() { + this( false ); + } + + /** @since 2 */ + public FlatSearchIcon( boolean ignoreButtonState ) { super( 16, 16, null ); + this.ignoreButtonState = ignoreButtonState; } /** @since 2 */ @@ -70,8 +78,10 @@ public class FlatSearchIcon */ - g.setColor( FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor, - null, searchIconHoverColor, searchIconPressedColor ) ); + g.setColor( ignoreButtonState + ? searchIconColor + : FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor, + null, searchIconHoverColor, searchIconPressedColor ) ); // paint magnifier Area area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) ); From 60e2ffac5fbfded311fb48697277777f50729220 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Mon, 13 Dec 2021 16:31:27 +0100 Subject: [PATCH 5/5] Demo: added text field leading/trailing components example --- .../icons/FlatSearchWithHistoryIcon.java | 6 ++ .../flatlaf/demo/BasicComponentsPanel.java | 80 +++++++++++++++---- .../flatlaf/demo/BasicComponentsPanel.jfd | 50 +++++++----- .../com/formdev/flatlaf/demo/FlatLafDemo.java | 2 +- .../formdev/flatlaf/demo/icons/matchCase.svg | 9 +++ .../flatlaf/demo/icons/matchCaseHovered.svg | 9 +++ .../flatlaf/demo/icons/matchCaseSelected.svg | 9 +++ .../com/formdev/flatlaf/demo/icons/regex.svg | 7 ++ .../flatlaf/demo/icons/regexHovered.svg | 7 ++ .../flatlaf/demo/icons/regexSelected.svg | 7 ++ .../com/formdev/flatlaf/demo/icons/words.svg | 6 ++ .../flatlaf/demo/icons/wordsHovered.svg | 6 ++ .../flatlaf/demo/icons/wordsSelected.svg | 6 ++ .../testing/FlatTextComponentsTest.java | 47 ++++++++++- .../testing/FlatTextComponentsTest.jfd | 26 +++++- 15 files changed, 238 insertions(+), 39 deletions(-) create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCase.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseHovered.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseSelected.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regex.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexHovered.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexSelected.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/words.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsHovered.svg create mode 100644 flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsSelected.svg diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchWithHistoryIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchWithHistoryIcon.java index 262bb8fc..d8a4e00b 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchWithHistoryIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchWithHistoryIcon.java @@ -30,6 +30,12 @@ public class FlatSearchWithHistoryIcon extends FlatSearchIcon { public FlatSearchWithHistoryIcon() { + this( false ); + } + + /** @since 2 */ + public FlatSearchWithHistoryIcon( boolean ignoreButtonState ) { + super( ignoreButtonState ); } @Override 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 02455ce9..dc9e05e3 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 @@ -22,6 +22,7 @@ import javax.swing.text.DefaultEditorKit; import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.extras.FlatSVGIcon; import com.formdev.flatlaf.icons.FlatSearchIcon; +import com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon; import net.miginfocom.layout.AC; import net.miginfocom.layout.BoundSize; import net.miginfocom.layout.ConstraintParser; @@ -36,6 +37,42 @@ class BasicComponentsPanel { BasicComponentsPanel() { initComponents(); + + // search history button + JButton searchHistoryButton = new JButton( new FlatSearchWithHistoryIcon( true ) ); + searchHistoryButton.setToolTipText( "Search History" ); + searchHistoryButton.addActionListener( e -> { + JPopupMenu popupMenu = new JPopupMenu(); + popupMenu.add( "(empty)" ); + popupMenu.show( searchHistoryButton, 0, searchHistoryButton.getHeight() ); + } ); + compsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_COMPONENT, searchHistoryButton ); + + // match case button + JToggleButton matchCaseButton = new JToggleButton( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/matchCase.svg" ) ); + matchCaseButton.setRolloverIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/matchCaseHovered.svg" ) ); + matchCaseButton.setSelectedIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/matchCaseSelected.svg" ) ); + matchCaseButton.setToolTipText( "Match Case" ); + + // whole words button + JToggleButton wordsButton = new JToggleButton( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/words.svg" ) ); + wordsButton.setRolloverIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/wordsHovered.svg" ) ); + wordsButton.setSelectedIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/wordsSelected.svg" ) ); + wordsButton.setToolTipText( "Whole Words" ); + + // regex button + JToggleButton regexButton = new JToggleButton( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/regex.svg" ) ); + regexButton.setRolloverIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/regexHovered.svg" ) ); + regexButton.setSelectedIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/regexSelected.svg" ) ); + regexButton.setToolTipText( "Regular Expression" ); + + // search toolbar + JToolBar searchToolbar = new JToolBar(); + searchToolbar.add( matchCaseButton ); + searchToolbar.add( wordsButton ); + searchToolbar.addSeparator(); + searchToolbar.add( regexButton ); + compsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT, searchToolbar ); } private void initComponents() { @@ -134,6 +171,8 @@ class BasicComponentsPanel JTextField leadingIconTextField = new JTextField(); JTextField trailingIconTextField = new JTextField(); JTextField iconsTextField = new JTextField(); + JLabel compsLabel = new JLabel(); + compsTextField = new JTextField(); JLabel fontsLabel = new JLabel(); JLabel h00Label = new JLabel(); JLabel h0Label = new JLabel(); @@ -181,6 +220,7 @@ class BasicComponentsPanel "[]" + "[]" + "[]" + + "[]" + "[]0" + "[]")); @@ -689,84 +729,89 @@ class BasicComponentsPanel iconsTextField.setText("text"); add(iconsTextField, "cell 3 14,growx"); + //---- compsLabel ---- + compsLabel.setText("Leading/trailing comp.:"); + add(compsLabel, "cell 0 15"); + add(compsTextField, "cell 1 15 2 1,growx"); + //---- fontsLabel ---- fontsLabel.setText("Typography / Fonts:"); - add(fontsLabel, "cell 0 15"); + add(fontsLabel, "cell 0 16"); //---- h00Label ---- h00Label.setText("H00"); h00Label.putClientProperty("FlatLaf.styleClass", "h00"); - add(h00Label, "cell 1 15 5 1"); + add(h00Label, "cell 1 16 5 1"); //---- h0Label ---- h0Label.setText("H0"); h0Label.putClientProperty("FlatLaf.styleClass", "h0"); - add(h0Label, "cell 1 15 5 1"); + add(h0Label, "cell 1 16 5 1"); //---- h1Label ---- h1Label.setText("H1"); h1Label.putClientProperty("FlatLaf.styleClass", "h1"); - add(h1Label, "cell 1 15 5 1"); + add(h1Label, "cell 1 16 5 1"); //---- h2Label ---- h2Label.setText("H2"); h2Label.putClientProperty("FlatLaf.styleClass", "h2"); - add(h2Label, "cell 1 15 5 1"); + add(h2Label, "cell 1 16 5 1"); //---- h3Label ---- h3Label.setText("H3"); h3Label.putClientProperty("FlatLaf.styleClass", "h3"); - add(h3Label, "cell 1 15 5 1"); + add(h3Label, "cell 1 16 5 1"); //---- h4Label ---- h4Label.setText("H4"); h4Label.putClientProperty("FlatLaf.styleClass", "h4"); - add(h4Label, "cell 1 15 5 1"); + add(h4Label, "cell 1 16 5 1"); //---- lightLabel ---- lightLabel.setText("light"); lightLabel.putClientProperty("FlatLaf.style", "font: 200% $light.font"); - add(lightLabel, "cell 1 15 5 1,gapx 30"); + add(lightLabel, "cell 1 16 5 1,gapx 30"); //---- semiboldLabel ---- semiboldLabel.setText("semibold"); semiboldLabel.putClientProperty("FlatLaf.style", "font: 200% $semibold.font"); - add(semiboldLabel, "cell 1 15 5 1"); + add(semiboldLabel, "cell 1 16 5 1"); //---- fontZoomLabel ---- fontZoomLabel.setText("(200%)"); fontZoomLabel.putClientProperty("FlatLaf.styleClass", "small"); fontZoomLabel.setEnabled(false); - add(fontZoomLabel, "cell 1 15 5 1"); + add(fontZoomLabel, "cell 1 16 5 1"); //---- largeLabel ---- largeLabel.setText("large"); largeLabel.putClientProperty("FlatLaf.styleClass", "large"); - add(largeLabel, "cell 1 16 5 1"); + add(largeLabel, "cell 1 17 5 1"); //---- defaultLabel ---- defaultLabel.setText("default"); - add(defaultLabel, "cell 1 16 5 1"); + add(defaultLabel, "cell 1 17 5 1"); //---- mediumLabel ---- mediumLabel.setText("medium"); mediumLabel.putClientProperty("FlatLaf.styleClass", "medium"); - add(mediumLabel, "cell 1 16 5 1"); + add(mediumLabel, "cell 1 17 5 1"); //---- smallLabel ---- smallLabel.setText("small"); smallLabel.putClientProperty("FlatLaf.styleClass", "small"); - add(smallLabel, "cell 1 16 5 1"); + add(smallLabel, "cell 1 17 5 1"); //---- miniLabel ---- miniLabel.setText("mini"); miniLabel.putClientProperty("FlatLaf.styleClass", "mini"); - add(miniLabel, "cell 1 16 5 1"); + add(miniLabel, "cell 1 17 5 1"); //---- monospacedLabel ---- monospacedLabel.setText("monospaced"); monospacedLabel.putClientProperty("FlatLaf.styleClass", "monospaced"); - add(monospacedLabel, "cell 1 16 5 1,gapx 30"); + add(monospacedLabel, "cell 1 17 5 1,gapx 30"); //======== popupMenu1 ======== { @@ -841,7 +886,7 @@ class BasicComponentsPanel rows[11].setGapAfter( zeroGap ); rows[12].setGapBefore( zeroGap ); rows[13].setGapBefore( zeroGap ); - rows[15].setGapBefore( zeroGap ); + rows[16].setGapBefore( zeroGap ); layout.setRowConstraints( ac ); // move two text field into same row as spinners @@ -859,5 +904,6 @@ class BasicComponentsPanel } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + private JTextField compsTextField; // 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 f1a7e69a..c5eb1554 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 @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8" +JFDML JFormDesigner: "7.0.5.0.404" Java: "17" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -9,7 +9,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "insets dialog,hidemode 3" "$columnConstraints": "[][sizegroup 1][sizegroup 1][sizegroup 1][][]" - "$rowConstraints": "[][][][][][][][][][][][]para[][][][]0[]" + "$rowConstraints": "[][][][][][][][][][][][]para[][][][][]0[]" } ) { name: "this" add( new FormComponent( "javax.swing.JLabel" ) { @@ -671,67 +671,81 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 3 14,growx" } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "compsLabel" + "text": "Leading/trailing comp.:" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 15" + } ) + add( new FormComponent( "javax.swing.JTextField" ) { + name: "compsTextField" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 15 2 1,growx" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "fontsLabel" "text": "Typography / Fonts:" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 0 15" + "value": "cell 0 16" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "h00Label" "text": "H00" "$client.FlatLaf.styleClass": "h00" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "h0Label" "text": "H0" "$client.FlatLaf.styleClass": "h0" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "h1Label" "text": "H1" "$client.FlatLaf.styleClass": "h1" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "h2Label" "text": "H2" "$client.FlatLaf.styleClass": "h2" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "h3Label" "text": "H3" "$client.FlatLaf.styleClass": "h3" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "h4Label" "text": "H4" "$client.FlatLaf.styleClass": "h4" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "lightLabel" "text": "light" "$client.FlatLaf.style": "font: 200% $light.font" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1,gapx 30" + "value": "cell 1 16 5 1,gapx 30" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "semiboldLabel" "text": "semibold" "$client.FlatLaf.style": "font: 200% $semibold.font" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "fontZoomLabel" @@ -739,48 +753,48 @@ new FormModel { "$client.FlatLaf.styleClass": "small" "enabled": false }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 15 5 1" + "value": "cell 1 16 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "largeLabel" "text": "large" "$client.FlatLaf.styleClass": "large" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 16 5 1" + "value": "cell 1 17 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "defaultLabel" "text": "default" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 16 5 1" + "value": "cell 1 17 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "mediumLabel" "text": "medium" "$client.FlatLaf.styleClass": "medium" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 16 5 1" + "value": "cell 1 17 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "smallLabel" "text": "small" "$client.FlatLaf.styleClass": "small" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 16 5 1" + "value": "cell 1 17 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "miniLabel" "text": "mini" "$client.FlatLaf.styleClass": "mini" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 16 5 1" + "value": "cell 1 17 5 1" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "monospacedLabel" "text": "monospaced" "$client.FlatLaf.styleClass": "monospaced" }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 1 16 5 1,gapx 30" + "value": "cell 1 17 5 1,gapx 30" } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/FlatLafDemo.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/FlatLafDemo.java index 9a78afe1..7bca3551 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/FlatLafDemo.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/FlatLafDemo.java @@ -72,7 +72,7 @@ public class FlatLafDemo DemoFrame frame = new DemoFrame(); if( FlatLafDemo.screenshotsMode ) - frame.setPreferredSize( new Dimension( 1660, 840 ) ); + frame.setPreferredSize( new Dimension( 1660, 880 ) ); // show frame frame.pack(); diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCase.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCase.svg new file mode 100644 index 00000000..64b341ed --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCase.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseHovered.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseHovered.svg new file mode 100644 index 00000000..e07af386 --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseHovered.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseSelected.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseSelected.svg new file mode 100644 index 00000000..6be2c27e --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/matchCaseSelected.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regex.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regex.svg new file mode 100644 index 00000000..f073c590 --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regex.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexHovered.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexHovered.svg new file mode 100644 index 00000000..545853d7 --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexHovered.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexSelected.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexSelected.svg new file mode 100644 index 00000000..29a9c56d --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/regexSelected.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/words.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/words.svg new file mode 100644 index 00000000..e427f911 --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/words.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsHovered.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsHovered.svg new file mode 100644 index 00000000..d99d09d6 --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsHovered.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsSelected.svg b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsSelected.svg new file mode 100644 index 00000000..21533311 --- /dev/null +++ b/flatlaf-demo/src/main/resources/com/formdev/flatlaf/demo/icons/wordsSelected.svg @@ -0,0 +1,6 @@ + + + + + + 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 1af9ec05..a0c66148 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 @@ -80,6 +80,7 @@ public class FlatTextComponentsTest JLabel l = new JLabel( "lead" ); l.setOpaque( true ); l.setBackground( Color.green ); + l.setVisible( leadingComponentVisibleCheckBox.isSelected() ); return l; } ); } @@ -92,10 +93,34 @@ public class FlatTextComponentsTest JLabel l = new JLabel( "tr" ); l.setOpaque( true ); l.setBackground( Color.magenta ); + l.setVisible( trailingComponentVisibleCheckBox.isSelected() ); return l; } ); } + private void leadingComponentVisible() { + setLeadingTrailingComponentVisible( FlatClientProperties.TEXT_FIELD_LEADING_COMPONENT, + leadingComponentVisibleCheckBox.isSelected() ); + } + + private void trailingComponentVisible() { + setLeadingTrailingComponentVisible( FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT, + trailingComponentVisibleCheckBox.isSelected() ); + } + + private void setLeadingTrailingComponentVisible( String key, boolean visible ) { + for( Component c : getComponents() ) { + if( c instanceof JTextField ) { + Object value = ((JTextField)c).getClientProperty( key ); + if( value instanceof JComponent ) { + ((JComponent)value).setVisible( visible ); + c.revalidate(); + c.repaint(); + } + } + } + } + private void putTextFieldClientProperty( String key, Object value ) { for( Component c : getComponents() ) { if( c instanceof JTextField ) @@ -141,6 +166,8 @@ public class FlatTextComponentsTest trailingIconCheckBox = new JCheckBox(); leadingComponentCheckBox = new JCheckBox(); trailingComponentCheckBox = new JCheckBox(); + leadingComponentVisibleCheckBox = new JCheckBox(); + trailingComponentVisibleCheckBox = new JCheckBox(); JLabel passwordFieldLabel = new JLabel(); JPasswordField passwordField1 = new JPasswordField(); JPasswordField passwordField3 = new JPasswordField(); @@ -290,6 +317,8 @@ public class FlatTextComponentsTest "[]0" + "[]" + "[]0" + + "[]" + + "[]0" + "[]")); //---- button1 ---- @@ -361,8 +390,22 @@ public class FlatTextComponentsTest trailingComponentCheckBox.setName("trailingComponentCheckBox"); trailingComponentCheckBox.addActionListener(e -> trailingComponent()); panel1.add(trailingComponentCheckBox, "cell 0 8 2 1,alignx left,growx 0"); + + //---- leadingComponentVisibleCheckBox ---- + leadingComponentVisibleCheckBox.setText("leading component visible"); + leadingComponentVisibleCheckBox.setSelected(true); + leadingComponentVisibleCheckBox.setName("leadingComponentVisibleCheckBox"); + leadingComponentVisibleCheckBox.addActionListener(e -> leadingComponentVisible()); + panel1.add(leadingComponentVisibleCheckBox, "cell 0 9 2 1,alignx left,growx 0"); + + //---- trailingComponentVisibleCheckBox ---- + trailingComponentVisibleCheckBox.setText("trailing component visible"); + trailingComponentVisibleCheckBox.setSelected(true); + trailingComponentVisibleCheckBox.setName("trailingComponentVisibleCheckBox"); + trailingComponentVisibleCheckBox.addActionListener(e -> trailingComponentVisible()); + panel1.add(trailingComponentVisibleCheckBox, "cell 0 10 2 1,alignx left,growx 0"); } - add(panel1, "cell 4 0 1 6,aligny top,growy 0"); + add(panel1, "cell 4 0 1 10,aligny top,growy 0"); //---- passwordFieldLabel ---- passwordFieldLabel.setText("JPasswordField:"); @@ -674,6 +717,8 @@ public class FlatTextComponentsTest private JCheckBox trailingIconCheckBox; private JCheckBox leadingComponentCheckBox; private JCheckBox trailingComponentCheckBox; + private JCheckBox leadingComponentVisibleCheckBox; + private JCheckBox trailingComponentVisibleCheckBox; 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 6eac474e..2dfcfb7b 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[]" + "$rowConstraints": "[][][][][][]0[][]0[][]0[]" } ) { name: "panel1" "border": new javax.swing.border.TitledBorder( "Control" ) @@ -188,8 +188,30 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 8 2 1,alignx left,growx 0" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "leadingComponentVisibleCheckBox" + "text": "leading component visible" + "selected": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "leadingComponentVisible", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 9 2 1,alignx left,growx 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "trailingComponentVisibleCheckBox" + "text": "trailing component visible" + "selected": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "trailingComponentVisible", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 10 2 1,alignx left,growx 0" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { - "value": "cell 4 0 1 6,aligny top,growy 0" + "value": "cell 4 0 1 10,aligny top,growy 0" } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "passwordFieldLabel"