Improve PasswordTextFormatter
Use commitValue() to refresh text field content. Also, add tests.
This commit is contained in:
parent
e485b28595
commit
308a4b9b28
@ -10,7 +10,6 @@ import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.TextFormatter;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
@ -19,7 +18,7 @@ import java.util.function.UnaryOperator;
|
||||
*/
|
||||
public class PasswordTextFormatter extends TextFormatter<String> {
|
||||
|
||||
public static final char BULLET = '\u2731'; // heavy asterisk
|
||||
public static final char BULLET = '✱'; // U+2731, heavy asterisk
|
||||
|
||||
protected PasswordTextFormatter(StringConverter<String> valueConverter,
|
||||
UnaryOperator<Change> filter,
|
||||
@ -39,13 +38,13 @@ public class PasswordTextFormatter extends TextFormatter<String> {
|
||||
passwordFilter.setInitialText(textField.getText());
|
||||
|
||||
revealPasswordProperty().addListener((obs, old, val) -> {
|
||||
// Force text field update, because converter is only called on focus
|
||||
// events by default. Don't use commitValue() here because caret position
|
||||
// won't be correct due to #javafx-bug (https://bugs.openjdk.org/browse/JDK-8248914).
|
||||
if (val == null) {
|
||||
return;
|
||||
}
|
||||
textField.setText(passwordProperty().get());
|
||||
if (val == null) { return; }
|
||||
|
||||
// Force text field update, because converter is only called on focus events by default.
|
||||
// Also, reset caret first, because otherwise its position won't be correct due to
|
||||
// #javafx-bug (https://bugs.openjdk.org/browse/JDK-8248914).
|
||||
textField.positionCaret(0);
|
||||
textField.commitValue();
|
||||
});
|
||||
|
||||
// force text field update on scene show
|
||||
@ -95,15 +94,17 @@ public class PasswordTextFormatter extends TextFormatter<String> {
|
||||
|
||||
@Override
|
||||
public String toString(String s) {
|
||||
if (s == null) {
|
||||
return "";
|
||||
}
|
||||
return filter.revealPassword.get() ? filter.password.get() : filter.maskText(s.length());
|
||||
return getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromString(String string) {
|
||||
return filter.password.get();
|
||||
public String fromString(String s) {
|
||||
return getPassword();
|
||||
}
|
||||
|
||||
protected String getPassword() {
|
||||
var password = filter.password.get();
|
||||
return filter.revealPassword.get() ? password : filter.maskText(password.length());
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,15 +117,6 @@ public class PasswordTextFormatter extends TextFormatter<String> {
|
||||
|
||||
@Override
|
||||
public TextFormatter.Change apply(TextFormatter.Change change) {
|
||||
// Since we are using setText() to force text field to update (see above),
|
||||
// we should protect internal password value from changing when `revealPassword`is toggled.
|
||||
if (Objects.equals(change.getText(), sb.toString())) {
|
||||
if (!revealPassword.get()) {
|
||||
change.setText(maskText(change.getText().length()));
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
if (change.isReplaced()) {
|
||||
sb.replace(change.getRangeStart(), change.getRangeEnd(), change.getText());
|
||||
} else if (change.isDeleted()) {
|
||||
|
@ -0,0 +1,160 @@
|
||||
package atlantafx.base.util;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.control.TextField;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
public class PasswordTextFormatterTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void startup() {
|
||||
Platform.startup(() -> { });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTextIsMaskedByDefault() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
assertEquals("+".repeat(3), field.getText());
|
||||
assertEquals("123", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTextCanBeRevealed() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
fmt.setRevealPassword(true);
|
||||
assertEquals("123", field.getText());
|
||||
assertEquals("123", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrependText() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.insertText(0, "456");
|
||||
assertEquals("+".repeat(6), field.getText());
|
||||
assertEquals("456123", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendText() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.appendText("456");
|
||||
assertEquals("+".repeat(6), field.getText());
|
||||
assertEquals("123456", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertText() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.insertText(2, "456");
|
||||
assertEquals("+".repeat(6), field.getText());
|
||||
assertEquals("124563", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoInitialText() {
|
||||
var field = new TextField(null);
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
|
||||
field.appendText("456");
|
||||
assertEquals("+".repeat(3), field.getText());
|
||||
assertEquals("456", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteSomeText() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.deleteText(0, 2);
|
||||
assertEquals("+", field.getText());
|
||||
assertEquals("3", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAllText() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.deleteText(0, field.getText().length());
|
||||
assertEquals("", field.getText());
|
||||
assertEquals("", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetTextToNull() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.setText(null);
|
||||
assertNull(null, field.getText());
|
||||
assertEquals("", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceSelection() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.selectRange(1, field.getText().length());
|
||||
field.replaceSelection("456");
|
||||
assertEquals("+".repeat(4), field.getText());
|
||||
assertEquals("1456", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAll() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123");
|
||||
|
||||
field.selectRange(0, field.getText().length());
|
||||
field.replaceSelection("456");
|
||||
assertEquals("+".repeat(3), field.getText());
|
||||
assertEquals("456", fmt.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanContainBullets() {
|
||||
var field = new TextField();
|
||||
var fmt = PasswordTextFormatter.create(field, '+');
|
||||
field.setTextFormatter(fmt);
|
||||
field.setText("123++");
|
||||
|
||||
assertEquals("+".repeat(5), field.getText());
|
||||
assertEquals("123++", fmt.getPassword());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user