/*
* Copyright [2014] [Christian Loehnert, krampenschiesser@gmail.com]
* 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.
*/
package de.ks.validation;
import javafx.application.Platform;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.controlsfx.control.decoration.Decoration;
import org.controlsfx.control.decoration.GraphicDecoration;
import org.controlsfx.validation.Severity;
import org.controlsfx.validation.ValidationMessage;
import org.controlsfx.validation.decoration.AbstractValidationDecoration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Collection;
public class CustomValidationDecoration extends AbstractValidationDecoration {
// TODO we shouldn't hardcode this - defer to CSS eventually
private static final Image ERROR_IMAGE = new Image("/impl/org/controlsfx/control/validation/decoration-error.png");
private static final Image WARNING_IMAGE = new Image("/impl/org/controlsfx/control/validation/decoration-warning.png");
private static final Image REQUIRED_IMAGE = new Image("/impl/org/controlsfx/control/validation/required-indicator.png");
private static final String SHADOW_EFFECT = "-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.8), 10, 0, 0, 0);";
private static final String TOOLTIP_COMMON_EFFECTS = "-fx-font-weight: bold; -fx-padding: 5; -fx-border-width:1;";
private static final String ERROR_TOOLTIP_EFFECT = SHADOW_EFFECT + TOOLTIP_COMMON_EFFECTS + "-fx-background-color: FBEFEF; -fx-text-fill: cc0033; -fx-border-color:cc0033;";
private static final String WARNING_TOOLTIP_EFFECT = SHADOW_EFFECT + TOOLTIP_COMMON_EFFECTS + "-fx-background-color: FFFFCC; -fx-text-fill: CC9900; -fx-border-color: CC9900;";
// TODO write javadoc that users should override these methods to customise
// the error / warning / success nodes to use
protected Node createErrorNode() {
return new ImageView(ERROR_IMAGE);
}
protected Node createWarningNode() {
return new ImageView(WARNING_IMAGE);
}
private static final Logger log = LoggerFactory.getLogger(CustomValidationDecoration.class);
private Node createDecorationNode(ValidationMessage message) {
Node graphic = Severity.ERROR == message.getSeverity() ? createErrorNode() : createWarningNode();
graphic.setStyle(SHADOW_EFFECT);
Label label = new Label();
label.setGraphic(graphic);
Tooltip tooltip = createTooltip(message);
label.setAlignment(Pos.CENTER);
Control target = message.getTarget();
showTooltip(tooltip, target);
label.parentProperty().addListener((p, o, n) -> {
if (n == null) {
tooltip.hide();
}
});
target.sceneProperty().addListener((p, o, n) -> {
if (n == null) {
tooltip.hide();
}
});
return label;
}
private void showTooltip(Tooltip tooltip, Control target) {
Point2D point2D = target.localToScreen(target.getLayoutBounds().getMinX(), target.getLayoutBounds().getMinY());
if (point2D == null) {
Platform.runLater(() -> {
Control target1 = target;
Point2D point = target1.localToScreen(target1.getLayoutBounds().getMinX(), target.getLayoutBounds().getMinY());
if (point != null && tooltip != null) {
showTooltip(tooltip, target, point);
}
});
} else {
showTooltip(tooltip, target, point2D);
}
}
private void showTooltip(Tooltip tooltip, Control target, Point2D point2D) {
tooltip.show(target, point2D.getX(), point2D.getY());
tooltip.hide();
tooltip.show(target, point2D.getX(), point2D.getY() - tooltip.getHeight() / 2);
}
protected Tooltip createTooltip(ValidationMessage message) {
Tooltip tooltip = new Tooltip(message.getText());
tooltip.setOpacity(.9);
tooltip.setAutoFix(true);
tooltip.setAutoHide(true);
tooltip.setHideOnEscape(true);
tooltip.setStyle(Severity.ERROR == message.getSeverity() ? ERROR_TOOLTIP_EFFECT : WARNING_TOOLTIP_EFFECT);
return tooltip;
}
/**
* {@inheritDoc}
*/
@Override
protected Collection<Decoration> createValidationDecorations(ValidationMessage message) {
return Arrays.asList(new GraphicDecoration(createDecorationNode(message), Pos.BOTTOM_LEFT));
}
/**
* {@inheritDoc}
*/
@Override
protected Collection<Decoration> createRequiredDecorations(Control target) {
return Arrays.asList(new GraphicDecoration(new ImageView(REQUIRED_IMAGE), Pos.TOP_LEFT, REQUIRED_IMAGE.getWidth() / 2, REQUIRED_IMAGE.getHeight() / 2));
}
}