chore: 弹窗工具

This commit is contained in:
octopus_yan 2024-09-09 20:12:20 +08:00
parent c3cbbd497f
commit 88a2f705ba
6 changed files with 182 additions and 86 deletions

View File

@ -1,18 +1,80 @@
package cn.octopusyan.alistgui.util.alert;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Window;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author octopus_yan
*/
public class AlertBuilder extends BaseBuilder<AlertBuilder, Alert> {
public AlertBuilder(Alert alert, Window owner) {
super(alert, owner);
public AlertBuilder(Window owner, Alert.AlertType alertType) {
super(new Alert(alertType), owner);
}
public AlertBuilder buttons(String... buttons) {
dialog.getButtonTypes().addAll(getButtonList(buttons));
return this;
}
public AlertBuilder exception(Exception ex) {
dialog.setTitle("Exception Dialog");
dialog.setHeaderText(ex.getClass().getSimpleName());
dialog.setContentText(ex.getMessage());
// 创建可扩展的异常
var sw = new StringWriter();
var pw = new PrintWriter(sw);
ex.printStackTrace(pw);
var exceptionText = sw.toString();
var label = new Label("The exception stacktrace was :");
var textArea = new TextArea(exceptionText);
textArea.setEditable(false);
textArea.setWrapText(true);
textArea.setMaxWidth(Double.MAX_VALUE);
textArea.setMaxHeight(Double.MAX_VALUE);
GridPane.setVgrow(textArea, Priority.ALWAYS);
GridPane.setHgrow(textArea, Priority.ALWAYS);
var expContent = new GridPane();
expContent.setMaxWidth(Double.MAX_VALUE);
expContent.add(label, 0, 0);
expContent.add(textArea, 0, 1);
// 将可扩展异常设置到对话框窗格中
dialog.getDialogPane().setExpandableContent(expContent);
return this;
}
/**
* 获取按钮列表
*
* @param buttons "Cancel" / "取消" 为取消按钮
*/
private List<ButtonType> getButtonList(String[] buttons) {
if (ArrayUtils.isEmpty(buttons)) return Collections.emptyList();
return Arrays.stream(buttons).map((type) -> {
ButtonBar.ButtonData buttonData = ButtonBar.ButtonData.OTHER;
if ("cancel".equals(StringUtils.lowerCase(type)) || "取消".equals(type))
buttonData = ButtonBar.ButtonData.CANCEL_CLOSE;
return new ButtonType(type, buttonData);
}).collect(Collectors.toList());
}
/**

View File

@ -1,17 +1,9 @@
package cn.octopusyan.alistgui.util.alert;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.apache.commons.lang3.StringUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 弹窗工具
@ -26,109 +18,61 @@ public class AlertUtil {
}
public static AlertBuilder info(String content) {
AlertBuilder alertBuilder = new AlertBuilder(new Alert(Alert.AlertType.INFORMATION), mOwner);
alertBuilder.content(content).header(null);
return alertBuilder;
return info().content(content).header(null);
}
public static AlertBuilder info() {
return new AlertBuilder(new Alert(Alert.AlertType.INFORMATION), mOwner);
return alert(Alert.AlertType.INFORMATION);
}
public static AlertBuilder error(String message) {
AlertBuilder alertBuilder = new AlertBuilder(new Alert(Alert.AlertType.ERROR), mOwner);
alertBuilder.header(null).content(message);
return alertBuilder;
return alert(Alert.AlertType.ERROR).header(null).content(message);
}
public static AlertBuilder warning() {
return new AlertBuilder(new Alert(Alert.AlertType.WARNING), mOwner);
return alert(Alert.AlertType.WARNING);
}
public static AlertBuilder exception(Exception ex) {
return new AlertBuilder(exceptionAlert(ex), mOwner);
}
private static Alert exceptionAlert(Exception ex) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Exception Dialog");
alert.setHeaderText(ex.getClass().getSimpleName());
alert.setContentText(ex.getMessage());
// 创建可扩展的异常
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
String exceptionText = sw.toString();
Label label = new Label("The exception stacktrace was :");
TextArea textArea = new TextArea(exceptionText);
textArea.setEditable(false);
textArea.setWrapText(true);
textArea.setMaxWidth(Double.MAX_VALUE);
textArea.setMaxHeight(Double.MAX_VALUE);
GridPane.setVgrow(textArea, Priority.ALWAYS);
GridPane.setHgrow(textArea, Priority.ALWAYS);
GridPane expContent = new GridPane();
expContent.setMaxWidth(Double.MAX_VALUE);
expContent.add(label, 0, 0);
expContent.add(textArea, 0, 1);
// 将可扩展异常设置到对话框窗格中
alert.getDialogPane().setExpandableContent(expContent);
return alert;
return alert(Alert.AlertType.ERROR).exception(ex);
}
/**
* 确认对话框
*/
public static AlertBuilder confirm() {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("确认对话框");
return new AlertBuilder(alert, mOwner);
return alert(Alert.AlertType.CONFIRMATION);
}
/**
* 自定义确认对话框 <p>
* <code>"Cancel"</code> OR <code>"取消"</code> 为取消按钮
*
* @param buttons <code>"Cancel"</code> OR <code>"取消"</code> 为取消按钮
*/
public static AlertBuilder confirm(String... buttons) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
return confirm().buttons(buttons);
}
List<ButtonType> buttonList = Arrays.stream(buttons).map((type) -> {
ButtonBar.ButtonData buttonData = ButtonBar.ButtonData.OTHER;
if ("cancel".equals(StringUtils.lowerCase(type)) || "取消".equals(type))
buttonData = ButtonBar.ButtonData.CANCEL_CLOSE;
return new ButtonType(type, buttonData);
}).collect(Collectors.toList());
alert.getButtonTypes().setAll(buttonList);
return new AlertBuilder(alert, mOwner);
public static AlertBuilder alert(Alert.AlertType type) {
return new AlertBuilder(mOwner, type);
}
public static TextInputBuilder input(String content) {
TextInputDialog dialog = new TextInputDialog();
dialog.setContentText(content);
return new TextInputBuilder(dialog, mOwner);
return new TextInputBuilder(mOwner);
}
public static TextInputBuilder input(String content, String defaultResult) {
TextInputDialog dialog = new TextInputDialog(defaultResult);
dialog.setContentText(content);
return new TextInputBuilder(dialog, mOwner);
return new TextInputBuilder(mOwner, defaultResult).content(content);
}
@SafeVarargs
public static <T> ChoiceBuilder<T> choices(String hintText, T... choices) {
ChoiceDialog<T> dialog = new ChoiceDialog<>(choices[0], choices);
dialog.setContentText(hintText);
return new ChoiceBuilder<>(dialog, mOwner);
return new ChoiceBuilder<>(mOwner, choices).content(hintText);
}
public static ProgressBuilder progress() {
return new ProgressBuilder(mOwner);
}
public interface OnChoseListener {
void confirm();

View File

@ -13,7 +13,7 @@ import java.util.Objects;
* @author octopus_yan
*/
public abstract class BaseBuilder<T extends BaseBuilder<T, ?>, D extends Dialog<?>> {
D dialog;
protected D dialog;
public BaseBuilder(D dialog, Window mOwner) {
this.dialog = dialog;
@ -49,14 +49,19 @@ public abstract class BaseBuilder<T extends BaseBuilder<T, ?>, D extends Dialog<
return (T) this;
}
public void show() {
if (dialog.isShowing()) {
if (!Objects.equals(dialog.getContentText(), dialog.getContentText()))
dialog.setOnHidden(_ -> show());
public D getDialog() {
return dialog;
}
public void show() {
dialog.showAndWait();
}
public void close() {
if(dialog.isShowing())
dialog.close();
}
private Stage getStage() {
return (Stage) dialog.getDialogPane().getScene().getWindow();
}

View File

@ -10,6 +10,12 @@ import java.util.Optional;
* @author octopus_yan
*/
public class ChoiceBuilder<R> extends BaseBuilder<ChoiceBuilder<R>, ChoiceDialog<R>> {
@SafeVarargs
public ChoiceBuilder(Window mOwner, R... choices) {
this(new ChoiceDialog<>(choices[0], choices), mOwner);
}
public ChoiceBuilder(ChoiceDialog<R> dialog, Window mOwner) {
super(dialog, mOwner);
}
@ -17,7 +23,7 @@ public class ChoiceBuilder<R> extends BaseBuilder<ChoiceBuilder<R>, ChoiceDialog
/**
* AlertUtil.choices
*/
public R getChoice(Collection<R> choices) {
public R showAndGetChoice() {
Optional<R> result = dialog.showAndWait();
return result.orElse(null);
}

View File

@ -0,0 +1,70 @@
package cn.octopusyan.alistgui.util.alert;
import cn.octopusyan.alistgui.config.Context;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.Window;
/**
* 加载弹窗
*
* @author octopus_yan
*/
public class ProgressBuilder extends BaseBuilder<ProgressBuilder, Dialog<Void>> {
public ProgressBuilder(Window mOwner) {
this(new Dialog<>(), mOwner);
}
public ProgressBuilder(Dialog<Void> dialog, Window mOwner) {
super(dialog, mOwner);
var content = getContent();
DialogPane pane = dialog.getDialogPane();
pane.setContent(content);
pane.getButtonTypes().add(new ButtonType(
Context.getLanguageBinding("label.cancel").get(),
ButtonType.CANCEL.getButtonData()
));
for (Node child : pane.getChildren()) {
if (child instanceof ButtonBar bar) {
pane.getChildren().remove(child);
break;
}
}
}
private Pane getContent() {
HBox hBox = new HBox();
hBox.setPrefWidth(350);
hBox.setAlignment(Pos.CENTER);
hBox.setPadding(new Insets(0, 0, 0, 0));
// 取消按钮
Button cancel = new Button(Context.getLanguageBinding("label.cancel").get());
cancel.setCancelButton(true);
cancel.setOnAction(_ -> dialog.close());
// 进度条 TODO 宽度绑定
ProgressBar progressBar = new ProgressBar(-1);
progressBar.prefWidthProperty().bind(Bindings.createDoubleBinding(
() -> hBox.widthProperty().get() - cancel.widthProperty().get() - 40,
hBox.widthProperty(), cancel.widthProperty()
));
hBox.getChildren().add(progressBar);
hBox.getChildren().add(cancel);
return hBox;
}
public ProgressBuilder onCancel(Runnable run) {
dialog.setOnCloseRequest(_ -> run.run());
return this;
}
}

View File

@ -11,6 +11,15 @@ import java.util.Optional;
* @author octopus_yan
*/
public class TextInputBuilder extends BaseBuilder<TextInputBuilder, TextInputDialog> {
public TextInputBuilder(Window mOwner) {
this(new TextInputDialog(), mOwner);
}
public TextInputBuilder(Window mOwner, String defaultResult) {
this(new TextInputDialog(defaultResult), mOwner);
}
public TextInputBuilder(TextInputDialog dialog, Window mOwner) {
super(dialog, mOwner);
}