package ctbrec.ui.controls; import java.io.File; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ctbrec.StringUtil; import ctbrec.ui.AutosizeAlert; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ChangeListener; import javafx.geometry.Point2D; import javafx.scene.Node; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.control.Tooltip; import javafx.scene.layout.Border; import javafx.scene.layout.BorderStroke; import javafx.scene.layout.BorderStrokeStyle; import javafx.scene.layout.BorderWidths; import javafx.scene.layout.CornerRadii; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.paint.Color; import javafx.stage.FileChooser; public abstract class AbstractFileSelectionBox extends HBox { private static final transient Logger LOG = LoggerFactory.getLogger(AbstractFileSelectionBox.class); // private ObjectProperty fileProperty = new ObjectPropertyBase() { // @Override // public Object getBean() { // return null; // } // // @Override // public String getName() { // return "file"; // } // }; private StringProperty fileProperty = new SimpleStringProperty(); protected TextField fileInput; protected boolean allowEmptyValue = false; private Tooltip validationError = new Tooltip(); public AbstractFileSelectionBox() { super(5); fileInput = new TextField(); fileInput.textProperty().addListener(textListener()); fileInput.focusedProperty().addListener((obs, o, n) -> { if(!n) { validationError.hide(); } }); Node browse = createBrowseButton(); getChildren().addAll(fileInput, browse); fileInput.disableProperty().bind(disableProperty()); browse.disableProperty().bind(disableProperty()); HBox.setHgrow(fileInput, Priority.ALWAYS); disabledProperty().addListener((obs, oldV, newV) -> { if (newV) { hideValidationHints(); } else { if (StringUtil.isNotBlank(fileInput.getText())) { setFile(new File(fileInput.getText())); } } }); } public AbstractFileSelectionBox(String initialValue) { this(); fileInput.setText(initialValue); } private ChangeListener textListener() { return (obs, o, n) -> { String input = fileInput.getText(); if(StringUtil.isBlank(input) && allowEmptyValue) { fileProperty.set(""); hideValidationHints(); return; } else { File program = new File(input); setFile(program); } }; } protected void setFile(File file) { String msg = validate(file); if (msg != null) { fileInput.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.DASHED, new CornerRadii(2), new BorderWidths(2)))); validationError.setText(msg); fileInput.setTooltip(validationError); Point2D p = fileInput.localToScreen(fileInput.getTranslateY(), fileInput.getTranslateY()); if(!validationError.isShowing() && getScene() != null) { validationError.show(getScene().getWindow(), p.getX(), p.getY() + fileInput.getHeight() + 4); } } else { fileProperty.set(file.getAbsolutePath()); hideValidationHints(); } } private void hideValidationHints() { fileInput.setBorder(Border.EMPTY); fileInput.setTooltip(null); validationError.hide(); } protected String validate(File file) { if(isDisabled()) { return null; } if (file == null || !file.exists()) { return "File does not exist"; } else { return null; } } public void allowEmptyValue() { this.allowEmptyValue = true; } private Button createBrowseButton() { Button button = new Button("Select"); button.setOnAction((e) -> { choose(); }); return button; } protected void choose() { FileChooser chooser = new FileChooser(); File program = chooser.showOpenDialog(null); if(program != null) { try { fileInput.setText(program.getCanonicalPath()); } catch (IOException e1) { LOG.error("Couldn't determine path", e1); Alert alert = new AutosizeAlert(Alert.AlertType.ERROR); alert.setTitle("Whoopsie"); alert.setContentText("Couldn't determine path"); alert.showAndWait(); } setFile(program); } } public StringProperty fileProperty() { return fileProperty; } }