拆分模块
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
package com.ecep.contract.controller;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.ecep.contract.util.FxmlPath;
|
||||
import com.ecep.contract.util.FxmlUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
|
||||
import com.ecep.contract.Desktop;
|
||||
import com.ecep.contract.SpringApp;
|
||||
import com.ecep.contract.model.Employee;
|
||||
import com.ecep.contract.model.IdentityEntity;
|
||||
import com.ecep.contract.service.EmployeeService;
|
||||
import com.ecep.contract.service.SysConfService;
|
||||
import com.ecep.contract.util.UITools;
|
||||
import com.ecep.contract.vm.CurrentEmployee;
|
||||
import com.ecep.contract.vm.IdentityViewModel;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import javafx.stage.WindowEvent;
|
||||
import lombok.Getter;
|
||||
|
||||
public class BaseController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
|
||||
public static HashMap<String, Stage> stages = new HashMap<>();
|
||||
|
||||
public static <T extends BaseController> CompletableFuture<Void> show(Class<T> clz, Window owner) {
|
||||
return show(clz, owner, null);
|
||||
}
|
||||
|
||||
public static <T extends BaseController> CompletableFuture<Void> show(Class<T> clz, Window owner,
|
||||
Consumer<T> consumer) {
|
||||
String key = clz.getName();
|
||||
if (toFront(key)) {
|
||||
return null;
|
||||
}
|
||||
FxmlPath annotation = clz.getAnnotation(FxmlPath.class);
|
||||
if (annotation == null) {
|
||||
throw new RuntimeException("@FxmlPath is required");
|
||||
}
|
||||
|
||||
return FxmlUtils.newLoaderAsyncWithRunLater(annotation.value(), null, loader -> {
|
||||
T controller = loader.getController();
|
||||
if (consumer != null) {
|
||||
consumer.accept(controller);
|
||||
}
|
||||
controller.show(loader, owner, Modality.NONE, key);
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K extends IdentityEntity, M extends IdentityViewModel<K>, T extends BaseController> void show(
|
||||
Class<T> clz, M viewModel, Window owner) {
|
||||
String key = getKey(clz, viewModel);
|
||||
if (toFront(key)) {
|
||||
return;
|
||||
}
|
||||
FxmlPath annotation = clz.getAnnotation(FxmlPath.class);
|
||||
if (annotation == null) {
|
||||
throw new RuntimeException("@FxmlPath is required");
|
||||
}
|
||||
|
||||
FxmlUtils.newLoaderAsyncWithRunLater(annotation.value(), null, loader -> {
|
||||
T controller = loader.getController();
|
||||
if (controller instanceof AbstEntityController<?, ?>) {
|
||||
((AbstEntityController<?, M>) controller).setViewModel(viewModel);
|
||||
}
|
||||
controller.show(loader, owner, Modality.NONE, key);
|
||||
});
|
||||
}
|
||||
|
||||
private static <V> String getKey(Class<?> clz, V viewModel) {
|
||||
PropertyDescriptor idProperty = BeanUtils.getPropertyDescriptor(viewModel.getClass(), "id");
|
||||
if (idProperty != null) {
|
||||
Method readMethod = idProperty.getReadMethod();
|
||||
if (readMethod != null) {
|
||||
try {
|
||||
Object object = readMethod.invoke(viewModel);
|
||||
if (object instanceof ObservableValue<?> value) {
|
||||
return clz.getName() + "#" + value.getValue();
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return clz.getName() + "#" + viewModel.hashCode();
|
||||
}
|
||||
|
||||
public static void show(Class<?> clz, String resource, Window owner) {
|
||||
String key = clz.getName();
|
||||
if (toFront(key)) {
|
||||
return;
|
||||
}
|
||||
FxmlUtils.newLoaderAsyncWithRunLater(resource, null, loader -> {
|
||||
BaseController controller = loader.getController();
|
||||
controller.show(loader, owner, Modality.NONE, key);
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean toFront(String key) {
|
||||
Stage stage = stages.get(key);
|
||||
if (stage != null) {
|
||||
stage.toFront();
|
||||
if (!stage.isShowing()) {
|
||||
stage.show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static CompletableFuture<Void> shutdown() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("shutdown");
|
||||
}
|
||||
// 关闭所有窗口
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
ArrayList<Stage> list = new ArrayList<>(stages.values());
|
||||
if (list.isEmpty()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("no stage should to close.");
|
||||
}
|
||||
future.complete(null);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("try to close stages {}.", list);
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
for (Stage stage : list) {
|
||||
System.out.println("stage = " + stage);
|
||||
stage.close();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("stage close {}", stage);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("stage close error", e);
|
||||
}
|
||||
future.complete(null);
|
||||
});
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> runAsync(Runnable runnable) {
|
||||
return CompletableFuture.runAsync(runnable, Desktop.instance.getExecutorService())
|
||||
.exceptionally(this::handleException);
|
||||
}
|
||||
|
||||
/**
|
||||
* 窗口标题
|
||||
*/
|
||||
@Getter
|
||||
private final StringProperty title = new SimpleStringProperty("窗口");
|
||||
/**
|
||||
* 窗口是否已经请求关闭
|
||||
*/
|
||||
@Getter
|
||||
private boolean closeRequested = false;
|
||||
/**
|
||||
* 用于管理窗口的Key
|
||||
*/
|
||||
private String stageKey;
|
||||
public Label leftStatusLabel;
|
||||
public Label rightStatusLabel;
|
||||
private Employee currentUser;
|
||||
|
||||
private HashMap<Class<?>, Object> cachedBeans = new HashMap<>();
|
||||
|
||||
public <T> T getBean(Class<T> requiredType) throws BeansException {
|
||||
return SpringApp.getBean(requiredType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getCachedBean(Class<T> requiredType) throws BeansException {
|
||||
Object object = cachedBeans.get(requiredType);
|
||||
if (object == null) {
|
||||
object = getBean(requiredType);
|
||||
cachedBeans.put(requiredType, object);
|
||||
}
|
||||
return (T) object;
|
||||
}
|
||||
|
||||
public SysConfService getConfService() {
|
||||
return getCachedBean(SysConfService.class);
|
||||
}
|
||||
|
||||
public EmployeeService getEmployeeService() {
|
||||
return getCachedBean(EmployeeService.class);
|
||||
}
|
||||
|
||||
public Employee getCurrentUser() {
|
||||
if (currentUser == null) {
|
||||
currentUser = getEmployeeService().findById(Desktop.instance.getActiveEmployeeId());
|
||||
}
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
public CurrentEmployee getCurrentEmployee() {
|
||||
return Desktop.instance.getActiveEmployee();
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
CurrentEmployee currentEmployee = getCurrentEmployee();
|
||||
if (currentEmployee == null) {
|
||||
return Locale.getDefault();
|
||||
}
|
||||
return currentEmployee.localeProperty().get();
|
||||
}
|
||||
|
||||
public String getMessage(String code, Object... args) {
|
||||
return SpringApp.getMessage(code, args, getLocale());
|
||||
}
|
||||
|
||||
protected void setStatus() {
|
||||
setStatus(Strings.EMPTY);
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
if (leftStatusLabel == null) {
|
||||
return;
|
||||
}
|
||||
Platform.runLater(() -> leftStatusLabel.textProperty().set(status));
|
||||
}
|
||||
|
||||
public void setRightStatus(String status) {
|
||||
if (rightStatusLabel == null) {
|
||||
return;
|
||||
}
|
||||
Platform.runLater(() -> rightStatusLabel.textProperty().set(status));
|
||||
}
|
||||
|
||||
/**
|
||||
* FXML loader 载入时会自动运行此函数
|
||||
*/
|
||||
public void initialize() {
|
||||
|
||||
}
|
||||
|
||||
public void show(Stage stage) {
|
||||
stage.titleProperty().bind(title);
|
||||
stage.setOnShown(this::onShown);
|
||||
stage.setOnShowing(this::onShowing);
|
||||
stage.setOnCloseRequest(this::onCloseRequest);
|
||||
stage.setOnHiding(this::onHiding);
|
||||
stage.setOnHidden(this::onHidden);
|
||||
stage.show();
|
||||
}
|
||||
|
||||
public Stage show(FXMLLoader loader, Window owner, Modality modality) {
|
||||
Scene scene = new Scene(loader.getRoot());
|
||||
Stage stage = new Stage();
|
||||
if (owner != null) {
|
||||
stage.initOwner(owner);
|
||||
stage.initModality(modality);
|
||||
}
|
||||
stage.setScene(scene);
|
||||
show(stage);
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
||||
protected Stage show(FXMLLoader loader, Window window, Modality modality, String stageKey) {
|
||||
Stage stage = show(loader, window, modality);
|
||||
stages.put(stageKey, stage);
|
||||
this.stageKey = stageKey;
|
||||
return stage;
|
||||
}
|
||||
|
||||
public void onShowing(WindowEvent windowEvent) {
|
||||
|
||||
}
|
||||
|
||||
public void onShown(WindowEvent windowEvent) {
|
||||
setStatus("");
|
||||
setRightStatus("");
|
||||
}
|
||||
|
||||
/**
|
||||
* 当窗口要关闭前
|
||||
*
|
||||
* @param windowEvent event
|
||||
*/
|
||||
public void onCloseRequest(WindowEvent windowEvent) {
|
||||
closeRequested = true;
|
||||
}
|
||||
|
||||
public void onHiding(WindowEvent windowEvent) {
|
||||
|
||||
}
|
||||
|
||||
public void onHidden(WindowEvent windowEvent) {
|
||||
if (stageKey != null) {
|
||||
stages.remove(stageKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理错误
|
||||
*
|
||||
* @param ex 错误信息
|
||||
* @return Void
|
||||
*/
|
||||
public Void handleException(Throwable ex) {
|
||||
handleException(ex.getMessage(), ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void handleException(String message, Throwable ex) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(message, ex);
|
||||
}
|
||||
UITools.showExceptionAndWait(message, ex);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user