diff --git a/src/main/java/org/cryptomator/ui/health/CheckListCell.java b/src/main/java/org/cryptomator/ui/health/CheckListCell.java deleted file mode 100644 index a1c05efb8..000000000 --- a/src/main/java/org/cryptomator/ui/health/CheckListCell.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cryptomator.ui.health; - -import javafx.beans.binding.Bindings; -import javafx.geometry.Insets; -import javafx.geometry.Pos; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ContentDisplay; -import javafx.scene.control.ListCell; -import javafx.scene.layout.StackPane; - -class CheckListCell extends ListCell { - - private final CheckStateIconView stateIcon = new CheckStateIconView(); - private CheckBox checkBox = new CheckBox(); - private final StackPane graphicContainer = new StackPane(stateIcon, checkBox); - - CheckListCell() { - setPadding(new Insets(6)); - setAlignment(Pos.CENTER_LEFT); - setContentDisplay(ContentDisplay.LEFT); - getStyleClass().add("label"); - graphicContainer.minWidth(20); - graphicContainer.maxWidth(20); - graphicContainer.setAlignment(Pos.CENTER); - } - - @Override - protected void updateItem(Check item, boolean empty) { - super.updateItem(item, empty); - if (item != null) { - setText(item.getLocalizedName()); - setGraphic(graphicContainer); - stateIcon.setCheck(item); - checkBox.visibleProperty().bind(Bindings.createBooleanBinding(() -> item.getState() == Check.CheckState.RUNNABLE, item.stateProperty())); - stateIcon.visibleProperty().bind(Bindings.createBooleanBinding(() -> item.getState() != Check.CheckState.RUNNABLE, item.stateProperty())); - checkBox.selectedProperty().bindBidirectional(item.chosenForExecutionProperty()); - } else { - graphicProperty(); - checkBox.visibleProperty().unbind(); - stateIcon.visibleProperty().unbind(); - stateIcon.setCheck(null); - setGraphic(null); - setText(null); - checkBox.selectedProperty().unbind(); - } - } - -} diff --git a/src/main/java/org/cryptomator/ui/health/CheckListCellController.java b/src/main/java/org/cryptomator/ui/health/CheckListCellController.java new file mode 100644 index 000000000..320fe3b36 --- /dev/null +++ b/src/main/java/org/cryptomator/ui/health/CheckListCellController.java @@ -0,0 +1,70 @@ +package org.cryptomator.ui.health; + +import com.tobiasdiez.easybind.EasyBind; +import com.tobiasdiez.easybind.Subscription; +import org.cryptomator.ui.common.FxController; + +import javax.inject.Inject; +import javafx.beans.binding.Binding; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.control.CheckBox; +import java.util.ArrayList; +import java.util.List; + +public class CheckListCellController implements FxController { + + + private final ObjectProperty check; + private final Binding checkName; + private final Binding checkRunnable; + private final List subscriptions; + + /* FXML */ + public CheckBox forRunSelectedCheckBox; + + @Inject + public CheckListCellController() { + check = new SimpleObjectProperty<>(); + checkRunnable = EasyBind.wrapNullable(check).mapObservable(Check::stateProperty).map(Check.CheckState.RUNNABLE::equals).orElse(false); + checkName = EasyBind.wrapNullable(check).map(Check::getLocalizedName).orElse(""); + subscriptions = new ArrayList<>(); + } + + public void initialize() { + subscriptions.add(EasyBind.subscribe(check, c -> { + forRunSelectedCheckBox.selectedProperty().unbind(); + if (c != null) { + forRunSelectedCheckBox.selectedProperty().bindBidirectional(c.chosenForExecutionProperty()); + } + })); + } + + public ObjectProperty checkProperty() { + return check; + } + + public Check getCheck() { + return check.get(); + } + + public void setCheck(Check c) { + check.set(c); + } + + public Binding checkNameProperty() { + return checkName; + } + + public String getCheckName() { + return checkName.getValue(); + } + + public Binding checkRunnableProperty() { + return checkRunnable; + } + + public boolean isCheckRunnable() { + return checkRunnable.getValue(); + } +} diff --git a/src/main/java/org/cryptomator/ui/health/CheckListCellFactory.java b/src/main/java/org/cryptomator/ui/health/CheckListCellFactory.java new file mode 100644 index 000000000..d8ccc8d48 --- /dev/null +++ b/src/main/java/org/cryptomator/ui/health/CheckListCellFactory.java @@ -0,0 +1,58 @@ +package org.cryptomator.ui.health; + +import org.cryptomator.ui.common.FxmlLoaderFactory; + +import javax.inject.Inject; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.control.ContentDisplay; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.util.Callback; +import java.io.IOException; +import java.io.UncheckedIOException; + +// unscoped because each cell needs its own controller +public class CheckListCellFactory implements Callback, ListCell> { + + private final FxmlLoaderFactory fxmlLoaders; + + @Inject + CheckListCellFactory(@HealthCheckWindow FxmlLoaderFactory fxmlLoaders) { + this.fxmlLoaders = fxmlLoaders; + } + + @Override + public ListCell call(ListView param) { + try { + FXMLLoader fxmlLoader = fxmlLoaders.load("/fxml/health_check_listcell.fxml"); + return new CheckListCellFactory.Cell(fxmlLoader.getRoot(), fxmlLoader.getController()); + } catch (IOException e) { + throw new UncheckedIOException("Failed to load /fxml/health_check_listcell.fxml.", e); + } + } + + private static class Cell extends ListCell { + + private final Parent node; + private final CheckListCellController controller; + + public Cell(Parent node, CheckListCellController controller) { + this.node = node; + this.controller = controller; + } + + @Override + protected void updateItem(Check item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setText(null); + setGraphic(null); + } else { + controller.setCheck(item); + setContentDisplay(ContentDisplay.GRAPHIC_ONLY); + setGraphic(node); + } + } + } +} diff --git a/src/main/java/org/cryptomator/ui/health/CheckListController.java b/src/main/java/org/cryptomator/ui/health/CheckListController.java index 7e087b8b5..75ecdef52 100644 --- a/src/main/java/org/cryptomator/ui/health/CheckListController.java +++ b/src/main/java/org/cryptomator/ui/health/CheckListController.java @@ -40,15 +40,17 @@ public class CheckListController implements FxController { private final Lazy errorComponentBuilder; private final IntegerBinding chosenTaskCount; private final BooleanBinding anyCheckSelected; + private final CheckListCellFactory listCellFactory; /* FXML */ public ListView checksListView; @Inject - public CheckListController(@HealthCheckWindow Stage window, List checks, CheckExecutor checkExecutor, ReportWriter reportWriteTask, ObjectProperty selectedCheck, Lazy errorComponentBuilder) { + public CheckListController(@HealthCheckWindow Stage window, List checks, CheckExecutor checkExecutor, ReportWriter reportWriteTask, ObjectProperty selectedCheck, Lazy errorComponentBuilder, CheckListCellFactory listCellFactory) { this.window = window; this.checks = FXCollections.observableList(checks, Check::observables); this.checkExecutor = checkExecutor; + this.listCellFactory = listCellFactory; this.chosenChecks = this.checks.filtered(Check::isChosenForExecution); this.reportWriter = reportWriteTask; this.selectedCheck = selectedCheck; @@ -63,7 +65,7 @@ public class CheckListController implements FxController { public void initialize() { checksListView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); checksListView.setItems(checks); - checksListView.setCellFactory(view -> new CheckListCell()); + checksListView.setCellFactory(listCellFactory); selectedCheck.bind(checksListView.getSelectionModel().selectedItemProperty()); } diff --git a/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java b/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java index 0d1c5f174..80a313dc8 100644 --- a/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java +++ b/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java @@ -166,4 +166,8 @@ abstract class HealthCheckModule { @FxControllerKey(ResultListCellController.class) abstract FxController bindResultListCellController(ResultListCellController controller); + @Binds + @IntoMap + @FxControllerKey(CheckListCellController.class) + abstract FxController bindCheckListCellController(CheckListCellController controller); } diff --git a/src/main/resources/fxml/health_check_listcell.fxml b/src/main/resources/fxml/health_check_listcell.fxml new file mode 100644 index 000000000..08155afc8 --- /dev/null +++ b/src/main/resources/fxml/health_check_listcell.fxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + +