Add CheckState icon to check detail view

This commit is contained in:
Armin Schrenk
2021-07-12 10:34:36 +02:00
parent 720478c2f4
commit c0d552da92
4 changed files with 76 additions and 32 deletions

View File

@@ -3,6 +3,7 @@ package org.cryptomator.ui.health;
import com.tobiasdiez.easybind.EasyBind;
import com.tobiasdiez.easybind.EasyObservableList;
import com.tobiasdiez.easybind.Subscription;
import com.tobiasdiez.easybind.optional.ObservableOptionalValue;
import com.tobiasdiez.easybind.optional.OptionalBinding;
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
import org.cryptomator.ui.common.FxController;
@@ -21,6 +22,7 @@ import java.util.stream.Stream;
public class CheckDetailController implements FxController {
private final EasyObservableList<Result> results;
private final ObjectProperty<Check> check;
private final OptionalBinding<Check.CheckState> checkState;
private final Binding<String> checkName;
private final Binding<Boolean> checkRunning;
@@ -34,6 +36,7 @@ public class CheckDetailController implements FxController {
private final Binding<Number> countOfCritSeverity;
private final ResultListCellFactory resultListCellFactory;
public CheckStateIconView checkStateIconView;
public ListView<Result> resultsListView;
private Subscription resultSubscription;
@@ -41,6 +44,7 @@ public class CheckDetailController implements FxController {
public CheckDetailController(ObjectProperty<Check> selectedTask, ResultListCellFactory resultListCellFactory) {
this.resultListCellFactory = resultListCellFactory;
this.results = EasyBind.wrapList(FXCollections.observableArrayList());
this.check = selectedTask;
this.checkState = EasyBind.wrapNullable(selectedTask).mapObservable(Check::stateProperty);
this.checkName = EasyBind.wrapNullable(selectedTask).map(Check::getLocalizedName).orElse("");
this.checkRunning = checkState.map(Check.CheckState.RUNNING::equals).orElse(false);
@@ -156,4 +160,11 @@ public class CheckDetailController implements FxController {
return checkCancelled;
}
public ObjectProperty<Check> checkProperty() {
return check;
}
public Check getCheck() {
return check.get();
}
}

View File

@@ -1,10 +1,5 @@
package org.cryptomator.ui.health;
import com.tobiasdiez.easybind.EasyBind;
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.cryptomator.ui.controls.FontAwesome5IconView;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@@ -15,7 +10,7 @@ import javafx.scene.layout.StackPane;
class CheckListCell extends ListCell<Check> {
private final FontAwesome5IconView stateIcon = new FontAwesome5IconView();
private final CheckStateIconView stateIcon = new CheckStateIconView();
private CheckBox checkBox = new CheckBox();
private final StackPane graphicContainer = new StackPane(stateIcon, checkBox);
@@ -27,11 +22,6 @@ class CheckListCell extends ListCell<Check> {
graphicContainer.minWidth(20);
graphicContainer.maxWidth(20);
graphicContainer.setAlignment(Pos.CENTER);
EasyBind.includeWhen(stateIcon.getStyleClass(), "glyph-icon-muted", stateIcon.glyphProperty().isEqualTo(FontAwesome5Icon.INFO_CIRCLE));
EasyBind.includeWhen(stateIcon.getStyleClass(), "glyph-icon-primary", stateIcon.glyphProperty().isEqualTo(FontAwesome5Icon.CHECK));
EasyBind.includeWhen(stateIcon.getStyleClass(), "glyph-icon-orange", stateIcon.glyphProperty().isEqualTo(FontAwesome5Icon.EXCLAMATION_TRIANGLE));
EasyBind.includeWhen(stateIcon.getStyleClass(), "glyph-icon-red", stateIcon.glyphProperty().isEqualTo(FontAwesome5Icon.TIMES));
}
@Override
@@ -40,36 +30,19 @@ class CheckListCell extends ListCell<Check> {
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()));
stateIcon.glyphProperty().bind(Bindings.createObjectBinding(() -> glyphForState(item), item.stateProperty(), item.highestResultSeverityProperty()));
checkBox.selectedProperty().bindBidirectional(item.chosenForExecutionProperty());
} else {
graphicProperty();
checkBox.visibleProperty().unbind();
stateIcon.visibleProperty().unbind();
stateIcon.setCheck(null);
setGraphic(null);
setText(null);
checkBox.selectedProperty().unbind();
}
}
private FontAwesome5Icon glyphForState(Check item) {
return switch (item.getState()) {
case RUNNABLE -> null;
case SKIPPED -> FontAwesome5Icon.FAST_FORWARD;
case SCHEDULED -> FontAwesome5Icon.CLOCK;
case RUNNING -> FontAwesome5Icon.SPINNER;
case ERROR -> FontAwesome5Icon.TIMES;
case CANCELLED -> FontAwesome5Icon.BAN;
case SUCCEEDED -> {
if (item.getHighestResultSeverity() == DiagnosticResult.Severity.INFO || item.getHighestResultSeverity() == DiagnosticResult.Severity.GOOD) {
yield FontAwesome5Icon.CHECK;
} else {
yield FontAwesome5Icon.EXCLAMATION_TRIANGLE;
}
}
};
}
}

