chore: 整理

This commit is contained in:
octopus_yan 2024-11-15 17:02:52 +08:00
parent 943056168f
commit 1dc7a64833
22 changed files with 142 additions and 87 deletions

View File

@ -71,9 +71,6 @@ public class Application extends javafx.application.Application {
Context.setApplication(this);
// 初始化弹窗工具
AlertUtil.initOwner(primaryStage);
// 全局异常处理
Thread.setDefaultUncaughtExceptionHandler(this::showErrorDialog);
Thread.currentThread().setUncaughtExceptionHandler(this::showErrorDialog);
@ -86,13 +83,11 @@ public class Application extends javafx.application.Application {
Scene scene = Context.initScene();
primaryStage.setScene(scene);
primaryStage.show();
}
private void showErrorDialog(Thread t, Throwable e) {
logger.error("未知异常", e);
Platform.runLater(() -> AlertUtil.exception(new Exception(e)).show());
Platform.runLater(() -> AlertUtil.getInstance(primaryStage).exception(new Exception(e)).show());
}
@Override

View File

@ -51,7 +51,8 @@ public abstract class BaseBuilder<T extends BaseBuilder<T, ?>, D extends Dialog<
}
public void close() {
if (dialog.isShowing())
dialog.close();
Platform.runLater(() -> {
if (dialog.isShowing()) dialog.close();
});
}
}

View File

@ -9,7 +9,6 @@ import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -29,7 +28,6 @@ import java.util.ResourceBundle;
*/
public abstract class BaseController<VM extends BaseViewModel> implements Initializable {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Getter
protected final VM viewModel;
public BaseController() {
@ -97,7 +95,7 @@ public abstract class BaseController<VM extends BaseViewModel> implements Initia
return "";
}
protected Stage getWindow() {
public Stage getWindow() {
try {
return (Stage) getRootPanel().getScene().getWindow();
} catch (Throwable _) {

View File

@ -8,7 +8,7 @@ import lombok.Setter;
* @author octopus_yan
*/
@Setter
public abstract class BaseViewModel<VM extends BaseViewModel<VM, T>, T extends BaseController<VM>> {
public abstract class BaseViewModel<T extends BaseController> {
protected T controller;

View File

@ -60,17 +60,6 @@ public class Context {
Context.application = application;
}
/**
* 有此类所在路径决定相对路径
*
* @param path 资源文件相对路径
* @return 资源文件路径
*/
// 加载资源文件
public static URL load(String path) {
return Context.class.getResource(path);
}
/**
* 初始化场景
*

View File

@ -224,6 +224,11 @@ public class ConfigManager {
getProxyInfo().setPort(port);
}
/**
* 端口检查
*
* @param consumer 检查结果信息
*/
public static void checkProxy(BiConsumer<Boolean, String> consumer) {
if (ProxySetup.SYSTEM.equals(proxySetup())) {
consumer.accept(true, "");

View File

@ -1,12 +1,20 @@
package cn.octopusyan.dmt.common.util;
import cn.octopusyan.dmt.Application;
import cn.octopusyan.dmt.common.manager.ConfigManager;
import cn.octopusyan.dmt.view.alert.AlertUtil;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* 工具
@ -55,6 +63,35 @@ public class ViewUtil {
});
}
public static void openDecorated(String title, String fxml) {
Stage open = Objects.requireNonNull(open(StageStyle.DECORATED, title, fxml));
open.setResizable(false);
open.showAndWait();
}
public static Stage open(StageStyle style, String title, String fxml) {
FXMLLoader load = FxmlUtil.load(fxml);
try {
return open(style, title, (Pane) load.load());
} catch (IOException e) {
AlertUtil.getInstance().exception(e).show();
}
return null;
}
public static Stage open(StageStyle style, String title, Pane pane) {
Stage stage = new Stage();
stage.initOwner(Application.getPrimaryStage());
stage.initStyle(style);
stage.initModality(Modality.WINDOW_MODAL);
stage.setTitle(title);
Scene scene = new Scene(pane);
scene.setUserAgentStylesheet(ConfigManager.theme().getUserAgentStylesheet());
stage.setScene(scene);
stage.sizeToScene();
return stage;
}
public static Stage getStage() {
return Application.getPrimaryStage();
}

View File

@ -8,6 +8,7 @@ import cn.octopusyan.dmt.common.config.Context;
import cn.octopusyan.dmt.common.manager.ConfigManager;
import cn.octopusyan.dmt.common.util.ClipUtil;
import cn.octopusyan.dmt.common.util.FxmlUtil;
import cn.octopusyan.dmt.common.util.ViewUtil;
import cn.octopusyan.dmt.controller.component.WordEditController;
import cn.octopusyan.dmt.model.WordItem;
import cn.octopusyan.dmt.task.TranslateTask;
@ -95,12 +96,13 @@ public class MainController extends BaseController<MainViewModel> {
@Override
public void initData() {
// 信息
ConsoleLog.init(logArea);
// 界面样式
List<MenuItem> list = ConfigManager.THEME_LIST.stream().map(this::createViewStyleItem).toList();
viewStyle.getItems().addAll(list);
// 信息
ConsoleLog.init(logArea);
fileNameLabel.textProperty().bind(viewModel.fileNameProperty());
}
@Override
@ -202,23 +204,15 @@ public class MainController extends BaseController<MainViewModel> {
/**
* 打开代理设置
*/
public void openSetupProxy() throws IOException {
FXMLLoader load = FxmlUtil.load("setup/proxy-view");
AlertUtil.builder(false)
.title("网络代理设置")
.content((Pane) load.load())
.show();
public void openSetupProxy() {
ViewUtil.openDecorated("网络代理设置", "setup/proxy-view");
}
/**
* 打开翻译设置
*/
public void openSetupTranslate() throws IOException {
FXMLLoader load = FxmlUtil.load("setup/translate-view");
AlertUtil.builder(false)
.title("翻译设置")
.content((Pane) load.load())
.show();
public void openSetupTranslate() {
ViewUtil.openDecorated("翻译设置", "setup/translate-view");
}
public void setFileName(String name) {
@ -288,7 +282,7 @@ public class MainController extends BaseController<MainViewModel> {
FileUtils.copyFile(packFile, file);
} catch (IOException e) {
consoleLog.error("保存文件失败!", e);
Platform.runLater(() -> AlertUtil.exception(e).content("保存文件失败!").show());
Platform.runLater(() -> AlertUtil.getInstance(getWindow()).exception(e).content("保存文件失败!").show());
}
}

View File

@ -55,7 +55,7 @@ public class WordEditController extends BaseController<WordEditViewModel> {
String result = TranslateFactoryImpl.getInstance().translate(ConfigManager.translateApi(), original.getText());
Platform.runLater(() -> chinese.setText(result));
} catch (Exception e) {
Platform.runLater(() -> AlertUtil.exception(e).show());
Platform.runLater(() -> AlertUtil.getInstance(getWindow()).exception(e).show());
}
Platform.runLater(() -> progress.setVisible(false));
});

View File

@ -1,4 +1,4 @@
package cn.octopusyan.dmt.controller;
package cn.octopusyan.dmt.controller.setup;
import cn.octopusyan.dmt.common.base.BaseController;
import cn.octopusyan.dmt.common.enums.ProxySetup;

View File

@ -1,4 +1,4 @@
package cn.octopusyan.dmt.controller;
package cn.octopusyan.dmt.controller.setup;
import cn.octopusyan.dmt.common.base.BaseController;
import cn.octopusyan.dmt.common.manager.ConfigManager;
@ -81,7 +81,8 @@ public class TranslateController extends BaseController<TranslateViewModel> {
ConfigManager.translateQps(source, qps);
if (source.needApiKey()) {
if (StringUtils.isBlank(apikey) || StringUtils.isBlank(appid)) {
AlertUtil.error("认证信息不能为空");
AlertUtil.getInstance(getWindow()).error("认证信息不能为空").show();
return;
}
ConfigManager.translateApikey(source, apikey);

View File

@ -22,7 +22,7 @@ public abstract class DefaultTaskListener implements Listener {
* 加载弹窗
*/
@Getter
final ProgressBuilder progress = AlertUtil.progress();
final ProgressBuilder progress = AlertUtil.getInstance().progress();
/**
* 是否展示加载弹窗

View File

@ -1,13 +1,10 @@
package cn.octopusyan.dmt.translate;
import lombok.Getter;
/**
* API 密钥配置
*
* @author octopus_yan@foxmail.com
*/
@Getter
public record ApiKey(String appid, String apiKey) {
}

View File

@ -1,5 +1,6 @@
package cn.octopusyan.dmt.view.alert;
import cn.octopusyan.dmt.Application;
import cn.octopusyan.dmt.view.alert.builder.*;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
@ -12,44 +13,56 @@ import javafx.stage.Window;
* @author octopus_yan@foxmail.com
*/
public class AlertUtil {
private static Window mOwner;
private final Window mOwner;
private static volatile AlertUtil alertUtil;
public static void initOwner(Stage stage) {
AlertUtil.mOwner = stage;
private AlertUtil(Window mOwner) {
this.mOwner = mOwner;
}
public static DefaultBuilder builder() {
public static synchronized AlertUtil getInstance() {
if (alertUtil == null) {
alertUtil = new AlertUtil(Application.getPrimaryStage());
}
return alertUtil;
}
public static AlertUtil getInstance(Stage stage) {
return new AlertUtil(stage);
}
public DefaultBuilder builder() {
return new DefaultBuilder(mOwner, true);
}
public static DefaultBuilder builder(boolean transparent) {
public DefaultBuilder builder(boolean transparent) {
return new DefaultBuilder(mOwner, transparent);
}
public static AlertBuilder info(String content) {
public AlertBuilder info(String content) {
return info().content(content).header(null);
}
public static AlertBuilder info() {
public AlertBuilder info() {
return alert(Alert.AlertType.INFORMATION);
}
public static AlertBuilder error(String message) {
public AlertBuilder error(String message) {
return alert(Alert.AlertType.ERROR).header(null).content(message);
}
public static AlertBuilder warning() {
public AlertBuilder warning() {
return alert(Alert.AlertType.WARNING);
}
public static AlertBuilder exception(Exception ex) {
public AlertBuilder exception(Exception ex) {
return alert(Alert.AlertType.ERROR).exception(ex);
}
/**
* 确认对话框
*/
public static AlertBuilder confirm() {
public AlertBuilder confirm() {
return alert(Alert.AlertType.CONFIRMATION);
}
@ -58,32 +71,32 @@ public class AlertUtil {
*
* @param buttons <code>"Cancel"</code> OR <code>"取消"</code> 为取消按钮
*/
public static AlertBuilder confirm(String... buttons) {
public AlertBuilder confirm(String... buttons) {
return confirm().buttons(buttons);
}
public static AlertBuilder confirm(ButtonType... buttons) {
public AlertBuilder confirm(ButtonType... buttons) {
return confirm().buttons(buttons);
}
public static AlertBuilder alert(Alert.AlertType type) {
public AlertBuilder alert(Alert.AlertType type) {
return new AlertBuilder(mOwner, type);
}
public static TextInputBuilder input(String content) {
public TextInputBuilder input(String content) {
return new TextInputBuilder(mOwner);
}
public static TextInputBuilder input(String content, String defaultResult) {
public TextInputBuilder input(String content, String defaultResult) {
return new TextInputBuilder(mOwner, defaultResult).content(content);
}
@SafeVarargs
public static <T> ChoiceBuilder<T> choices(String hintText, T... choices) {
public final <T> ChoiceBuilder<T> choices(String hintText, T... choices) {
return new ChoiceBuilder<>(mOwner, choices).content(hintText);
}
public static ProgressBuilder progress() {
public ProgressBuilder progress() {
return new ProgressBuilder(mOwner);
}

View File

@ -1,5 +1,6 @@
package cn.octopusyan.dmt.viewModel;
import atlantafx.base.theme.Styles;
import cn.octopusyan.dmt.common.base.BaseViewModel;
import cn.octopusyan.dmt.controller.MainController;
import cn.octopusyan.dmt.model.WordItem;
@ -11,6 +12,8 @@ import cn.octopusyan.dmt.translate.DelayWord;
import cn.octopusyan.dmt.translate.TranslateUtil;
import cn.octopusyan.dmt.view.ConsoleLog;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Worker;
import javafx.scene.control.ProgressIndicator;
import org.apache.commons.lang3.StringUtils;
@ -28,7 +31,7 @@ import java.util.regex.Pattern;
*
* @author octopus_yan
*/
public class MainViewModel extends BaseViewModel<MainViewModel, MainController> {
public class MainViewModel extends BaseViewModel<MainController> {
private static final ConsoleLog consoleLog = ConsoleLog.getInstance(MainViewModel.class);
/**
* 解包任务
@ -38,9 +41,7 @@ public class MainViewModel extends BaseViewModel<MainViewModel, MainController>
* 翻译任务
*/
private TranslateTask translateTask;
private DelayQueue<DelayWord> delayQueue;
private String unpackPath;
private int total;
@ -48,13 +49,19 @@ public class MainViewModel extends BaseViewModel<MainViewModel, MainController>
FontIcon pauseIcon = new FontIcon(Feather.PAUSE);
private List<WordItem> wordItems;
private final StringProperty fileName = new SimpleStringProperty();
public StringProperty fileNameProperty() {
return fileName;
}
/**
* 加载PBO文件
*/
public void selectFile(File pboFile) {
if (pboFile == null) return;
controller.setFileName(pboFile.getAbsolutePath());
fileName.setValue(pboFile.getAbsolutePath());
unpackTask = new UnpackTask(pboFile);
}
@ -185,6 +192,7 @@ public class MainViewModel extends BaseViewModel<MainViewModel, MainController>
private void resetProgress() {
translateTask = null;
controller.translate.setGraphic(startIcon);
Styles.toggleStyleClass(controller.translateProgress, Styles.SMALL);
controller.translateProgress.progressProperty().unbind();
controller.translateProgress.setProgress(0);
controller.translateProgress.setVisible(false);

View File

@ -4,7 +4,7 @@ import cn.octopusyan.dmt.common.base.BaseViewModel;
import cn.octopusyan.dmt.common.enums.ProxySetup;
import cn.octopusyan.dmt.common.manager.ConfigManager;
import cn.octopusyan.dmt.common.manager.http.HttpUtil;
import cn.octopusyan.dmt.controller.ProxyController;
import cn.octopusyan.dmt.controller.setup.ProxyController;
import cn.octopusyan.dmt.task.ProxyCheckTask;
import cn.octopusyan.dmt.task.listener.DefaultTaskListener;
import cn.octopusyan.dmt.view.alert.AlertUtil;
@ -16,20 +16,22 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.apache.commons.lang3.StringUtils;
import java.net.URI;
/**
* 设置
*
* @author octopus_yan
*/
public class ProxyViewModel extends BaseViewModel<ProxyViewModel, ProxyController> {
public class ProxyViewModel extends BaseViewModel<ProxyController> {
private final StringProperty proxyHost = new SimpleStringProperty(ConfigManager.proxyHost());
private final StringProperty proxyPort = new SimpleStringProperty(ConfigManager.proxyPort());
private final ObjectProperty<ProxySetup> proxySetup = new SimpleObjectProperty<>(ConfigManager.proxySetup());
private final StringProperty proxyTestUrl = new SimpleStringProperty(ConfigManager.proxyTestUrl());
private final AlertUtil alertUtil = AlertUtil.getInstance();
public ProxyViewModel() {
proxySetup.addListener((_, _, newValue) -> ConfigManager.proxySetup(newValue));
proxyTestUrl.addListener((_, _, newValue) -> ConfigManager.proxyTestUrl(newValue));
proxyHost.addListener((_, _, newValue) -> {
ConfigManager.proxyHost(newValue);
setProxy();
@ -53,30 +55,43 @@ public class ProxyViewModel extends BaseViewModel<ProxyViewModel, ProxyControlle
}
public void proxyTest() {
var checkUrl = AlertUtil.input("URL :", proxyTestUrl.getValue())
var checkUrl = alertUtil.input("URL :", ConfigManager.proxyTestUrl())
.title("检查代理设置")
.header("请输入您要检查的任何URL")
.getInput();
if (StringUtils.isEmpty(checkUrl)) return;
proxyTestUrl.setValue(checkUrl);
// 检查URL格式
if (!checkUrl(checkUrl)) return;
ProgressBuilder progress = AlertUtil.progress();
ConfigManager.proxyTestUrl(checkUrl);
ProgressBuilder progress = alertUtil.progress();
progress.show();
ConfigManager.checkProxy((success, msg) -> {
Platform.runLater(progress::close);
if (!success) {
final var tmp = "连接问题: ";
AlertUtil.error(STR."\{tmp}\{msg}").show();
alertUtil.error(STR."\{tmp}\{msg}").show();
return;
}
HttpUtil.getInstance().proxy(ConfigManager.proxySetup(), ConfigManager.getProxyInfo());
// 代理检查任务
getProxyCheckTask(checkUrl).execute();
});
}
private boolean checkUrl(String checkUrl) {
try {
//noinspection ResultOfMethodCallIgnored
URI.create(checkUrl);
return true;
} catch (Exception e) {
return false;
}
}
private void setProxy() {
ConfigManager.checkProxy((success, msg) -> {
if (!success) {
@ -87,19 +102,19 @@ public class ProxyViewModel extends BaseViewModel<ProxyViewModel, ProxyControlle
});
}
private static ProxyCheckTask getProxyCheckTask(String checkUrl) {
private ProxyCheckTask getProxyCheckTask(String checkUrl) {
var task = new ProxyCheckTask(checkUrl);
task.onListen(new DefaultTaskListener(true) {
@Override
public void onSucceed() {
AlertUtil.info("连接成功").show();
alertUtil.info("连接成功").show();
}
@Override
public void onFailed(Throwable throwable) {
super.onFailed(throwable);
AlertUtil.exception(new Exception(throwable)).show();
alertUtil.exception(new Exception(throwable)).show();
}
});
return task;

View File

@ -2,7 +2,7 @@ package cn.octopusyan.dmt.viewModel;
import cn.octopusyan.dmt.common.base.BaseViewModel;
import cn.octopusyan.dmt.common.manager.ConfigManager;
import cn.octopusyan.dmt.controller.TranslateController;
import cn.octopusyan.dmt.controller.setup.TranslateController;
import cn.octopusyan.dmt.translate.TranslateApi;
import javafx.beans.property.*;
import lombok.Getter;
@ -13,7 +13,7 @@ import lombok.Getter;
* @author octopus_yan
*/
@Getter
public class TranslateViewModel extends BaseViewModel<TranslateViewModel, TranslateController> {
public class TranslateViewModel extends BaseViewModel<TranslateController> {
private final ObjectProperty<TranslateApi> source = new SimpleObjectProperty<>(ConfigManager.translateApi()) {
{

View File

@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class WordEditViewModel extends BaseViewModel<WordEditViewModel, WordEditController> {
public class WordEditViewModel extends BaseViewModel<WordEditController> {
private WordItem data;
/**

View File

@ -24,5 +24,7 @@ module cn.octopusyan.dmt {
opens cn.octopusyan.dmt.common.base to javafx.fxml;
opens cn.octopusyan.dmt.controller to javafx.fxml;
opens cn.octopusyan.dmt.controller.component to javafx.fxml;
opens cn.octopusyan.dmt.controller.setup to javafx.fxml;
opens cn.octopusyan.dmt.controller.help to javafx.fxml;
opens cn.octopusyan.dmt.view.filemanager to javafx.fxml;
}

View File

@ -5,7 +5,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<?import org.kordamp.ikonli.javafx.*?>
<StackPane xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1"
fx:id="root" prefHeight="800.0" prefWidth="1000.0"
fx:controller="cn.octopusyan.dmt.controller.MainController">
@ -55,7 +55,7 @@
<Button text="打包" onAction="#startPack"/>
</ToolBar>
<VBox prefHeight="${root.height}">
<ProgressBar fx:id="translateProgress" styleClass="small" prefWidth="Infinity" progress="0" visible="false"/>
<ProgressBar fx:id="translateProgress" prefWidth="Infinity" progress="0" visible="false"/>
<SplitPane dividerPositions="0.25" prefWidth="Infinity" VBox.vgrow="ALWAYS">
<DirectoryTree fx:id="treeFileBox" maxWidth="420" minWidth="40"/>
<StackPane GridPane.columnIndex="1" minWidth="40">

View File

@ -4,7 +4,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
fx:controller="cn.octopusyan.dmt.controller.ProxyController"
fx:controller="cn.octopusyan.dmt.controller.setup.ProxyController"
fx:id="root" prefHeight="400.0" prefWidth="600.0" spacing="10">
<padding>

View File

@ -4,7 +4,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
fx:controller="cn.octopusyan.dmt.controller.TranslateController"
fx:controller="cn.octopusyan.dmt.controller.setup.TranslateController"
fx:id="root" prefHeight="400.0" prefWidth="600.0">
<padding>