Explorar o código

Refactor CheckListCell to display ellipsis rather than allow horizontal scrolling

Armin Schrenk %!s(int64=3) %!d(string=hai) anos
pai
achega
3f76a04b38

+ 0 - 48
src/main/java/org/cryptomator/ui/health/CheckListCell.java

@@ -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<Check> {
-
-	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();
-		}
-	}
-
-}

+ 70 - 0
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> check;
+	private final Binding<String> checkName;
+	private final Binding<Boolean> checkRunnable;
+	private final List<Subscription> 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<Check> checkProperty() {
+		return check;
+	}
+
+	public Check getCheck() {
+		return check.get();
+	}
+
+	public void setCheck(Check c) {
+		check.set(c);
+	}
+
+	public Binding<String> checkNameProperty() {
+		return checkName;
+	}
+
+	public String getCheckName() {
+		return checkName.getValue();
+	}
+
+	public Binding<Boolean> checkRunnableProperty() {
+		return checkRunnable;
+	}
+
+	public boolean isCheckRunnable() {
+		return checkRunnable.getValue();
+	}
+}

+ 58 - 0
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<ListView<Check>, ListCell<Check>> {
+
+	private final FxmlLoaderFactory fxmlLoaders;
+
+	@Inject
+	CheckListCellFactory(@HealthCheckWindow FxmlLoaderFactory fxmlLoaders) {
+		this.fxmlLoaders = fxmlLoaders;
+	}
+
+	@Override
+	public ListCell<Check> call(ListView<Check> 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<Check> {
+
+		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);
+			}
+		}
+	}
+}

+ 4 - 2
src/main/java/org/cryptomator/ui/health/CheckListController.java

@@ -40,15 +40,17 @@ public class CheckListController implements FxController {
 	private final Lazy<ErrorComponent.Builder> errorComponentBuilder;
 	private final IntegerBinding chosenTaskCount;
 	private final BooleanBinding anyCheckSelected;
+	private final CheckListCellFactory listCellFactory;
 
 	/* FXML */
 	public ListView<Check> checksListView;
 
 	@Inject
-	public CheckListController(@HealthCheckWindow Stage window, List<Check> checks, CheckExecutor checkExecutor, ReportWriter reportWriteTask, ObjectProperty<Check> selectedCheck, Lazy<ErrorComponent.Builder> errorComponentBuilder) {
+	public CheckListController(@HealthCheckWindow Stage window, List<Check> checks, CheckExecutor checkExecutor, ReportWriter reportWriteTask, ObjectProperty<Check> selectedCheck, Lazy<ErrorComponent.Builder> 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());
 	}
 

+ 4 - 0
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);
 }

+ 26 - 0
src/main/resources/fxml/health_check_listcell.fxml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+<?import org.cryptomator.ui.health.CheckStateIconView?>
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.StackPane?>
+<?import javafx.scene.control.CheckBox?>
+<?import javafx.scene.control.Label?>
+
+<HBox xmlns="http://javafx.com/javafx"
+	  xmlns:fx="http://javafx.com/fxml"
+	  fx:controller="org.cryptomator.ui.health.CheckListCellController"
+	  prefHeight="30.0" prefWidth="150.0"
+	  alignment="CENTER_LEFT" spacing="6">
+	<padding>
+		<Insets topRightBottomLeft="6"/>
+	</padding>
+
+	<StackPane minWidth="20" minHeight="20" alignment="CENTER">
+		<CheckBox fx:id="forRunSelectedCheckBox" visible="${controller.checkRunnable}" />
+		<CheckStateIconView check="${controller.check}" glyphSize="20" visible="${!controller.checkRunnable}"/>
+	</StackPane>
+	<Label text="${controller.checkName}"/>
+
+</HBox>