View File

@@ -0,0 +1,55 @@
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.controls.FontAwesome5Icon;
import org.cryptomator.ui.controls.FontAwesome5IconView;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import java.util.Optional;
public class CheckStateIconView extends FontAwesome5IconView {
private final ObjectProperty<Check> check = new SimpleObjectProperty<>();
private final OptionalBinding<Check.CheckState> state;
private final OptionalBinding<DiagnosticResult.Severity> severity;
public CheckStateIconView() {
super();
this.getStyleClass().remove("glyph-icon");
this.state = EasyBind.wrapNullable(check).mapObservable(Check::stateProperty);
this.severity = EasyBind.wrapNullable(check).mapObservable(Check::highestResultSeverityProperty);
glyphProperty().bind(EasyBind.combine(state, severity, this::glyphForState));
EasyBind.includeWhen(getStyleClass(), "glyph-icon-muted", glyphProperty().isEqualTo(FontAwesome5Icon.INFO_CIRCLE));
EasyBind.includeWhen(getStyleClass(), "glyph-icon-primary", glyphProperty().isEqualTo(FontAwesome5Icon.CHECK));
EasyBind.includeWhen(getStyleClass(), "glyph-icon-orange", glyphProperty().isEqualTo(FontAwesome5Icon.EXCLAMATION_TRIANGLE));
EasyBind.includeWhen(getStyleClass(), "glyph-icon-red", glyphProperty().isEqualTo(FontAwesome5Icon.TIMES));
}
private FontAwesome5Icon glyphForState(Optional<Check.CheckState> state, Optional<DiagnosticResult.Severity> severity) {
return state.map(s -> switch (s) {
case RUNNABLE -> null;
case SKIPPED -> FontAwesome5Icon.FAST_FORWARD;
case SCHEDULED -> FontAwesome5Icon.CLOCK;
case RUNNING -> FontAwesome5Icon.SPINNER;
case ERROR -> FontAwesome5Icon.TIMES;
case CANCELLED -> FontAwesome5Icon.BAN;
case SUCCEEDED -> severity.map(se -> DiagnosticResult.Severity.GOOD.compareTo(se) >= 0 ? FontAwesome5Icon.CHECK : FontAwesome5Icon.EXCLAMATION_TRIANGLE).orElse(null);
}).orElse(null);
}
public ObjectProperty<Check> checkProperty() {
return check;
}
public void setCheck(Check c) {
check.set(c);
}
public Check getCheck() {
return check.get();
}
}

View File

@@ -4,12 +4,17 @@
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.VBox?>
<?import org.cryptomator.ui.health.CheckStateIconView?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.health.CheckDetailController"
prefWidth="500"
spacing="6">
<FormattedLabel fx:id="checkTitle" styleClass="label-large" format="%health.check.detail.header" arg1="${controller.checkName}"/>
<FormattedLabel fx:id="checkTitle" styleClass="label-large" format="%health.check.detail.header" arg1="${controller.checkName}" contentDisplay="LEFT">
<graphic>
<CheckStateIconView fx:id="checkStateIconView" check="${controller.check}" glyphSize="20"/>
</graphic>
</FormattedLabel>
<Label text="%health.check.detail.checkRunning" visible="${controller.checkRunning}" managed="${controller.checkRunning}"/>
<Label text="%health.check.detail.checkScheduled" visible="${controller.checkScheduled}" managed="${controller.checkScheduled}"/>
@@ -19,6 +24,6 @@
<Label text="%health.check.detail.checkSucceeded" visible="${controller.checkSucceeded}" managed="${controller.checkSucceeded}"/>
<FormattedLabel styleClass="label" format="%health.check.detail.problemCount" arg1="${controller.countOfWarnSeverity}" arg2="${controller.countOfCritSeverity}" visible="${!controller.checkSkipped}"
managed="${!controller.checkSkipped}" />
managed="${!controller.checkSkipped}"/>
<ListView fx:id="resultsListView" VBox.vgrow="ALWAYS" visible="${!controller.checkSkipped}"/>
</VBox>