All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dua3.fx.controls.InputControl Maven / Gradle / Ivy

The newest version!
package com.dua3.fx.controls;

import com.dua3.cabe.annotations.Nullable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.Property;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.stage.FileChooser;
import javafx.util.StringConverter;

import java.nio.file.Path;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.Locale;
import java.util.Optional;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

/**
 * Interface for an input field.
 *
 * @param  the input result type
 */
public interface InputControl {
    static SimpleInputControl stringInput(Supplier dflt, Function> validate) {
        TextField control = new TextField();
        StringProperty value = control.textProperty();
        return new SimpleInputControl<>(control, value, dflt, validate);
    }

    static  SimpleInputControl stringInput(Supplier dflt, Function> validate, StringConverter converter) {
        TextField control = new TextField();
        ObjectProperty value = new SimpleObjectProperty<>();
        Bindings.bindBidirectional(control.textProperty(), value, converter);
        return new SimpleInputControl<>(control, value, dflt, validate);
    }

    static SimpleInputControl integerInput(Supplier dflt, Function> validate) {
        TextField control = new TextField();
        StringProperty textProperty = control.textProperty();
        IntegerProperty value = new SimpleIntegerProperty();
        textProperty.bindBidirectional(value, NumberFormat.getIntegerInstance(Locale.getDefault()));
        return new SimpleInputControl<>(control, value.asObject(), dflt, validate);
    }

    static SimpleInputControl decimalInput(Supplier dflt, Function> validate) {
        TextField control = new TextField();
        StringProperty textProperty = control.textProperty();
        DoubleProperty value = new SimpleDoubleProperty();
        textProperty.bindBidirectional(value, NumberFormat.getInstance(Locale.getDefault()));
        return new SimpleInputControl<>(control, value.asObject(), dflt, validate);
    }

    static SimpleInputControl checkBoxInput(Supplier dflt, String text, Function> validate) {
        CheckBox control = new CheckBox(text);
        BooleanProperty value = control.selectedProperty();
        return new SimpleInputControl<>(control, value.asObject(), dflt, validate);
    }

    static  SimpleInputControl, T> comboBoxInput(Collection choices, Supplier dflt, Function> validate) {
        ComboBox control = new ComboBox<>(FXCollections.observableArrayList(choices));
        Property value = control.valueProperty();
        return new SimpleInputControl<>(control, value, dflt, validate);
    }

    static  SimpleInputControl, T> comboBoxExInput(
            Collection choices,
            Supplier dflt,
            @Nullable UnaryOperator edit,
            @Nullable Supplier add,
            @Nullable BiPredicate, T> remove,
            Function format,
            Function> validate) {
        ComboBoxEx control = new ComboBoxEx<>(edit, add, remove, format, FXCollections.observableArrayList(choices));
        Property value = control.valueProperty();
        return new SimpleInputControl<>(control, value, dflt, validate);
    }

    static InputControl chooseFile(Supplier dflt, FileDialogMode mode, boolean existingOnly, Collection filters,
                                         Function> validate) {
        return new FileInput(mode, existingOnly, dflt, filters, validate);
    }

    /**
     * Get the Node for this input element.
     *
     * @return the node
     */
    Node node();

    /**
     * Get value.
     *
     * @return the current value
     */
    default R get() {
        return valueProperty().getValue();
    }

    Property valueProperty();

    /**
     * Set value.
     *
     * @param arg the value to set
     */
    default void set(R arg) {
        valueProperty().setValue(arg);
    }

    /**
     * Test if content is valid.
     * @return true, if content is valid
     */
    default boolean isValid() {
        return validProperty().get();
    }

    /**
     * Set/update control state.
     */
    default void init() {
        // nop
    }

    /**
     * Reset value to default
     */
    void reset();

    ReadOnlyBooleanProperty validProperty();

    ReadOnlyStringProperty errorProperty();

    class State {
        private final Property value;
        private final BooleanProperty valid = new SimpleBooleanProperty(true);
        private final StringProperty error = new SimpleStringProperty("");

        private Supplier dflt;

        private Function> validate;

        public State(Property value) {
            this(value, freeze(value));

        }

        public State(Property value, Supplier dflt) {
            this(value, dflt, s -> Optional.empty());
        }

        private static  Supplier freeze(ObservableValue value) {
            final R frozen = value.getValue();
            return () -> frozen;
        }

        public State(Property value, Supplier dflt, Function> validate) {
            this.value = value;
            this.value.addListener((v, o, n) -> updateValidState(n));
            this.dflt = dflt;
            this.validate = validate;

            this.value.addListener((v, o, n) -> updateValidState(n));
        }

        private void updateValidState(@Nullable R r) {
            Optional result = validate.apply(r);
            valid.setValue(result.isEmpty());
            error.setValue(result.orElse(""));
        }

        public void setValidate(Function> validate) {
            this.validate = validate;
            updateValidState(valueProperty().getValue());
        }

        public Property valueProperty() {
            return value;
        }

        public ReadOnlyBooleanProperty validProperty() {
            return valid;
        }

        public ReadOnlyStringProperty errorProperty() {
            return error;
        }

        public void setDefault(Supplier dflt) {
            this.dflt = dflt;
        }

        public void reset() {
            value.setValue(dflt.get());
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy