package com.ecep.contract.controller; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.function.Function; import com.ecep.contract.controller.tab.AbstEntityBasedTabSkin; import com.ecep.contract.controller.tab.RefreshableSkin; import com.ecep.contract.controller.tab.TabSkin; import com.ecep.contract.model.IdentityEntity; import com.ecep.contract.service.QueryService; import com.ecep.contract.service.ViewModelService; import com.ecep.contract.util.UITools; import com.ecep.contract.vm.BaseViewModel; import com.ecep.contract.vm.IdentityViewModel; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; import javafx.beans.property.BooleanProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.control.Button; import javafx.scene.control.Tab; import javafx.stage.WindowEvent; import lombok.Getter; import lombok.Setter; public abstract class AbstEntityController> extends BaseController { /** * 保存按钮 */ public Button saveBtn; @Getter @Setter protected TV viewModel; @Getter @Setter protected CompletableFuture loadedFuture; private final ObservableList tabSkins = FXCollections.observableArrayList(); @Override public void onShown(WindowEvent windowEvent) { super.onShown(windowEvent); ViewModelService service = getViewModelService(); if (service instanceof QueryService queryService) { setStatus("读取..."); loadedFuture = queryService.asyncFindById(viewModel.getId().get()); loadedFuture.thenAccept(entity -> { // fixed, bind change if new view model create if (viewModel != null) { viewModel.bindListener(); } setStatus(); // BaseViewModel.updateInFxApplicationThread(entity, viewModel); }); loadedFuture.exceptionally(ex -> { handleException("载入失败,#" + viewModel.getId().get(), ex); return null; }); } else { loadedFuture = CompletableFuture.supplyAsync(() -> { T entity = getViewModelService().findById(viewModel.getId().get()); if (entity == null) { return null; } Platform.runLater(() -> { setStatus(); viewModel.update(entity); }); viewModel.bindListener(); return entity; }); } registerTabSkins(); if (saveBtn != null) { saveBtn.disableProperty().bind(createTabSkinChangedBindings().not()); saveBtn.setOnAction(event -> saveTabSkins()); } installTabSkins(); } public T getEntity() { return getLoadedFuture().join(); } protected void setEntity(T entity) { loadedFuture = CompletableFuture.completedFuture(entity); BaseViewModel.updateInFxApplicationThread(entity, viewModel); } protected T saveEntity(T entity) { return getViewModelService().save(entity); } public T save(T entity) { T saved = saveEntity(entity); setEntity(saved); return saved; } protected void registerTabSkins() { } protected > K registerTabSkin(Tab tab, Function func) { K f = func.apply(tab); if (f != null) { tabSkins.add(f); } return f; } protected void installTabSkins() { for (TabSkin tabSkin : tabSkins) { try { tabSkin.install(); } catch (Exception e) { throw new RuntimeException(tabSkin + ".install", e); } } } public void saveTabSkins() { for (TabSkin tabSkin : tabSkins) { try { tabSkin.save(); } catch (Exception e) { UITools.showExceptionAndWait("Tab" + tabSkin.getTab().getText() + " 保存失败,请检查", e); } } } public TabSkin getTabSkin(Tab tab) { for (TabSkin tabSkin : tabSkins) { if (tabSkin.getTab() == tab) { return tabSkin; } } return null; } public BooleanBinding createTabSkinChangedBindings() { return Bindings.createBooleanBinding(() -> { for (TabSkin tabSkin : tabSkins) { if (tabSkin.changeProperty().get()) { return true; } } return false; }, tabSkins.stream().map(TabSkin::changeProperty).toArray(BooleanProperty[]::new)); } @SuppressWarnings("unchecked") public C getTabSkin(Class skinClass) { for (TabSkin tabSkin : tabSkins) { if (tabSkin.getClass().isAssignableFrom(skinClass)) { return (C) tabSkin; } } return null; } public void onHidden(WindowEvent windowEvent) { if (viewModel != null) { try { viewModel.unBindListener(); } catch (InvocationTargetException | IllegalAccessException e) { throw new RuntimeException(e); } } uninstallTabSkins(); super.onHidden(windowEvent); } protected void uninstallTabSkins() { tabSkins.forEach(TabSkin::dispose); } /** * 刷新 * * @param button 按钮 */ public void refreshByButton(Button button) { CompletableFuture.runAsync(() -> { button.setDisable(true); refresh().whenComplete((v, ex) -> { button.setDisable(false); if (ex != null) { setStatus(ex.getMessage()); } }); }); } public CompletableFuture refresh() { CompletableFuture future = new CompletableFuture<>(); ViewModelService service = getViewModelService(); if (service instanceof QueryService queryService) { loadedFuture = queryService.asyncFindById(viewModel.getId().get()); loadedFuture.whenComplete((entity, ex) -> { if (ex != null) { future.completeExceptionally(ex); return; } BaseViewModel.updateInFxApplicationThread(entity, viewModel); }); } else { T entity = service.findById(viewModel.getId().get()); setEntity(entity); } List list = tabSkins.stream() .filter(v -> v instanceof RefreshableSkin) .map(v -> ((RefreshableSkin) v)).toList(); if (list.isEmpty()) { future.complete(null); return future; } return CompletableFuture.allOf(list .stream() .map(RefreshableSkin::refresh) .filter(Objects::nonNull) .toArray(CompletableFuture[]::new)) .whenComplete((v, ex) -> { if (ex != null) { future.completeExceptionally(ex); } else { future.complete(null); } }); } public abstract ViewModelService getViewModelService(); }