All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.dua3.fx.controls.OptionsPane Maven / Gradle / Ivy
package com.dua3.fx.controls;
import com.dua3.cabe.annotations.Nullable;
import com.dua3.utility.options.Arguments;
import com.dua3.utility.options.ChoiceOption;
import com.dua3.utility.options.Flag;
import com.dua3.utility.options.Option;
import com.dua3.utility.options.SimpleOption;
import javafx.beans.property.Property;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.util.StringConverter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class OptionsPane extends GridPane implements InputControl {
/**
* Logger
*/
protected static final Logger LOG = LogManager.getLogger(OptionsPane.class);
private static final Insets INSETS = new Insets(2);
private final InputControl.State state;
private final Supplier extends Collection>> options;
private final Supplier dflt;
private final Property value = new SimpleObjectProperty<>();
private final Map, InputControl>> items = new LinkedHashMap<>();
/**
* Create new OptionsPane.
*
* @param optionSet the available options
* @param currentValues the current values
*/
public OptionsPane(Collection > optionSet, Arguments currentValues) {
this(() -> optionSet, () -> currentValues);
}
public OptionsPane(Supplier extends Collection >> options, Supplier dflt) {
this.options = options;
this.dflt = dflt;
this.state = new State<>(value, dflt);
}
@Override
public Node node() {
return this;
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public Arguments get() {
Deque> entries = new ArrayDeque<>();
for (var entry : items.entrySet()) {
Option option = entry.getKey();
Object value = entry.getValue().valueProperty().getValue();
if (value != null) {
entries.add(Arguments.createEntry(option, value));
}
}
return Arguments.of(entries.toArray(Arguments.Entry[]::new));
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void set(Arguments arg) {
for (var item : items.entrySet()) {
Option option = item.getKey();
InputControl control = item.getValue();
Stream> stream = arg.stream(option);
Optional> value = stream.filter(list -> !list.isEmpty())
.reduce((first, second) -> second)
.map(List::getLast);
control.set(value.orElse(null));
}
}
@Override
public void init() {
getChildren().clear();
Collection> optionSet = options.get();
Arguments values = dflt.get();
int row = 0;
for (Option> option : optionSet) {
Label label = new Label(option.displayName());
var control = createControl(values, option);
items.put(option, control);
addToGrid(label, 0, row);
addToGrid(control.node(), 1, row);
row++;
}
}
@SuppressWarnings("unchecked")
private InputControl createControl(Arguments values, Option option) {
if (option instanceof ChoiceOption co) {
return new ChoiceInputControl<>(co, supplyDefault(co, values));
} else if (option instanceof Flag f) {
CheckBox checkBox = new CheckBox(f.displayName());
return (InputControl) new SimpleInputControl<>(checkBox, checkBox.selectedProperty(), supplyDefault(f, values), nopValidator());
} else if (option instanceof SimpleOption so) {
StringConverter converter = new StringConverter<>() {
@Override
public String toString(T v) {
return option.format(v);
}
@Override
public T fromString(String s) {
return option.map(s);
}
};
return InputControl.stringInput(supplyDefault(so, values), nopValidator(), converter);
}
throw new UnsupportedOperationException("unsupported input type: " + option.getClass().getName());
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static T getValue(Option option, Arguments values) {
if (option instanceof Flag flag) {
return (T) (Object) values.isSet(flag);
}
if (option instanceof SimpleOption so) {
return (T) values.get(so).orElse(so.getDefault());
}
if (option instanceof ChoiceOption co) {
return (T) values.get(co).orElse(co.getDefault());
}
throw new IllegalArgumentException("Unknown option type: " + option);
}
private static Function> nopValidator() {
return s -> Optional.empty();
}
private static Supplier supplyDefault(Option extends T> option, Arguments values) {
return () -> getValue(option, values);
}
private void addToGrid(@Nullable Node node, int c, int r) {
if (node != null) {
add(node, c, r);
setMargin(node, INSETS);
}
}
@Override
public void reset() {
items.forEach((item, control) -> control.reset());
}
@Override
public Property valueProperty() {
return state.valueProperty();
}
@Override
public ReadOnlyBooleanProperty validProperty() {
return state.validProperty();
}
@Override
public ReadOnlyStringProperty errorProperty() {
return state.errorProperty();
}
}