diff --git a/CHANGELOG.md b/CHANGELOG.md index bd1559d6..0be075e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ FlatLaf Change Log - FileChooser: Fixed occasional NPE in `FlatShortcutsPanel` on Windows. (issue #718) +- TextField: Fixed placeholder text painting, which did not respect horizontal + alignment property of `JTextField`. (issue #721) ## 3.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 f129d665..4211da32 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTextFieldUI.java @@ -45,6 +45,7 @@ import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -480,10 +481,22 @@ debug*/ // compute placeholder location Rectangle r = getVisibleEditorRect(); FontMetrics fm = c.getFontMetrics( c.getFont() ); - String clippedPlaceholder = JavaCompatibility.getClippedString( c, fm, placeholder, r.width ); - int x = r.x + (isLeftToRight() ? 0 : r.width - fm.stringWidth( clippedPlaceholder )); + int x = r.x; int y = r.y + fm.getAscent() + ((r.height - fm.getHeight()) / 2); + // apply horizontal alignment to x location + String clippedPlaceholder = JavaCompatibility.getClippedString( c, fm, placeholder, r.width ); + int stringWidth = fm.stringWidth( clippedPlaceholder ); + int halign = (c instanceof JTextField) ? ((JTextField)c).getHorizontalAlignment() : SwingConstants.LEADING; + if( halign == SwingConstants.LEADING ) + halign = isLeftToRight() ? SwingConstants.LEFT : SwingConstants.RIGHT; + else if( halign == SwingConstants.TRAILING ) + halign = isLeftToRight() ? SwingConstants.RIGHT : SwingConstants.LEFT; + if( halign == SwingConstants.RIGHT ) + x += r.width - stringWidth; + else if( halign == SwingConstants.CENTER ) + x = Math.max( 0, x + (r.width / 2) - (stringWidth / 2) ); + // paint placeholder g.setColor( placeholderForeground ); FlatUIUtils.drawString( c, g, clippedPlaceholder, x, y ); 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 c12e8935..6a2e8729 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 @@ -27,6 +27,7 @@ import javax.swing.border.*; import javax.swing.text.DefaultEditorKit; import javax.swing.text.JTextComponent; import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.extras.components.*; import com.formdev.flatlaf.util.UIScale; import net.miginfocom.swing.*; @@ -214,6 +215,17 @@ public class FlatTextComponentsTest trailingComponentVisibleCheckBox = new JCheckBox(); showClearButtonCheckBox = new JCheckBox(); showRevealButtonCheckBox = new JCheckBox(); + JPanel panel2 = new JPanel(); + JLabel label7 = new JLabel(); + FlatTextField flatTextField1 = new FlatTextField(); + JLabel label8 = new JLabel(); + FlatTextField flatTextField2 = new FlatTextField(); + JLabel label9 = new JLabel(); + FlatTextField flatTextField3 = new FlatTextField(); + JLabel label10 = new JLabel(); + FlatTextField flatTextField4 = new FlatTextField(); + JLabel label11 = new JLabel(); + FlatTextField flatTextField5 = new FlatTextField(); JLabel passwordFieldLabel = new JLabel(); JPasswordField passwordField1 = new JPasswordField(); JPasswordField passwordField3 = new JPasswordField(); @@ -273,6 +285,7 @@ public class FlatTextComponentsTest "[]" + "[::100]" + "[100,fill]" + + "[fill]" + "[fill]", // rows "[]" + @@ -450,6 +463,73 @@ public class FlatTextComponentsTest } add(panel1, "cell 4 0 1 10,aligny top,growy 0"); + //======== panel2 ======== + { + panel2.setBorder(new TitledBorder("Placeholder")); + panel2.setLayout(new MigLayout( + "hidemode 3", + // columns + "[fill]" + + "[fill]", + // rows + "[]" + + "[]" + + "[]" + + "[]" + + "[]")); + + //---- label7 ---- + label7.setText("leading"); + panel2.add(label7, "cell 0 0"); + + //---- flatTextField1 ---- + flatTextField1.setHorizontalAlignment(SwingConstants.LEADING); + flatTextField1.setPlaceholderText("text"); + flatTextField1.setColumns(10); + panel2.add(flatTextField1, "cell 1 0"); + + //---- label8 ---- + label8.setText("left"); + panel2.add(label8, "cell 0 1"); + + //---- flatTextField2 ---- + flatTextField2.setHorizontalAlignment(SwingConstants.LEFT); + flatTextField2.setPlaceholderText("text"); + flatTextField2.setColumns(10); + panel2.add(flatTextField2, "cell 1 1"); + + //---- label9 ---- + label9.setText("center"); + panel2.add(label9, "cell 0 2"); + + //---- flatTextField3 ---- + flatTextField3.setHorizontalAlignment(SwingConstants.CENTER); + flatTextField3.setPlaceholderText("text"); + flatTextField3.setColumns(10); + panel2.add(flatTextField3, "cell 1 2"); + + //---- label10 ---- + label10.setText("right"); + panel2.add(label10, "cell 0 3"); + + //---- flatTextField4 ---- + flatTextField4.setHorizontalAlignment(SwingConstants.RIGHT); + flatTextField4.setPlaceholderText("text"); + flatTextField4.setColumns(10); + panel2.add(flatTextField4, "cell 1 3"); + + //---- label11 ---- + label11.setText("trailing"); + panel2.add(label11, "cell 0 4"); + + //---- flatTextField5 ---- + flatTextField5.setHorizontalAlignment(SwingConstants.TRAILING); + flatTextField5.setPlaceholderText("text"); + flatTextField5.setColumns(10); + panel2.add(flatTextField5, "cell 1 4"); + } + add(panel2, "cell 5 0 1 9,aligny top,growy 0"); + //---- passwordFieldLabel ---- passwordFieldLabel.setText("JPasswordField:"); passwordFieldLabel.setDisplayedMnemonic('P'); 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 179190c4..73b5c705 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.5.0.404" Java: "17" encoding: "UTF-8" +JFDML JFormDesigner: "8.1.0.0.283" Java: "19.0.2" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -8,7 +8,7 @@ new FormModel { } add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "ltr,insets dialog,hidemode 3" - "$columnConstraints": "[][][::100][100,fill][fill]" + "$columnConstraints": "[][][::100][100,fill][fill][fill]" "$rowConstraints": "[][][][50,fill][50,fill][50,fill][][]para[40][40][][][::14][::14][][]para[][90,fill]" } ) { name: "this" @@ -244,6 +244,89 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 4 0 1 10,aligny top,growy 0" } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "hidemode 3" + "$columnConstraints": "[fill][fill]" + "$rowConstraints": "[][][][][]" + } ) { + name: "panel2" + "border": new javax.swing.border.TitledBorder( "Placeholder" ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label7" + "text": "leading" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTextField" ) { + name: "flatTextField1" + "horizontalAlignment": 10 + "placeholderText": "text" + "columns": 10 + auxiliary() { + "horizontalAlignment.forceValue": true + } + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 0" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label8" + "text": "left" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTextField" ) { + name: "flatTextField2" + "horizontalAlignment": 2 + "placeholderText": "text" + "columns": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 1" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label9" + "text": "center" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 2" + } ) + add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTextField" ) { + name: "flatTextField3" + "horizontalAlignment": 0 + "placeholderText": "text" + "columns": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 2" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label10" + "text": "right" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3" + } ) + add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTextField" ) { + name: "flatTextField4" + "horizontalAlignment": 4 + "placeholderText": "text" + "columns": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 3" + } ) + add( new FormComponent( "javax.swing.JLabel" ) { + name: "label11" + "text": "trailing" + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 4" + } ) + add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTextField" ) { + name: "flatTextField5" + "horizontalAlignment": 11 + "placeholderText": "text" + "columns": 10 + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 1 4" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 5 0 1 9,aligny top,growy 0" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "passwordFieldLabel" "text": "JPasswordField:" @@ -572,7 +655,7 @@ new FormModel { } ) }, new FormLayoutConstraints( null ) { "location": new java.awt.Point( 0, 0 ) - "size": new java.awt.Dimension( 640, 725 ) + "size": new java.awt.Dimension( 875, 725 ) } ) add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) { name: "popupMenu1"