Commit 02cbb46a authored by Axel Howind's avatar Axel Howind

fix dialogs not being initialized correctly

parent b2afcf7e
......@@ -41,7 +41,7 @@ public class DialogSample extends Application {
// Confirmation
container.getChildren().add(createButton("Confirmation", () -> {
Dialogs.confirmation()
.title("Confimration")
.title("Confirmation")
.header("This is a conformation dialog.")
.text("And this is an additional text providing details.")
.showAndWait();
......@@ -52,7 +52,6 @@ public class DialogSample extends Application {
Dialogs.prompt()
.title("Prompt")
.header("This is a prompt dialog.")
.text("Enter txt here: ")
.showAndWait();
}));
......@@ -61,7 +60,6 @@ public class DialogSample extends Application {
Dialogs.input()
.title("Input")
.header("This is an input dialog.")
.text("Enter data here: ")
.string("txt", "enter text", () -> "dflt")
.integer("integer", "enter number", () -> 0)
.integer("integer from 4 to 7", "enter number", () -> 0,
......
......@@ -18,7 +18,7 @@ import com.dua3.fx.util.controls.AboutDialogBuilder;
import com.dua3.fx.util.controls.AlertBuilder;
import com.dua3.fx.util.controls.AlertPaneBuilder;
import com.dua3.fx.util.controls.InputDialogBuilder;
import com.dua3.fx.util.controls.InputDialogPaneBuilder;
import com.dua3.fx.util.controls.InputPaneBuilder;
import com.dua3.fx.util.controls.OptionsDialogBuilder;
import com.dua3.fx.util.controls.PromptBuilder;
import com.dua3.fx.util.controls.WizardDialogBuilder;
......@@ -152,8 +152,8 @@ public class Dialogs {
* @return
* new {@link InputDialogBuilder} instance
*/
public static InputDialogPaneBuilder inputPane() {
return new InputDialogPaneBuilder();
public static InputPaneBuilder inputPane() {
return new InputPaneBuilder();
}
/**
......
......@@ -29,8 +29,8 @@ public abstract class AbstractDialogBuilder<D extends Dialog<R>, B extends Abstr
private final BiConsumer<D,String> titleSetter;
protected AbstractDialogBuilder(Supplier<D> supplier) {
super(supplier, Dialog::setHeaderText, Dialog::setContentText);
protected AbstractDialogBuilder() {
super(Dialog::setHeaderText);
this.titleSetter = Dialog::setTitle;
}
......
......@@ -36,7 +36,7 @@ public abstract class AbstractDialogPaneBuilder<D, B extends AbstractDialogPaneB
*
* @param <R> the result type
*/
public static interface ResultHandler<R> {
public interface ResultHandler<R> {
/**
* Handle result.
*
......@@ -53,27 +53,22 @@ public abstract class AbstractDialogPaneBuilder<D, B extends AbstractDialogPaneB
boolean handleResult(ButtonType btn, R result);
}
final BiConsumer<D, String> headerSetter;
final BiConsumer<D, String> textSetter;
private final BiConsumer<D, String> headerSetter;
AbstractDialogPaneBuilder(
Supplier<D> supplier,
BiConsumer<D, String> headerSetter,
BiConsumer<D, String> textSetter
BiConsumer<D, String> headerSetter
) {
this.supplier = supplier;
this.dialogSupplier = () -> { throw new IllegalStateException("call setDialogSupplier() first"); };
this.headerSetter=headerSetter;
this.textSetter=textSetter;
}
private Supplier<D> supplier;
private Supplier<D> dialogSupplier;
private String header = null;
private String text = null;
private ResultHandler<R> resultHandler = (b,r) -> true;
protected void setSupplier(Supplier<D> supplier) {
this.supplier = Objects.requireNonNull(supplier);
protected final void setDialogSupplier(Supplier<D> dialogSupplier) {
this.dialogSupplier = Objects.requireNonNull(dialogSupplier);
}
protected static <C,D> void applyIfNotNull(BiConsumer<C,D> consumer, C a, D b) {
......@@ -91,10 +86,9 @@ public abstract class AbstractDialogPaneBuilder<D, B extends AbstractDialogPaneB
* @return Alert instance
*/
public D build() {
D dlg = supplier.get();
D dlg = dialogSupplier.get();
applyIfNotNull(headerSetter, dlg, header);
applyIfNotNull(textSetter, dlg, text);
return dlg;
}
......@@ -114,21 +108,6 @@ public abstract class AbstractDialogPaneBuilder<D, B extends AbstractDialogPaneB
return (B) this;
}
/**
* Set text.
* @param fmt
* the format String as defined by {@link java.util.Formatter}
* @param args
* the arguments passed to the formatter
* @return
* {@code this}
*/
@SuppressWarnings("unchecked")
public B text(String fmt, Object... args) {
this.text = format(fmt, args);
return (B) this;
}
@SuppressWarnings("unchecked")
public B resultHandler(ResultHandler<R> resultHandler) {
this.resultHandler = Objects.requireNonNull(resultHandler);
......
......@@ -13,8 +13,8 @@ import javafx.scene.control.DialogPane;
*/
public class AbstractPaneBuilder<D extends DialogPane & Supplier<R>, B extends AbstractPaneBuilder<D,B,R>,R>
extends AbstractDialogPaneBuilder<D, B,R> {
protected AbstractPaneBuilder(Supplier<D> supplier) {
super(supplier, DialogPane::setHeaderText, DialogPane::setContentText);
protected AbstractPaneBuilder() {
super(DialogPane::setHeaderText);
}
String next = null;
......
......@@ -30,9 +30,10 @@ import javafx.scene.control.DialogPane;
public class AlertBuilder
extends AbstractDialogBuilder<Alert, AlertBuilder, ButtonType> {
public AlertBuilder(AlertType type) {
super(() -> new Alert(type));
setDialogSupplier( () -> new Alert(type) );
}
private String text = null;
private ButtonType[] buttons;
private ButtonType defaultButton;
......@@ -56,9 +57,27 @@ public class AlertBuilder
}
}
if (text!=null) {
dlg.setContentText(text);
}
return dlg;
}
/**
* Set text.
* @param fmt
* the format String as defined by {@link java.util.Formatter}
* @param args
* the arguments passed to the formatter
* @return
* {@code this}
*/
public AlertBuilder text(String fmt, Object... args) {
this.text = format(fmt, args);
return this;
}
/**
* Define Alert Buttons.
*
......
......@@ -23,31 +23,36 @@ import javafx.scene.control.Alert.AlertType;
*/
public class AlertPaneBuilder
extends AbstractPaneBuilder<InputDialogPane<Void>, AlertPaneBuilder, Void> {
private String text = null;
public AlertPaneBuilder(AlertType type) {
super(() -> createPane(type));
super();
setDialogSupplier(() -> createPane(type));
}
public AlertPaneBuilder text(String fmt, Object... args) {
this.text = format(fmt, args);
return this;
}
public static InputDialogPane<Void> createPane(AlertType type) {
return new InputDialogPane<Void>() {
private static InputDialogPane<Void> createPane(AlertType type) {
return new InputDialogPane<>() {
@Override
public Void get() {
return null;
}
@Override
public void init() {
// nop
}
};
}
/**
* Create Alert instance.
* @return Alert instance
*/
@Override
public InputDialogPane<Void> build() {
InputDialogPane<Void> dlg = super.build();
return dlg;
public InputDialogPane<Void> build() {
InputDialogPane<Void> inputPane = super.build();
applyIfNotNull((pane,text) -> pane.setContentText(text), inputPane, text);
return inputPane;
}
}
......@@ -28,6 +28,22 @@ public interface InputBuilder<B extends InputBuilder<B>> {
*/
<T> B add(String id, String label, Class<T> type, Supplier<T> dflt, InputControl<T> control);
/**
* Add unlabeled input control.
*
* @param id
* the control's ID
* @param type
* the result type
* @param dflt
* supplier of default value
* @param control
* the control
* @return
* {@code this}
*/
<T> B add(String id, Class<T> type, Supplier<T> dflt, InputControl<T> control);
/**
* Set number of columns for layout (default is 1).
* @param columns
......
......@@ -22,6 +22,7 @@ import java.util.function.Supplier;
import com.dua3.utility.options.OptionSet;
import com.dua3.utility.options.OptionValues;
import javafx.scene.control.Label;
/**
* Builder for Alert Dialogs.
......@@ -32,18 +33,32 @@ public class InputDialogBuilder
extends AbstractDialogBuilder<InputDialog, InputDialogBuilder, Map<String, Object>>
implements InputBuilder<InputDialogBuilder> {
private final InputDialogPaneBuilder pb = new InputDialogPaneBuilder();
private final InputPaneBuilder pb = new InputPaneBuilder();
public InputDialogBuilder() {
super(InputDialog::new);
setDialogSupplier(this::createDialog);
}
@Override
public <T> InputDialogBuilder add(String id, String label, Class<T> type, Supplier<T> dflt, InputControl<T> control) {
pb.add(id, label, type, dflt, control);
return this;
private InputDialog createDialog() {
InputDialog dlg = new InputDialog();
InputPane dialogPane = pb.build();
dialogPane.init();
dlg.setDialogPane(dialogPane);
return dlg;
}
@Override
public <T> InputDialogBuilder add(String id, String label, Class<T> type, Supplier<T> dflt, InputControl<T> control) {
pb.add(id, label, type, dflt, control);
return this;
}
@Override
public <T> InputDialogBuilder add(String id, Class<T> type, Supplier<T> dflt, InputControl<T> control) {
pb.add(id, type, dflt, control);
return this;
}
@Override
public InputDialogBuilder columns(int columns) {
pb.columns(columns);
......@@ -91,14 +106,5 @@ implements InputBuilder<InputDialogBuilder> {
pb.options(id, label, dflt, options);
return this;
}
@Override
public InputDialog build() {
InputDialog dlg = super.build();
dlg.setDialogPane(pb.build());
return dlg;
}
}
......@@ -74,15 +74,15 @@ public class InputPane extends InputDialogPane<Map<String,Object>> {
public Map<String, Object> get() {
// Collecors.toMap() does not support null values!
Map<String,Object> result = new HashMap<>();
data.stream().forEach(e -> result.put(e.id, e.control.get()));
data.forEach(e -> result.put(e.id, e.control.get()));
return result;
}
public InputPane() {
}
private void addToGrid(Node child, int c, int r, Insets insets) {
grid.add(child, c, r);
private void addToGrid(Node child, int c, int r, int span, Insets insets) {
grid.add(child, c, r, span, 1);
GridPane.setMargin(child, insets);
}
......@@ -111,9 +111,22 @@ public class InputPane extends InputDialogPane<Map<String,Object>> {
int r = 0, c = 0;
for (var entry : data) {
// add label and control
addToGrid(entry.label, 3 * c, r, insets);
addToGrid(entry.control.node(), 3 * c + 1, r, insets);
addToGrid(entry.marker, 3 * c + 2, r, markerInsets);
int gridX = 3*c;
int gridY = r;
int span;
if (entry.label != null) {
addToGrid(entry.label, gridX, gridY, 1, insets);
gridX++;
span = 1;
} else {
span = 2;
}
addToGrid(entry.control.node(), gridX, gridY, span, insets);
gridX += span;
addToGrid(entry.marker, gridX, gridY, 1, markerInsets);
entry.control.init();
......@@ -131,7 +144,7 @@ public class InputPane extends InputDialogPane<Map<String,Object>> {
// validate all input fields. validation succeeds if no validation returns an error message.
// do not use allMatches() because it might not process all items
return data.stream()
.map(item -> validateAndMark(item))
.map(this::validateAndMark)
.filter(Optional::isPresent)
.count() == 0;
}
......
......@@ -38,35 +38,48 @@ import javafx.scene.control.TextField;
*
* Provides a fluent interface to create Alerts.
*/
public class InputDialogPaneBuilder
extends AbstractPaneBuilder<InputPane, InputDialogPaneBuilder, Map<String, Object>>
implements InputBuilder<InputDialogPaneBuilder> {
public class InputPaneBuilder
extends AbstractPaneBuilder<InputPane, InputPaneBuilder, Map<String, Object>>
implements InputBuilder<InputPaneBuilder> {
public InputDialogPaneBuilder() {
super(InputPane::new);
public InputPaneBuilder() {
super();
setDialogSupplier(InputPane::new);
}
private int columns = 1;
private LinkedHashMap<String, InputPane.Meta<?>> data = new LinkedHashMap<>();
/* (non-Javadoc)
/* (non-Javadoc)
* @see com.dua3.fx.util.controls.InputBuilder#add(java.lang.String, java.lang.String, java.lang.Class, T, com.dua3.fx.util.controls.InputDialogPane.InputControl)
*/
@Override
public <T> InputDialogPaneBuilder add(String id, String label, Class<T> type, Supplier<T> dflt, InputControl<T> control) {
Objects.requireNonNull(id);
Meta<T> meta = new Meta<>(id, label, type, dflt, control);
Meta<?> prev = data.put(id, meta);
LangUtil.check(prev == null, "Input with id '" + id + "' already defined");
return this;
}
@Override
public <T> InputPaneBuilder add(String id, String label, Class<T> type, Supplier<T> dflt, InputControl<T> control) {
Objects.requireNonNull(id);
Meta<T> meta = new Meta<>(id, label, type, dflt, control);
Meta<?> prev = data.put(id, meta);
LangUtil.check(prev == null, "Input with id '" + id + "' already defined");
return this;
}
/* (non-Javadoc)
* @see com.dua3.fx.util.controls.InputBuilder#add(java.lang.String, java.lang.String, java.lang.Class, T, com.dua3.fx.util.controls.InputDialogPane.InputControl)
*/
@Override
public <T> InputPaneBuilder add(String id, Class<T> type, Supplier<T> dflt, InputControl<T> control) {
Objects.requireNonNull(id);
Meta<T> meta = new Meta<>(id, null, type, dflt, control);
Meta<?> prev = data.put(id, meta);
LangUtil.check(prev == null, "Input with id '" + id + "' already defined");
return this;
}
/* (non-Javadoc)
* @see com.dua3.fx.util.controls.InputBuilder#columns(int)
*/
@Override
public InputDialogPaneBuilder columns(int columns) {
public InputPaneBuilder columns(int columns) {
LangUtil.check(columns > 0);
this.columns = columns;
return this;
......@@ -76,9 +89,9 @@ implements InputBuilder<InputDialogPaneBuilder> {
* @see com.dua3.fx.util.controls.InputBuilder#text(java.lang.String, java.lang.String, java.lang.String, java.util.function.Function)
*/
@Override
public InputDialogPaneBuilder string(String id, String label, Supplier<String> dflt, Function<String,Optional<String>> validate) {
public InputPaneBuilder string(String id, String label, Supplier<String> dflt, Function<String,Optional<String>> validate) {
return add(id, label, String.class, dflt,
new InputControl<String>() {
new InputControl<>() {
final TextField control = new TextField();
@Override
......@@ -107,9 +120,9 @@ implements InputBuilder<InputDialogPaneBuilder> {
* @see com.dua3.fx.util.controls.InputBuilder#integer(java.lang.String, java.lang.String, java.lang.Integer, java.util.function.Function)
*/
@Override
public InputDialogPaneBuilder integer(String id, String label, Supplier<Integer> dflt, Function<Integer,Optional<String>> validate) {
public InputPaneBuilder integer(String id, String label, Supplier<Integer> dflt, Function<Integer,Optional<String>> validate) {
return add(id, label, Integer.class, dflt,
new InputControl<Integer>() {
new InputControl<>() {
final TextField control = new TextField();
@Override
......@@ -144,9 +157,9 @@ implements InputBuilder<InputDialogPaneBuilder> {
* @see com.dua3.fx.util.controls.InputBuilder#decimal(java.lang.String, java.lang.String, java.lang.Double, java.util.function.Function)
*/
@Override
public InputDialogPaneBuilder decimal(String id, String label, Supplier<Double> dflt, Function<Double,Optional<String>> validate) {
public InputPaneBuilder decimal(String id, String label, Supplier<Double> dflt, Function<Double,Optional<String>> validate) {
return add(id, label, Double.class, dflt,
new InputControl<Double>() {
new InputControl<>() {
final TextField control = new TextField();
@Override
......@@ -181,9 +194,9 @@ implements InputBuilder<InputDialogPaneBuilder> {
* @see com.dua3.fx.util.controls.InputBuilder#checkBox(java.lang.String, java.lang.String, boolean, java.lang.String)
*/
@Override
public InputDialogPaneBuilder checkBox(String id, String label, Supplier<Boolean> dflt, String text) {
public InputPaneBuilder checkBox(String id, String label, Supplier<Boolean> dflt, String text) {
return add(id, label, Boolean.class, dflt,
new InputControl<Boolean>() {
new InputControl<>() {
final CheckBox control = new CheckBox(text);
{
......@@ -216,9 +229,9 @@ implements InputBuilder<InputDialogPaneBuilder> {
* @see com.dua3.fx.util.controls.InputBuilder#comboBox(java.lang.String, java.lang.String, T, java.lang.Class, java.util.Collection)
*/
@Override
public <T> InputDialogPaneBuilder comboBox(String id, String label, Supplier<T> dflt, Class<T> cls, Collection<T> items) {
public <T> InputPaneBuilder comboBox(String id, String label, Supplier<T> dflt, Class<T> cls, Collection<T> items) {
return add(id, label, cls, dflt,
new InputControl<T>() {
new InputControl<>() {
final ComboBox<T> control = new ComboBox<>();
{
......@@ -256,12 +269,12 @@ implements InputBuilder<InputDialogPaneBuilder> {
* @see com.dua3.fx.util.controls.InputBuilder#radioList(java.lang.String, java.lang.String, T, java.lang.Class, java.util.Collection)
*/
@Override
public <T> InputDialogPaneBuilder radioList(String id, String label, Supplier<T> dflt, Class<T> cls, Collection<T> items) {
public <T> InputPaneBuilder radioList(String id, String label, Supplier<T> dflt, Class<T> cls, Collection<T> items) {
return add(id, label, cls, dflt, new RadioPane<>(items, null));
}
@Override
public InputDialogPaneBuilder options(String id, String label, Supplier<OptionValues> dflt, Supplier<OptionSet> options) {
public InputPaneBuilder options(String id, String label, Supplier<OptionValues> dflt, Supplier<OptionSet> options) {
return add(id, label, OptionValues.class, dflt, new OptionsPane(options, dflt));
}
......
......@@ -57,6 +57,7 @@ public class OptionsDialog extends Dialog<OptionValues> {
public void setOptions(OptionSet optionSet, OptionValues currentValues) {
LangUtil.check(optionPane==null, "setOptions() already called!");
this.optionPane = new OptionsPane(optionSet, currentValues);
optionPane.init();
getDialogPane().setContent(optionPane);
}
......
// Copyright 2019 Axel Howind
//
//
// 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.
......@@ -21,18 +21,18 @@ import com.dua3.utility.options.OptionValues;
/**
* Builder for Alert Dialogs.
*
*
* Provides a fluent interface to create Alerts.
*/
public class OptionsDialogBuilder extends AbstractDialogBuilder<OptionsDialog, OptionsDialogBuilder, OptionValues> {
public OptionsDialogBuilder() {
super(OptionsDialog::new);
setDialogSupplier(OptionsDialog::new);
}
private OptionSet options = new OptionSet();
private OptionValues currentValues = OptionValues.empty();
@Override
public OptionsDialog build() {
OptionsDialog dlg = super.build();
......@@ -44,7 +44,7 @@ public class OptionsDialogBuilder extends AbstractDialogBuilder<OptionsDialog, O
/**
* Set options.
* @param options
* @param options
* the options to set
* @return
* this builder instance
......@@ -56,7 +56,7 @@ public class OptionsDialogBuilder extends AbstractDialogBuilder<OptionsDialog, O
/**
* Set current values.
* @param currentValues
* @param currentValues
* the currentValues to set
* @return
* this builder instance
......
......@@ -23,12 +23,12 @@ import javafx.scene.control.TextInputDialog;
*/
public class PromptBuilder extends AbstractDialogBuilder<TextInputDialog, PromptBuilder, String> {
public PromptBuilder() {
super(TextInputDialog::new);
setDialogSupplier(TextInputDialog::new);
}
public PromptBuilder defaultValue(String fmt, Object... args) {
String defaultValue = args.length==0 ? fmt : String.format(fmt, args);
setSupplier(() -> new TextInputDialog(defaultValue));
setDialogSupplier(() -> new TextInputDialog(defaultValue));
return this;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment