From 1a6dffab74d6cd1a4ce44e3f38f4488079a102ef Mon Sep 17 00:00:00 2001 From: Glavo Date: Sun, 5 Feb 2023 17:09:35 +0800 Subject: [PATCH] fix #2008: Replace JFXTreeTableView with TableView close #2068 --- .../construct/JFXCheckBoxTreeTableCell.java | 135 ------------------ .../hmcl/ui/versions/ModListPage.java | 13 +- .../hmcl/ui/versions/ModUpdatesPage.java | 82 ++++------- .../resources/assets/lang/I18N_zh.properties | 2 +- .../assets/lang/I18N_zh_CN.properties | 2 +- 5 files changed, 37 insertions(+), 197 deletions(-) delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java deleted file mode 100644 index 86024a590..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/JFXCheckBoxTreeTableCell.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2019 huangyuhui and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.jackhuang.hmcl.ui.construct; - -import com.jfoenix.controls.JFXCheckBox; -import javafx.beans.binding.Bindings; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ObservableValue; -import javafx.geometry.Pos; -import javafx.scene.control.CheckBox; -import javafx.scene.control.TreeTableCell; -import javafx.util.Callback; -import javafx.util.StringConverter; - -public class JFXCheckBoxTreeTableCell extends TreeTableCell { - - private final CheckBox checkBox; - private boolean showLabel; - private ObservableValue booleanProperty; - - public JFXCheckBoxTreeTableCell() { - this(null, null); - } - - public JFXCheckBoxTreeTableCell( - final Callback> getSelectedProperty) { - this(getSelectedProperty, null); - } - - public JFXCheckBoxTreeTableCell( - final Callback> getSelectedProperty, - final StringConverter converter) { - this.getStyleClass().add("check-box-tree-table-cell"); - this.checkBox = new JFXCheckBox(); - setGraphic(null); - setSelectedStateCallback(getSelectedProperty); - setConverter(converter); - } - - private ObjectProperty> converter = new SimpleObjectProperty>(this, "converter") { - protected void invalidated() { - updateShowLabel(); - } - }; - - public final ObjectProperty> converterProperty() { - return converter; - } - - public final void setConverter(StringConverter value) { - converterProperty().set(value); - } - - public final StringConverter getConverter() { - return converterProperty().get(); - } - - private ObjectProperty>> - selectedStateCallback = - new SimpleObjectProperty>>( - this, "selectedStateCallback"); - - public final ObjectProperty>> selectedStateCallbackProperty() { - return selectedStateCallback; - } - - public final void setSelectedStateCallback(Callback> value) { - selectedStateCallbackProperty().set(value); - } - - public final Callback> getSelectedStateCallback() { - return selectedStateCallbackProperty().get(); - } - - @SuppressWarnings("unchecked") - @Override - public void updateItem(T item, boolean empty) { - super.updateItem(item, empty); - - if (empty) { - setText(null); - setGraphic(null); - } else { - StringConverter c = getConverter(); - - if (showLabel) { - setText(c.toString(item)); - } - setGraphic(checkBox); - - if (booleanProperty instanceof BooleanProperty) { - checkBox.selectedProperty().unbindBidirectional((BooleanProperty) booleanProperty); - } - ObservableValue obsValue = getSelectedProperty(); - if (obsValue instanceof BooleanProperty) { - booleanProperty = (ObservableValue) obsValue; - checkBox.selectedProperty().bindBidirectional((BooleanProperty) booleanProperty); - } - - checkBox.disableProperty().bind(Bindings.not( - getTreeTableView().editableProperty().and( - getTableColumn().editableProperty()).and( - editableProperty()) - )); - } - } - - private void updateShowLabel() { - this.showLabel = converter != null; - this.checkBox.setAlignment(showLabel ? Pos.CENTER_LEFT : Pos.CENTER); - } - - private ObservableValue getSelectedProperty() { - return getSelectedStateCallback() != null ? - getSelectedStateCallback().call(getIndex()) : - getTableColumn().getCellObservableValue(getIndex()); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index 164a5e2ca..e72eb2c43 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -179,7 +179,7 @@ public final class ModListPage extends ListPageBase Controllers.taskDialog(Task .composeAsync(() -> { Optional gameVersion = profile.getRepository().getGameVersion(versionId); if (gameVersion.isPresent()) { @@ -193,11 +193,20 @@ public final class ModListPage extends ListPageBase objects; @SuppressWarnings("unchecked") - public ModUpdatesPage(ModManager modManager, List updates, Boolean isModpack) { + public ModUpdatesPage(ModManager modManager, List updates) { this.modManager = modManager; getStyleClass().add("gray-background"); - JFXTreeTableColumn enabledColumn = new JFXTreeTableColumn<>(); - enabledColumn.setCellFactory(column -> new JFXCheckBoxTreeTableCell<>()); + TableColumn enabledColumn = new TableColumn<>(); + enabledColumn.setCellFactory(CheckBoxTableCell.forTableColumn(enabledColumn)); setupCellValueFactory(enabledColumn, ModUpdateObject::enabledProperty); enabledColumn.setEditable(true); enabledColumn.setMaxWidth(40); enabledColumn.setMinWidth(40); - JFXTreeTableColumn fileNameColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.file")); + TableColumn fileNameColumn = new TableColumn<>(i18n("mods.check_updates.file")); + fileNameColumn.setPrefWidth(200); setupCellValueFactory(fileNameColumn, ModUpdateObject::fileNameProperty); - JFXTreeTableColumn currentVersionColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.current_version")); + TableColumn currentVersionColumn = new TableColumn<>(i18n("mods.check_updates.current_version")); + currentVersionColumn.setPrefWidth(200); setupCellValueFactory(currentVersionColumn, ModUpdateObject::currentVersionProperty); - JFXTreeTableColumn targetVersionColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.target_version")); + TableColumn targetVersionColumn = new TableColumn<>(i18n("mods.check_updates.target_version")); + targetVersionColumn.setPrefWidth(200); setupCellValueFactory(targetVersionColumn, ModUpdateObject::targetVersionProperty); - JFXTreeTableColumn sourceColumn = new JFXTreeTableColumn<>(i18n("mods.check_updates.source")); + TableColumn sourceColumn = new TableColumn<>(i18n("mods.check_updates.source")); setupCellValueFactory(sourceColumn, ModUpdateObject::sourceProperty); objects = FXCollections.observableList(updates.stream().map(ModUpdateObject::new).collect(Collectors.toList())); - RecursiveTreeItem root = new RecursiveTreeItem<>( - objects, - RecursiveTreeObject::getChildren); - - JFXTreeTableView table = new JFXTreeTableView<>(root); - table.setShowRoot(false); + TableView table = new TableView<>(objects); table.setEditable(true); table.getColumns().setAll(enabledColumn, fileNameColumn, currentVersionColumn, targetVersionColumn, sourceColumn); @@ -111,9 +110,6 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage { JFXButton nextButton = new JFXButton(i18n("mods.check_updates.update")); nextButton.getStyleClass().add("jfx-button-raised"); nextButton.setButtonType(JFXButton.ButtonType.RAISED); - nextButton.setOnAction(e -> { - if (isModpack) updateModpackModWarningDialog(); - }); JFXButton cancelButton = new JFXButton(i18n("button.cancel")); cancelButton.getStyleClass().add("jfx-button-raised"); @@ -125,38 +121,8 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage { setBottom(actions); } - private void setupCellValueFactory(JFXTreeTableColumn column, Function> mapper) { - column.setCellValueFactory(param -> { - if (column.validateValue(param)) - return mapper.apply(param.getValue().getValue()); - else - return column.getComputedValue(param); - }); - } - - private void updateModpackModWarningDialog() { - JFXDialogLayout warningPane = new JFXDialogLayout(); - warningPane.setHeading(new Label(i18n("message.warning"), SVG.alert(new ObjectBinding() { - @Override - protected Paint computeValue() { - return Color.ORANGERED; - } - }, -1, -1))); - warningPane.setBody(new Label(i18n("mods.update_modpack_mod.warning"))); - JFXButton yesButton = new JFXButton(i18n("button.yes")); - yesButton.getStyleClass().add("dialog-accept"); - yesButton.setOnAction(event -> { - warningPane.fireEvent(new DialogCloseEvent()); - updateMods(); - }); - JFXButton noButton = new JFXButton(i18n("button.cancel")); - noButton.getStyleClass().add("dialog-cancel"); - noButton.setOnAction(event -> { - // Do nothing. - warningPane.fireEvent(new DialogCloseEvent()); - }); - warningPane.setActions(yesButton, noButton); - Controllers.dialog(warningPane); + private void setupCellValueFactory(TableColumn column, Function> mapper) { + column.setCellValueFactory(param -> mapper.apply(param.getValue())); } private void updateMods() { @@ -189,7 +155,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage { return state; } - public static class ModUpdateCell extends MDListCell { + public static final class ModUpdateCell extends MDListCell { TwoLineListItem content = new TwoLineListItem(); public ModUpdateCell(JFXListView listView, MutableObject lastCell) { @@ -214,7 +180,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage { } } - private static class ModUpdateObject extends RecursiveTreeObject { + private static final class ModUpdateObject { final LocalModFile.ModUpdate data; final BooleanProperty enabled = new SimpleBooleanProperty(); final StringProperty fileName = new SimpleStringProperty(); diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 373f0547c..8bfee4a33 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -705,7 +705,7 @@ mods.name=名稱 mods.not_modded=你需要先在自動安裝頁面安裝 Fabric、Forge 或 LiteLoader 才能進行模組管理。 mods.restore=回退 mods.url=官方頁面 -mods.update_modpack_mod.warning=更新整合包中的Mod可能導致整合包損壞,使整合包無法正常啟動。該操作不可逆,確定要更新嗎? +mods.update_modpack_mod.warning=更新模組包中的 Mod 可能導致綜合包損壞,使模組包無法正常啟動。該操作不可逆,確定要更新嗎? multiplayer=多人聯機 multiplayer.agreement.prompt=多人聯機功能由 速聚 提供。使用前,你需要先同意多人聯機服務提供方 速聚 的用戶協議與免責聲明。\n你需要了解,HMCL 僅為 速聚 提供多人聯機服務入口,使用中遇到的任何問題由 速聚 負責處理。您在使用多人聯機服務過程中所遇到的任何問題與糾紛(包括其付費業務)均與 HMCL 無關,應與 速聚 協商解決。 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index cc1d50227..3cafcc700 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -707,7 +707,7 @@ mods.name=名称 mods.not_modded=你需要先在自动安装页面安装 Fabric、Forge 或 LiteLoader 才能进行模组管理! mods.restore=回退 mods.url=官方页面 -mods.update_modpack_mod.warning=更新整合包中的Mod可能导致整合包损坏,使整合包无法正常启动。该操作不可逆,确定要更新吗? +mods.update_modpack_mod.warning=更新整合包中的 Mod 可能导致整合包损坏,使整合包无法正常启动。该操作不可逆,确定要更新吗? multiplayer=多人联机 multiplayer.agreement.prompt=多人联机功能由 速聚 提供。使用前,你需要先同意多人联机服务提供方 速聚 的用户协议与免责声明。\n你需要了解,HMCL 仅为 速聚 提供多人联机服务入口,使用中遇到的任何问题由 速聚 负责处理。\n您在使用多人联机服务过程中所遇到的任何问题与纠纷(包括其付费业务)均与 HMCL 无关,请与 速聚 协商解决。