Skip to content

Commit

Permalink
#600 make ValidationVisualizerBase methods protected to allow own imp…
Browse files Browse the repository at this point in the history
…lementations. Add css visualizer example
  • Loading branch information
manuel-mauky committed Oct 21, 2019
1 parent b5a8e6d commit 9962bed
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@
* this visualization you have to add the ControlsFX library to your classpath, otherwise you will get
* {@link NoClassDefFoundError}s and {@link ClassNotFoundException}s. If you are using a build management system like
* <i>maven</i> or <i>gradle</i> you simply have to add the library as dependency.
*
*
*
*
* @author manuel.mauky
*/
public class ControlsFxVisualizer extends ValidationVisualizerBase {

private ValidationDecoration decoration = new GraphicValidationDecoration();

/**
* Define a custom ControlsFX {@link ValidationVisualizer} that is used to visualize the validation results.
* <p>
Expand All @@ -48,39 +48,39 @@ public class ControlsFxVisualizer extends ValidationVisualizerBase {
public void setDecoration(ValidationDecoration decoration) {
this.decoration = decoration;
}


@Override
void applyRequiredVisualization(Control control, boolean required) {
protected void applyRequiredVisualization(Control control, boolean required) {
ValidationSupport.setRequired(control, required);
if (required) {
decoration.applyRequiredDecoration(control);
}
}

@Override
void applyVisualization(Control control, Optional<ValidationMessage> messageOptional, boolean required) {
protected void applyVisualization(Control control, Optional<ValidationMessage> messageOptional, boolean required) {

if (messageOptional.isPresent()) {
final ValidationMessage message = messageOptional.get();

decoration.removeDecorations(control);

if (Severity.ERROR.equals(message.getSeverity())) {
decoration.applyValidationDecoration(org.controlsfx.validation.ValidationMessage.error(control,
message.getMessage()));
} else if (Severity.WARNING.equals(message.getSeverity())) {
decoration.applyValidationDecoration(org.controlsfx.validation.ValidationMessage.warning(control,
message.getMessage()));
}

} else {
decoration.removeDecorations(control);
}

if (required) {
decoration.applyRequiredDecoration(control);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
* <p>
* This base class takes care for the handling of the {@link ValidationStatus} and the reaction to it's changing message
* lists.
*
*
* @author manuel.mauky
*/
public abstract class ValidationVisualizerBase implements ValidationVisualizer {


@Override
public void initVisualization(final ValidationStatus result, final Control control, boolean required) {
Platform.runLater(() -> {
Expand All @@ -56,19 +56,19 @@ public void initVisualization(final ValidationStatus result, final Control contr
});
});
}

/**
* Apply a visualization to the given control that indicates that it is a mandatory field.
* <p>
* This method is called when the validator is initialized.
*
*
* @param control
* the controls that has to be decorated.
* @param required
* a boolean indicating whether the given control is mandatory or not.
*/
abstract void applyRequiredVisualization(Control control, boolean required);
protected abstract void applyRequiredVisualization(Control control, boolean required);

/**
* Apply a visualization to the given control that shows a validation message.
* <p>
Expand All @@ -81,8 +81,8 @@ public void initVisualization(final ValidationStatus result, final Control contr
* <p>
* The given boolean parameter indicates whether this controls is mandatory or not. It can be used if a violation
* for a mandatory field should be visualized differently than a non-mandatory field.
*
*
*
*
* @param control
* the control that will be decorated.
* @param messageOptional
Expand All @@ -91,6 +91,6 @@ public void initVisualization(final ValidationStatus result, final Control contr
* @param required
* a boolean flag indicating whether this control is mandatory or not.
*/
abstract void applyVisualization(Control control, Optional<ValidationMessage> messageOptional, boolean required);
protected abstract void applyVisualization(Control control, Optional<ValidationMessage> messageOptional, boolean required);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.saxsys.mvvmfx.utils.validation.cssvisualizer;

import de.saxsys.mvvmfx.utils.validation.ValidationMessage;
import de.saxsys.mvvmfx.utils.validation.visualization.ValidationVisualizerBase;

import java.util.List;
import java.util.Optional;

import javafx.scene.control.Control;

public class CssVisualizer extends ValidationVisualizerBase {

private final String errorStyleClass;
private final String validStyleClass;
private final String requiredStyleClass;

public CssVisualizer(String errorStyleClass, String validStyleClass, String requiredStyleClass) {
this.errorStyleClass = errorStyleClass;
this.validStyleClass = validStyleClass;
this.requiredStyleClass = requiredStyleClass;
}

@Override
protected void applyRequiredVisualization(Control control, boolean required) {
addIfAbsent(control.getStyleClass(), requiredStyleClass);
}

@Override
public void applyVisualization(Control control, Optional<ValidationMessage> messageOptional, boolean required) {
if (messageOptional.isPresent()) {
control.getStyleClass().remove(validStyleClass);
addIfAbsent(control.getStyleClass(), errorStyleClass);
} else {
control.getStyleClass().remove(errorStyleClass);
addIfAbsent(control.getStyleClass(), validStyleClass);
}
}

private static <T> void addIfAbsent(List<T> list, T element) {
if (!list.contains(element)) {
list.add(element);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package de.saxsys.mvvmfx.utils.validation.cssvisualizer;

import de.saxsys.mvvmfx.FluentViewLoader;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class CssVisualizerExampleApp extends Application {

public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {

Parent parent = FluentViewLoader.fxmlView(CssVisualizerView.class).load().getView();

primaryStage.setScene(new Scene(parent));
primaryStage.show();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.saxsys.mvvmfx.utils.validation.cssvisualizer;

import de.saxsys.mvvmfx.FxmlView;
import de.saxsys.mvvmfx.InjectViewModel;
import de.saxsys.mvvmfx.utils.validation.visualization.ValidationVisualizer;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;

public class CssVisualizerView implements FxmlView<CssVisualizerViewModel> {

@FXML
private TextField email;

@InjectViewModel
private CssVisualizerViewModel viewModel;

private ValidationVisualizer visualizer = new CssVisualizer("error", "valid", "required");

public void initialize() {
email.textProperty().bindBidirectional(viewModel.emailAddressProperty());

visualizer.initVisualization(viewModel.getValidationStatus(), email, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package de.saxsys.mvvmfx.utils.validation.cssvisualizer;

import de.saxsys.mvvmfx.ViewModel;
import de.saxsys.mvvmfx.utils.validation.FunctionBasedValidator;
import de.saxsys.mvvmfx.utils.validation.ValidationMessage;
import de.saxsys.mvvmfx.utils.validation.ValidationStatus;
import de.saxsys.mvvmfx.utils.validation.Validator;

import java.util.function.Function;
import java.util.regex.Pattern;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class CssVisualizerViewModel implements ViewModel {
private static final Pattern EMAIL_REGEX = Pattern
.compile("^$|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}");

private StringProperty emailAddress = new SimpleStringProperty("");

private Validator validator = new FunctionBasedValidator<String>(emailAddress, input -> {
if (input == null || input.trim().isEmpty() || !EMAIL_REGEX.matcher(input).matches()) {
return ValidationMessage.error("Invalid EMail address");
} else {
return null;
}
});

public ValidationStatus getValidationStatus() {
return validator.getValidationStatus();
}

public StringProperty emailAddressProperty() {
return emailAddress;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* This package contains an example for a simple custom visualizer that uses CSS styling. It's not intended to be an
* official visualizer but just a starting point for people to implement their own visualizers.
*/
package de.saxsys.mvvmfx.utils.validation.cssvisualizer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>


<VBox stylesheets="@style.css" spacing="10.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.saxsys.mvvmfx.utils.validation.cssvisualizer.CssVisualizerView">

<children>
<Label text="Email:" />
<TextField fx:id="email" />
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</VBox>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

.error {
-fx-border-color: red;
}

.valid {
-fx-border-color: green;
}

.required {
-fx-background-color: yellow;
}

0 comments on commit 9962bed

Please sign in to comment.