diff --git a/CHANGELOG.md b/CHANGELOG.md index eff57deb..a1debe25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ FlatLaf Change Log #### New features and improvements +- TextField, FormattedTextField and PasswordField: Support adding extra padding. + (set client property `JTextField.padding` to `Insets`). - PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI` (instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier extensibility. 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 ff6a5aa5..dace152f 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -733,6 +733,18 @@ public interface FlatClientProperties */ String PLACEHOLDER_TEXT = "JTextField.placeholderText"; + /** + * Specifies the padding of the text. + * This changes the location and size of the text view within the component bounds, + * but does not affect the size of the component. + *
+ * Component {@link javax.swing.JTextField} (and subclasses)
+ * Value type {@link java.awt.Insets}
+ *
+ * @since 1.4
+ */
+ String TEXT_FIELD_PADDING = "JTextField.padding";
+
//---- JToggleButton ------------------------------------------------------
/**
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
index ba52ff4f..fe28e1c0 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
@@ -18,6 +18,8 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.FlatClientProperties.*;
import java.awt.EventQueue;
+import java.awt.Insets;
+import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import javax.swing.JFormattedTextField;
@@ -61,6 +63,19 @@ public class FlatCaret
}
}
+ @Override
+ protected void adjustVisibility( Rectangle nloc ) {
+ JTextComponent c = getComponent();
+ if( c != null && c.getUI() instanceof FlatTextFieldUI ) {
+ Insets padding = ((FlatTextFieldUI)c.getUI()).getPadding();
+ if( padding != null ) {
+ nloc.x -= padding.left;
+ nloc.y -= padding.top;
+ }
+ }
+ super.adjustVisibility( nloc );
+ }
+
@Override
public void focusGained( FocusEvent e ) {
if( !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
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 28bf85a5..8e9db66b 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
@@ -24,6 +24,7 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
+import java.awt.Rectangle;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComboBox;
@@ -40,6 +41,7 @@ import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.JavaCompatibility;
+import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JTextField}.
@@ -142,6 +144,7 @@ public class FlatTextFieldUI
switch( e.getPropertyName() ) {
case FlatClientProperties.PLACEHOLDER_TEXT:
case FlatClientProperties.COMPONENT_ROUND_RECT:
+ case FlatClientProperties.TEXT_FIELD_PADDING:
c.repaint();
break;
@@ -264,4 +267,27 @@ public class FlatTextFieldUI
size.width = Math.max( size.width, scale( minimumWidth ) + Math.round( focusWidth * 2 ) );
return size;
}
+
+ @Override
+ protected Rectangle getVisibleEditorRect() {
+ Rectangle r = super.getVisibleEditorRect();
+ if( r != null ) {
+ // remove padding
+ Insets padding = getPadding();
+ if( padding != null ) {
+ r = FlatUIUtils.subtractInsets( r, padding );
+ r.width = Math.max( r.width, 0 );
+ r.height = Math.max( r.height, 0 );
+ }
+ }
+ return r;
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected Insets getPadding() {
+ Object padding = getComponent().getClientProperty( FlatClientProperties.TEXT_FIELD_PADDING );
+ return (padding instanceof Insets) ? UIScale.scale( (Insets) padding ) : null;
+ }
}
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 80b68989..ecb55f42 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
@@ -16,8 +16,12 @@
package com.formdev.flatlaf.testing;
+import java.awt.Component;
+import java.awt.Insets;
import javax.swing.*;
+import javax.swing.border.*;
import javax.swing.text.DefaultEditorKit;
+import com.formdev.flatlaf.FlatClientProperties;
import net.miginfocom.swing.*;
/**
@@ -41,16 +45,40 @@ public class FlatTextComponentsTest
textField1.setText( "new text" );
}
+ private void paddingChanged() {
+ Insets padding = new Insets(
+ (int) topPaddingField.getValue(),
+ (int) leftPaddingField.getValue(),
+ (int) bottomPaddingField.getValue(),
+ (int) rightPaddingField.getValue() );
+ 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 );
+ }
+ }
+
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JLabel textFieldLabel = new JLabel();
textField1 = new JTextField();
JTextField textField3 = new JTextField();
JTextField textField2 = new JTextField();
- JButton button1 = new JButton();
JLabel formattedTextFieldLabel = new JLabel();
JFormattedTextField formattedTextField1 = new JFormattedTextField();
JFormattedTextField formattedTextField3 = new JFormattedTextField();
+ JPanel panel1 = new JPanel();
+ JButton button1 = new JButton();
+ JLabel leftPaddingLabel = new JLabel();
+ leftPaddingField = new JSpinner();
+ JLabel rightPaddingLabel = new JLabel();
+ rightPaddingField = new JSpinner();
+ JLabel topPaddingLabel = new JLabel();
+ topPaddingField = new JSpinner();
+ JLabel bottomPaddingLabel = new JLabel();
+ bottomPaddingField = new JSpinner();
JLabel passwordFieldLabel = new JLabel();
JPasswordField passwordField1 = new JPasswordField();
JPasswordField passwordField3 = new JPasswordField();
@@ -134,12 +162,6 @@ public class FlatTextComponentsTest
textField2.setName("textField2");
add(textField2, "cell 3 0");
- //---- button1 ----
- button1.setText("change text");
- button1.setName("button1");
- button1.addActionListener(e -> changeText());
- add(button1, "cell 4 0");
-
//---- formattedTextFieldLabel ----
formattedTextFieldLabel.setText("JFormattedTextField:");
formattedTextFieldLabel.setDisplayedMnemonic('F');
@@ -159,6 +181,70 @@ public class FlatTextComponentsTest
formattedTextField3.setName("formattedTextField3");
add(formattedTextField3, "cell 2 1,growx");
+ //======== panel1 ========
+ {
+ panel1.setBorder(new TitledBorder("Control"));
+ panel1.setName("panel1");
+ panel1.setLayout(new MigLayout(
+ "hidemode 3",
+ // columns
+ "[fill]" +
+ "[fill]",
+ // rows
+ "[]" +
+ "[]" +
+ "[]" +
+ "[]" +
+ "[]"));
+
+ //---- button1 ----
+ button1.setText("change text");
+ button1.setName("button1");
+ button1.addActionListener(e -> changeText());
+ panel1.add(button1, "cell 0 0 2 1,alignx left,growx 0");
+
+ //---- leftPaddingLabel ----
+ leftPaddingLabel.setText("Left padding:");
+ leftPaddingLabel.setName("leftPaddingLabel");
+ panel1.add(leftPaddingLabel, "cell 0 1");
+
+ //---- leftPaddingField ----
+ leftPaddingField.setName("leftPaddingField");
+ leftPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(leftPaddingField, "cell 1 1");
+
+ //---- rightPaddingLabel ----
+ rightPaddingLabel.setText("Right padding:");
+ rightPaddingLabel.setName("rightPaddingLabel");
+ panel1.add(rightPaddingLabel, "cell 0 2");
+
+ //---- rightPaddingField ----
+ rightPaddingField.setName("rightPaddingField");
+ rightPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(rightPaddingField, "cell 1 2");
+
+ //---- topPaddingLabel ----
+ topPaddingLabel.setText("Top padding:");
+ topPaddingLabel.setName("topPaddingLabel");
+ panel1.add(topPaddingLabel, "cell 0 3");
+
+ //---- topPaddingField ----
+ topPaddingField.setName("topPaddingField");
+ topPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(topPaddingField, "cell 1 3");
+
+ //---- bottomPaddingLabel ----
+ bottomPaddingLabel.setText("Bottom padding:");
+ bottomPaddingLabel.setName("bottomPaddingLabel");
+ panel1.add(bottomPaddingLabel, "cell 0 4");
+
+ //---- bottomPaddingField ----
+ bottomPaddingField.setName("bottomPaddingField");
+ bottomPaddingField.addChangeListener(e -> paddingChanged());
+ panel1.add(bottomPaddingField, "cell 1 4");
+ }
+ add(panel1, "cell 4 0 1 6,aligny top,growy 0");
+
//---- passwordFieldLabel ----
passwordFieldLabel.setText("JPasswordField:");
passwordFieldLabel.setDisplayedMnemonic('P');
@@ -301,7 +387,7 @@ public class FlatTextComponentsTest
comboBox3.setPrototypeDisplayValue("12345");
comboBox3.setComponentPopupMenu(popupMenu1);
comboBox3.setName("comboBox3");
- add(comboBox3, "cell 2 6,growx");
+ add(comboBox3, "cell 2 6,growx,wmin 50");
//---- spinnerLabel ----
spinnerLabel.setText("JSpinner:");
@@ -361,5 +447,9 @@ public class FlatTextComponentsTest
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JTextField textField1;
+ private JSpinner leftPaddingField;
+ private JSpinner rightPaddingField;
+ private JSpinner topPaddingField;
+ private JSpinner bottomPaddingField;
// JFormDesigner - End of variables declaration //GEN-END:variables
}
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 aa4526b3..b8bcac13 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
@@ -1,4 +1,4 @@
-JFDML JFormDesigner: "7.0.3.1.342" Java: "16" encoding: "UTF-8"
+JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -47,13 +47,6 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 3 0"
} )
- add( new FormComponent( "javax.swing.JButton" ) {
- name: "button1"
- "text": "change text"
- addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeText", false ) )
- }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 4 0"
- } )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "formattedTextFieldLabel"
"text": "JFormattedTextField:"
@@ -76,6 +69,83 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 1,growx"
} )
+ add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
+ "$layoutConstraints": "hidemode 3"
+ "$columnConstraints": "[fill][fill]"
+ "$rowConstraints": "[][][][][]"
+ } ) {
+ name: "panel1"
+ "border": new javax.swing.border.TitledBorder( "Control" )
+ add( new FormComponent( "javax.swing.JButton" ) {
+ name: "button1"
+ "text": "change text"
+ addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "changeText", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 0 2 1,alignx left,growx 0"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "leftPaddingLabel"
+ "text": "Left padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 1"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "leftPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 1"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "rightPaddingLabel"
+ "text": "Right padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 2"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "rightPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 2"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "topPaddingLabel"
+ "text": "Top padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 3"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "topPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 3"
+ } )
+ add( new FormComponent( "javax.swing.JLabel" ) {
+ name: "bottomPaddingLabel"
+ "text": "Bottom padding:"
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 0 4"
+ } )
+ add( new FormComponent( "javax.swing.JSpinner" ) {
+ name: "bottomPaddingField"
+ auxiliary() {
+ "JavaCodeGenerator.variableLocal": false
+ }
+ addEvent( new FormEvent( "javax.swing.event.ChangeListener", "stateChanged", "paddingChanged", false ) )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 1 4"
+ } )
+ }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
+ "value": "cell 4 0 1 6,aligny top,growy 0"
+ } )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "passwordFieldLabel"
"text": "JPasswordField:"
@@ -217,7 +287,7 @@ new FormModel {
"prototypeDisplayValue": "12345"
"componentPopupMenu": #FormReference0
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
- "value": "cell 2 6,growx"
+ "value": "cell 2 6,growx,wmin 50"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "spinnerLabel"