mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-17 10:11:27 +00:00
Replace result table by result list
This commit is contained in:
@@ -2,21 +2,17 @@ package org.cryptomator.ui.health;
|
||||
|
||||
import com.tobiasdiez.easybind.EasyBind;
|
||||
import com.tobiasdiez.easybind.optional.OptionalBinding;
|
||||
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Binding;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.concurrent.Worker;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.ListView;
|
||||
|
||||
public class CheckDetailController implements FxController {
|
||||
|
||||
@@ -24,19 +20,18 @@ public class CheckDetailController implements FxController {
|
||||
private final OptionalBinding<Worker.State> taskState;
|
||||
private final Binding<String> taskName;
|
||||
private final Binding<String> taskDescription;
|
||||
private final ResultListCellFactory resultListCellFactory;
|
||||
private final BooleanBinding producingResults;
|
||||
|
||||
public TableView<DiagnosticResultAction> resultsTableView;
|
||||
public TableColumn<DiagnosticResultAction, String> resultDescriptionColumn;
|
||||
public TableColumn<DiagnosticResultAction, DiagnosticResult.Severity> resultSeverityColumn;
|
||||
public TableColumn<DiagnosticResultAction, Runnable> resultActionColumn;
|
||||
public ListView<DiagnosticResultAction> resultsListView;
|
||||
|
||||
@Inject
|
||||
public CheckDetailController(ObjectProperty<HealthCheckTask> selectedTask) {
|
||||
public CheckDetailController(ObjectProperty<HealthCheckTask> selectedTask, ResultListCellFactory resultListCellFactory) {
|
||||
this.results = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::results).orElse(FXCollections.emptyObservableList());
|
||||
this.taskState = EasyBind.wrapNullable(selectedTask).mapObservable(HealthCheckTask::stateProperty);
|
||||
this.taskName = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::getTitle).orElse("");
|
||||
this.taskDescription = EasyBind.wrapNullable(selectedTask).map(task -> task.getCheck().toString()).orElse("");
|
||||
this.resultListCellFactory = resultListCellFactory;
|
||||
this.producingResults = taskState.filter(this::producesResults).isPresent();
|
||||
}
|
||||
|
||||
@@ -49,12 +44,8 @@ public class CheckDetailController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
resultsTableView.itemsProperty().bind(results);
|
||||
resultDescriptionColumn.setCellValueFactory(cellFeatures -> new SimpleStringProperty(cellFeatures.getValue().getDescription()));
|
||||
resultSeverityColumn.setCellValueFactory(cellFeatures -> new SimpleObjectProperty<>(cellFeatures.getValue().getSeverity()));
|
||||
resultSeverityColumn.setCellFactory(column -> new ResultSeverityTableCell());
|
||||
resultActionColumn.setCellValueFactory(cellFeatures -> new SimpleObjectProperty<>(cellFeatures.getValue()));
|
||||
resultActionColumn.setCellFactory(column -> new ResultActionTableCell());
|
||||
resultsListView.itemsProperty().bind(results);
|
||||
resultsListView.setCellFactory(resultListCellFactory);
|
||||
}
|
||||
/* Getter/Setter */
|
||||
|
||||
|
||||
@@ -134,5 +134,9 @@ abstract class HealthCheckModule {
|
||||
@FxControllerKey(CheckDetailController.class)
|
||||
abstract FxController bindCheckDetailController(CheckDetailController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(ResultListCellController.class)
|
||||
abstract FxController bindResultListCellController(ResultListCellController controller);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.cryptomator.ui.health;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TableCell;
|
||||
|
||||
class ResultActionTableCell extends TableCell<DiagnosticResultAction, Runnable> {
|
||||
|
||||
private Button button;
|
||||
|
||||
ResultActionTableCell() {
|
||||
button = new Button();
|
||||
setGraphic(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(Runnable item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty || item == null) {
|
||||
setText(null);
|
||||
setGraphic(null);
|
||||
} else {
|
||||
setGraphic(button);
|
||||
button.setOnAction(event -> item.run());
|
||||
button.setText("FIXME"); //FIXME
|
||||
button.setAlignment(Pos.CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.cryptomator.ui.health;
|
||||
|
||||
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
|
||||
import org.cryptomator.cryptofs.health.api.HealthCheck;
|
||||
|
||||
import javafx.scene.control.ListCell;
|
||||
|
||||
class ResultListCell extends ListCell<DiagnosticResult> {
|
||||
|
||||
@Override
|
||||
protected void updateItem(DiagnosticResult item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null) {
|
||||
setText(item.toString());
|
||||
} else {
|
||||
setText(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.cryptomator.ui.health;
|
||||
|
||||
import com.tobiasdiez.easybind.EasyBind;
|
||||
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.controls.FontAwesome5Icon;
|
||||
import org.cryptomator.ui.controls.FontAwesome5IconView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Binding;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.fxml.FXML;
|
||||
|
||||
public class ResultListCellController implements FxController {
|
||||
|
||||
private final ObjectProperty<DiagnosticResultAction> result;
|
||||
private final Binding<Boolean> fixButtonVisible;
|
||||
private final Binding<String> description;
|
||||
|
||||
@FXML
|
||||
public FontAwesome5IconView iconView;
|
||||
|
||||
@Inject
|
||||
public ResultListCellController() {
|
||||
this.result = new SimpleObjectProperty<>(null);
|
||||
this.fixButtonVisible = EasyBind.wrapNullable(result) //
|
||||
.map(val -> val.getSeverity() == DiagnosticResult.Severity.WARN).orElse(true); //
|
||||
this.description = EasyBind.wrapNullable(result).map(DiagnosticResultAction::getDescription).orElse("");
|
||||
result.addListener(this::getGlyphForSeverity);
|
||||
}
|
||||
|
||||
private void getGlyphForSeverity(ObservableValue<? extends DiagnosticResultAction> observable, DiagnosticResultAction oldVal, DiagnosticResultAction newVal) {
|
||||
iconView.getStyleClass().clear();
|
||||
switch (newVal.getSeverity()) {
|
||||
case INFO -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.INFO_CIRCLE);
|
||||
iconView.getStyleClass().add("glyph-icon-muted");
|
||||
}
|
||||
case GOOD -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.CHECK);
|
||||
iconView.getStyleClass().add("glyph-icon-primary");
|
||||
}
|
||||
case WARN -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.EXCLAMATION_TRIANGLE);
|
||||
iconView.getStyleClass().add("glyph-icon-orange");
|
||||
}
|
||||
case CRITICAL -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.TIMES);
|
||||
iconView.getStyleClass().add("glyph-icon-red");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void runResultAction() {
|
||||
final var realResult = result.get();
|
||||
if (realResult != null) {
|
||||
realResult.run(); //TODO: this hogs currently the JAVAFX thread
|
||||
}
|
||||
}
|
||||
|
||||
/* Getter & Setter */
|
||||
|
||||
public DiagnosticResultAction getResult() {
|
||||
return result.get();
|
||||
}
|
||||
|
||||
public void setResult(DiagnosticResultAction result) {
|
||||
this.result.set(result);
|
||||
}
|
||||
|
||||
public ObjectProperty<DiagnosticResultAction> resultProperty() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isFixButtonVisibile() {
|
||||
return fixButtonVisible.getValue();
|
||||
}
|
||||
|
||||
public Binding<Boolean> fixButtonVisibleProperty() {
|
||||
return fixButtonVisible;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description.getValue();
|
||||
}
|
||||
|
||||
public Binding<String> descriptionProperty() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
public class ResultListCellFactory implements Callback<ListView<DiagnosticResultAction>, ListCell<DiagnosticResultAction>> {
|
||||
|
||||
private final FxmlLoaderFactory fxmlLoaders;
|
||||
|
||||
@Inject
|
||||
ResultListCellFactory(@HealthCheckWindow FxmlLoaderFactory fxmlLoaders) {
|
||||
this.fxmlLoaders = fxmlLoaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListCell<DiagnosticResultAction> call(ListView<DiagnosticResultAction> param) {
|
||||
try {
|
||||
FXMLLoader fxmlLoader = fxmlLoaders.load("/fxml/health_result_listcell.fxml");
|
||||
return new ResultListCellFactory.Cell(fxmlLoader.getRoot(), fxmlLoader.getController());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to load /fxml/health_result_listcell.fxml.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Cell extends ListCell<DiagnosticResultAction> {
|
||||
|
||||
private final Parent node;
|
||||
private final ResultListCellController controller;
|
||||
|
||||
public Cell(Parent node, ResultListCellController controller) {
|
||||
this.node = node;
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(DiagnosticResultAction item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item == null || empty) {
|
||||
setText(null);
|
||||
setGraphic(null);
|
||||
} else {
|
||||
controller.setResult(item);
|
||||
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
|
||||
setGraphic(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.cryptomator.ui.health;
|
||||
|
||||
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
|
||||
import org.cryptomator.ui.controls.FontAwesome5Icon;
|
||||
import org.cryptomator.ui.controls.FontAwesome5IconView;
|
||||
|
||||
import javafx.scene.control.TableCell;
|
||||
|
||||
public class ResultSeverityTableCell extends TableCell<DiagnosticResultAction, DiagnosticResult.Severity> {
|
||||
|
||||
private FontAwesome5IconView iconView;
|
||||
|
||||
ResultSeverityTableCell() {
|
||||
iconView = new FontAwesome5IconView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(DiagnosticResult.Severity item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
iconView.getStyleClass().clear();
|
||||
if (empty || item == null) {
|
||||
setText(null);
|
||||
setGraphic(null);
|
||||
} else {
|
||||
switch (item) {
|
||||
case INFO -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.INFO_CIRCLE);
|
||||
iconView.getStyleClass().add("glyph-icon-muted");
|
||||
}
|
||||
case GOOD -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.CHECK);
|
||||
iconView.getStyleClass().add("glyph-icon-primary");
|
||||
}
|
||||
case WARN -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.EXCLAMATION_TRIANGLE);
|
||||
iconView.getStyleClass().add("glyph-icon-orange");
|
||||
}
|
||||
case CRITICAL -> {
|
||||
iconView.setGlyph(FontAwesome5Icon.TIMES);
|
||||
iconView.getStyleClass().add("glyph-icon-red");
|
||||
}
|
||||
}
|
||||
setGraphic(iconView);
|
||||
setText(item.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TableColumn?>
|
||||
<?import javafx.scene.control.TableView?>
|
||||
<?import javafx.scene.control.ListView?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.health.CheckDetailController"
|
||||
spacing="6">
|
||||
<Label fx:id="checkTitle" styleClass="label-large" text="${controller.taskName}"/>
|
||||
<Label fx:id="checkTitle" styleClass="label-large" text="${controller.taskName}"/> <!-- use formatted label and let the text be "Results of [TASKNAME] -->
|
||||
<Text fx:id="checkDescription" styleClass="label" text="${controller.taskDescription}"/>
|
||||
<TableView fx:id="resultsTableView" visible="${controller.producingResults}" managed="${controller.producingResults}" VBox.vgrow="ALWAYS">
|
||||
<columns>
|
||||
<TableColumn fx:id="resultDescriptionColumn" text="Info" editable="false" maxWidth="Infinity" />
|
||||
<TableColumn fx:id="resultSeverityColumn" text="Severity" editable="false" />
|
||||
<TableColumn fx:id="resultActionColumn" text="Action" editable="false"/>
|
||||
</columns>
|
||||
</TableView>
|
||||
<ListView fx:id="resultsListView"/>
|
||||
</VBox>
|
||||
26
main/ui/src/main/resources/fxml/health_result_listcell.fxml
Normal file
26
main/ui/src/main/resources/fxml/health_result_listcell.fxml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<HBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.health.ResultListCellController"
|
||||
prefHeight="25"
|
||||
prefWidth="200"
|
||||
spacing="6"
|
||||
alignment="CENTER_LEFT">
|
||||
<!-- Remark Check the containing list view for a fixed cell size before editing height properties -->
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="6"/>
|
||||
</padding>
|
||||
<children>
|
||||
<FontAwesome5IconView fx:id="iconView" HBox.hgrow="NEVER" glyphSize="16"/>
|
||||
<Label text="${controller.description}" wrapText="true"/>
|
||||
<Region HBox.hgrow="ALWAYS"/>
|
||||
<Button text="YOLO" onAction="#runResultAction" alignment="CENTER_RIGHT" visible="${controller.fixButtonVisibile}"/>
|
||||
</children>
|
||||
</HBox>
|
||||
Reference in New Issue
Block a user