Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PasswordField support #10

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion formsfx-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<groupId>com.dlsc.formsfx</groupId>
<artifactId>formsfx-core</artifactId>
<packaging>jar</packaging>
<version>1.2.1</version>
<version>1.2.2-SNAPSHOT</version>

<name>FormsFX</name>
<description>A framework for quickly creating form-based UIs.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,30 @@ public abstract class Field<F extends Field> {
.collect(Collectors.toList())));
}

/**
* Creates a new {@link PasswordField} with the given default value.
*
* @param defaultValue
* The initial value and persistent value of the field.
*
* @return Returns a new {@link PasswordField}.
*/
public static PasswordField ofPasswordType(String defaultValue) {
return new PasswordField(new SimpleStringProperty(defaultValue), new SimpleStringProperty(defaultValue));
}

/**
* Creates a new {@link PasswordField} with the given property.
*
* @param binding
* The property from the model to be bound with.
*
* @return Returns a new {@link PasswordField}.
*/
public static PasswordField ofPasswordType(StringProperty binding) {
return new PasswordField(new SimpleStringProperty(binding.getValue()), new SimpleStringProperty(binding.getValue())).bind(binding);
}

/**
* Creates a new {@link StringField} with the given default value.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.dlsc.formsfx.model.structure;

/*-
* ========================LICENSE_START=================================
* FormsFX
* %%
* Copyright (C) 2017 DLSC Software & Consulting
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =========================LICENSE_END==================================
*/

