From 1ce98588938745bdf116051645895b5ddc97d822 Mon Sep 17 00:00:00 2001 From: Burning_TNT <88144530+burningtnt@users.noreply.github.com> Date: Tue, 15 Oct 2024 04:06:40 +0800 Subject: [PATCH] =?UTF-8?q?Support=20#2992:=20=E6=A3=80=E6=9F=A5=E6=A8=A1?= =?UTF-8?q?=E7=BB=84=E6=9B=B4=E6=96=B0=E7=95=8C=E9=9D=A2=E5=8A=A0=E5=85=A5?= =?UTF-8?q?=E5=85=A8=E9=80=89/=E5=8F=96=E6=B6=88=E5=85=A8=E9=80=89?= =?UTF-8?q?=E5=A4=8D=E9=80=89=E6=A1=86=20(#3032)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support #2992 --------- Co-authored-by: Glavo --- .../java/org/jackhuang/hmcl/ui/FXUtils.java | 63 +++++++++++++++++-- .../hmcl/ui/versions/ModUpdatesPage.java | 6 +- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index df712fe24..41e5d1cd6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -23,11 +23,9 @@ import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.WeakInvalidationListener; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.Property; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.beans.value.WeakChangeListener; -import javafx.beans.value.WritableValue; +import javafx.beans.value.*; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; @@ -657,6 +655,61 @@ public final class FXUtils { comboBox.getSelectionModel().selectedIndexProperty().removeListener(listener); } + public static void bindAllEnabled(BooleanProperty allEnabled, BooleanProperty... children) { + int itemCount = children.length; + int childSelectedCount = 0; + for (BooleanProperty child : children) { + if (child.get()) + childSelectedCount++; + } + + allEnabled.set(childSelectedCount == itemCount); + + class Listener implements InvalidationListener { + private int childSelectedCount; + private boolean updating = false; + + public Listener(int childSelectedCount) { + this.childSelectedCount = childSelectedCount; + } + + @Override + public void invalidated(Observable observable) { + if (updating) + return; + + updating = true; + try { + boolean value = ((BooleanProperty) observable).get(); + + if (observable == allEnabled) { + for (BooleanProperty child : children) { + child.setValue(value); + } + childSelectedCount = value ? itemCount : 0; + } else { + if (value) + childSelectedCount++; + else + childSelectedCount--; + + allEnabled.set(childSelectedCount == itemCount); + } + } finally { + updating = false; + } + } + } + + InvalidationListener listener = new Listener(childSelectedCount); + + WeakInvalidationListener weakListener = new WeakInvalidationListener(listener); + allEnabled.addListener(listener); + for (BooleanProperty child : children) { + child.addListener(weakListener); + } + } + public static void setIcon(Stage stage) { String icon; if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { @@ -925,7 +978,7 @@ public final class FXUtils { Element r = doc.getDocumentElement(); NodeList children = r.getChildNodes(); - List texts = new ArrayList<>(); + List texts = new ArrayList<>(); for (int i = 0; i < children.getLength(); i++) { org.w3c.dom.Node node = children.item(i); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java index 0d080f731..791ba21c4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModUpdatesPage.java @@ -24,6 +24,7 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.Insets; import javafx.geometry.Pos; +import javafx.scene.control.CheckBox; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.CheckBoxTableCell; @@ -73,6 +74,8 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage { getStyleClass().add("gray-background"); TableColumn enabledColumn = new TableColumn<>(); + CheckBox allEnabledBox = new CheckBox(); + enabledColumn.setGraphic(allEnabledBox); enabledColumn.setCellFactory(CheckBoxTableCell.forTableColumn(enabledColumn)); setupCellValueFactory(enabledColumn, ModUpdateObject::enabledProperty); enabledColumn.setEditable(true); @@ -95,6 +98,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage { setupCellValueFactory(sourceColumn, ModUpdateObject::sourceProperty); objects = FXCollections.observableList(updates.stream().map(ModUpdateObject::new).collect(Collectors.toList())); + FXUtils.bindAllEnabled(allEnabledBox.selectedProperty(), objects.stream().map(o -> o.enabled).toArray(BooleanProperty[]::new)); TableView table = new TableView<>(objects); table.setEditable(true); @@ -170,7 +174,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage { csvTable.write(Files.newOutputStream(path)); FXUtils.showFileInExplorer(path); - }).whenComplete(Schedulers.javafx() ,exception -> { + }).whenComplete(Schedulers.javafx(), exception -> { if (exception == null) { Controllers.dialog(path.toString(), i18n("message.success")); } else {