import com.dlsc.formsfx.view.controls.SimplePasswordControl;
import com.dlsc.formsfx.view.controls.SimpleTextControl;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
* This class provides an implementation of a {@link Field} containing a
* {@code string} value intended for passwords.
*
* @author Andres Almiray
*/
public class PasswordField extends DataField<StringProperty, String, PasswordField> {
/**
* The constructor of {@code PasswordField}.
*
* @param valueProperty
* The property that is used to store the current valid value
* of the field.
* @param persistentValueProperty
* The property that is used to store the latest persisted
* value of the field.
*/
PasswordField(SimpleStringProperty valueProperty, SimpleStringProperty persistentValueProperty) {
super(valueProperty, persistentValueProperty);

valueTransformer = String::valueOf;
renderer = new SimplePasswordControl();

userInput.set(String.valueOf(value.getValue()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package com.dlsc.formsfx.view.controls;

/*-
* ========================LICENSE_START=================================
* FormsFX
* %%
* Copyright (C) 2017 DLSC Software & Consulting
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =========================LICENSE_END==================================
*/

import com.dlsc.formsfx.model.structure.PasswordField;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;

/**
* This class provides the base implementation for a simple control to edit
* password values.
*
* @author Rinesch Murugathas
* @author Sacha Schmid
* @author Andres Almiray
*/
public class SimplePasswordControl extends SimpleControl<PasswordField> {

/**
* This StackPane is needed for achieving the readonly effect by putting
* the readOnlyLabel over the editableField on the change of the
* visibleProperty.
*/
private StackPane stack;

/**
* - The fieldLabel is the container that displays the label property of
* the field.
* - The editableField allows users to modify the field's value.
* - The readOnlyLabel displays the field's value if it is not editable.
*/
private javafx.scene.control.PasswordField editableField;
private Label readOnlyLabel;
private Label fieldLabel;

/*
* Translates characters found in user input into '*'
*/
private StringBinding obfuscatedUserInputBinding;

/**
* {@inheritDoc}
*/
@Override
public void initializeParts() {
super.initializeParts();

getStyleClass().add("simple-password-control");

stack = new StackPane();

editableField = new javafx.scene.control.PasswordField();
editableField.setText(field.getValue());

readOnlyLabel = new Label(obfuscate(field.getValue()));
fieldLabel = new Label(field.labelProperty().getValue());
editableField.setPromptText(field.placeholderProperty().getValue());
}

/**
* {@inheritDoc}
*/
@Override
public void layoutParts() {
super.layoutParts();

readOnlyLabel.getStyleClass().add("read-only-label");

readOnlyLabel.setPrefHeight(26);

stack.getChildren().addAll(editableField, readOnlyLabel);

stack.setAlignment(Pos.CENTER_LEFT);

int columns = field.getSpan();

if (columns < 3) {
add(fieldLabel, 0, 0, columns, 1);
add(stack, 0, 1, columns, 1);
} else {
add(fieldLabel, 0, 0, 2, 1);
add(stack, 2, 0, columns - 2, 1);
}
}

/**
* {@inheritDoc}
*/
@Override
public void setupBindings() {
super.setupBindings();

editableField.visibleProperty().bind(field.editableProperty());
readOnlyLabel.visibleProperty().bind(field.editableProperty().not());

editableField.textProperty().bindBidirectional(field.userInputProperty());
obfuscatedUserInputBinding = Bindings.createStringBinding(() -> obfuscate(field.getUserInput()), field.userInputProperty());
readOnlyLabel.textProperty().bind(obfuscatedUserInputBinding);
fieldLabel.textProperty().bind(field.labelProperty());
editableField.promptTextProperty().bind(field.placeholderProperty());
editableField.managedProperty().bind(editableField.visibleProperty());
}

/**
* {@inheritDoc}
*/
@Override
public void setupValueChangedListeners() {
super.setupValueChangedListeners();

field.errorMessagesProperty().addListener((observable, oldValue, newValue) -> toggleTooltip(editableField));

editableField.focusedProperty().addListener((observable, oldValue, newValue) -> toggleTooltip(editableField));
}

private String obfuscate(String input) {
if (input == null) { return ""; }
int length = input.length();
StringBuilder b = new StringBuilder();
for (int i = 0; i < length; i++) {
b.append('*');
}
return b.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
}

.simple-control .text-field,
.simple-control .password-field,
.simple-control .text-area {
-fx-padding: 5px;
}
Expand Down Expand Up @@ -92,10 +93,13 @@

/*noinspection CssInvalidPseudoSelector*/
.simple-control:changed .text-field,
.simple-control:changed .password-field,
.simple-control:changed .text-area,
.simple-control:required .text-field,
.simple-control:required .password-field,
.simple-control:required .text-area,
.simple-control:invalid .text-field,
.simple-control:invalid .password-field,
.simple-control:invalid .text-area,
.simple-select-control:changed .arrow-button,
.simple-select-control:required .arrow-button,
Expand Down Expand Up @@ -124,6 +128,7 @@

/*noinspection CssInvalidPseudoSelector*/
.simple-control:required .text-field,
.simple-control:required .password-field,
.simple-control:required .text-area,
.simple-boolean-control:required > VBox,
.simple-select-control:required .arrow-button,
Expand All @@ -135,6 +140,7 @@

/*noinspection CssInvalidPseudoSelector*/
.simple-control:changed .text-field,
.simple-control:changed .password-field,
.simple-control:changed .text-area,
.simple-boolean-control:changed > VBox,
.simple-select-control:changed .arrow-button,
Expand All @@ -146,6 +152,7 @@

/*noinspection CssInvalidPseudoSelector*/
.simple-control:invalid .text-field,
.simple-control:invalid .password-field,
.simple-control:invalid .text-area,
.simple-boolean-control:invalid > VBox,
.simple-select-control:invalid .arrow-button,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ public void generateFormTest() {
Section.of(
Field.ofIntegerType(1),
Field.ofDoubleType(1.0)
),
Section.of(
Field.ofPasswordType("")
)
);

Assert.assertEquals(5, f.getFields().size());
Assert.assertEquals(3, f.getGroups().size());
Assert.assertEquals(6, f.getFields().size());
Assert.assertEquals(4, f.getGroups().size());
}

@Test
Expand Down
4 changes: 2 additions & 2 deletions formsfx-demo/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.dlsc.formsfx</groupId>
<artifactId>formsfx</artifactId>
<version>1.2.1</version>
<version>1.2.2-SNAPSHOT</version>
</parent>

<packaging>jar</packaging>
Expand All @@ -18,7 +18,7 @@
<dependency>
<groupId>com.dlsc.formsfx</groupId>
<artifactId>formsfx-core</artifactId>
<version>1.2.1</version>
<version>1.2.2-SNAPSHOT</version>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,12 @@ private void createForm() {
.render(new SimpleCheckBoxControl<>()),
Field.ofMultiSelectionType(country.allCitiesProperty(), country.germanCitiesProperty())
.label("german_cities_label")
.span(ColSpan.HALF),
Field.ofPasswordType("secret")
.label("secret_label")
.required("required_error_message")
.span(ColSpan.HALF)
.validate(StringLengthValidator.between(1, 10, "secret_error_message"))
).title("cities_and_population_label")
).title("form_label")
.i18n(rbs);
Expand Down
2 changes: 2 additions & 0 deletions formsfx-demo/src/main/resources/demo-locale_de_CH.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ capital_label = Hauptstadt
german_cities_label = Deutschsprachige St\u00e4dte
continent_label = Kontinent
population_label = Einwohner
secret_label = Geheimnis
cities_and_population_label = St\u00e4dte und Einwohner
currency_label = W\u00e4hrung
currency_long_label = W\u00e4hrung lang
Expand Down Expand Up @@ -40,5 +41,6 @@ time_zone_error_message = Zeitzone muss genau 3 Zeichen lang sein
summer_time_zone_error_message = Sommer-Zeitzone muss l\u00e4nger als 3 Zeichen sein
country_error_message = Landesname muss l\u00e4nger als 2 Zeichen sein
ISO_3166_error_message = ISO 3166 code muss genau 2 Zeichen lang sein
secret_error_message = Passwortl\u00e4nge muss zwischen 1 und 10 Zeichen sein

capital_tooltip = Die Hauptstadt des Landes ist oftmals nicht die gr\u00f6sste Stadt.
2 changes: 2 additions & 0 deletions formsfx-demo/src/main/resources/demo-locale_en_UK.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ capital_label = Capital
german_cities_label = German-speaking Cities
continent_label = Continent
population_label = Population
secret_label = Secret
cities_and_population_label = Cities and Population
currency_label = Currency
currency_long_label = Currency long
Expand Down Expand Up @@ -40,5 +41,6 @@ time_zone_error_message = Time zone has to be exactly 3 characters long
summer_time_zone_error_message = Summer time zone has to be at least 3 characters long
country_error_message = Name of country has to be longer than 2 characters
ISO_3166_error_message = ISO 3166 code has to be exactly 2 characters long
secret_error_message = Password length must be between 1 and 10 characters

capital_tooltip = The capital city is often not the largest city.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<groupId>com.dlsc.formsfx</groupId>
<artifactId>formsfx</artifactId>
<packaging>pom</packaging>
<version>1.2.1</version>
<version>1.2.2-SNAPSHOT</version>

<modules>
<module>formsfx-core</module>
Expand Down