Behebe Darstellungsfehler der Statusicons und Stale-Summary-Bug

Statusicons (Bug 2): Emoji-Codepunkte werden durch BMP-Zeichen ersetzt
(✔ ⚠ ✘ ►), die in JavaFX auf Windows zuverlässig gerendert werden.
Die Statusspalte erhält eine farbige Cell-Factory (grün/orange/rot/grau).

Stale Summary (Bug 1): observerSummary wird zu Beginn jedes Laufs
zurückgesetzt, damit eine abgebrochene Vorgänger-Zusammenfassung
nicht als Ergebnis des neuen Laufs erscheint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-22 16:27:33 +02:00
parent f4cfb5cbc0
commit 20a14b3c62
4 changed files with 38 additions and 10 deletions
@@ -193,6 +193,7 @@ public final class GuiBatchRunCoordinator {
private void executeRun(Path configFilePath) {
LOG.info("GUI-Verarbeitungslauf: Worker-Thread gestartet für Konfiguration {}.",
configFilePath);
observerSummary.set(null);
BatchRunProgressObserver observer = buildDispatchingObserver();
BatchRunCancellationToken token = cancellationRequested::get;
GuiBatchRunLaunchOutcome outcome;
@@ -59,16 +59,17 @@ public record GuiBatchRunResultRow(
}
/**
* Returns the status icon for this row, mirroring the specification.
* Returns the status icon for this row as a Basic Multilingual Plane character
* that renders reliably in JavaFX on Windows.
*
* @return the corresponding emoji icon
* @return the corresponding status character
*/
public String statusIcon() {
return switch (status) {
case SUCCESS -> "\u2705"; // ✅
case FAILED_RETRYABLE -> "\u26A0\uFE0F"; // ⚠
case FAILED_PERMANENT -> "\u274C"; //
case SKIPPED -> "\u23ED\uFE0F"; // ⏭️
case SUCCESS -> "\u2714"; // ✔ HEAVY CHECK MARK
case FAILED_RETRYABLE -> "\u26A0"; // ⚠ WARNING SIGN (no variation selector)
case FAILED_PERMANENT -> "\u2718"; // ✘ HEAVY BALLOT X
case SKIPPED -> "\u25BA"; // ► BLACK RIGHT-POINTING POINTER
};
}
}
@@ -28,6 +28,7 @@ import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
@@ -295,6 +296,22 @@ public final class GuiBatchRunTab {
TableColumn<GuiBatchRunResultRow, String> iconCol = new TableColumn<>("Status");
iconCol.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().statusIcon()));
iconCol.setPrefWidth(64);
iconCol.setCellFactory(col -> new TableCell<GuiBatchRunResultRow, String>() {
@Override
protected void updateItem(String icon, boolean empty) {
super.updateItem(icon, empty);
if (empty || icon == null) {
setText(null);
setStyle(null);
return;
}
setText(icon);
TableRow<GuiBatchRunResultRow> tableRow = getTableRow();
GuiBatchRunResultRow data = tableRow != null ? tableRow.getItem() : null;
String color = data != null ? statusColor(data.status()) : "#000000";
setStyle("-fx-text-fill: " + color + "; -fx-alignment: CENTER; -fx-font-size: 14;");
}
});
TableColumn<GuiBatchRunResultRow, String> nameCol = new TableColumn<>("Originaldateiname");
nameCol.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().originalFileName()));
@@ -338,6 +355,15 @@ public final class GuiBatchRunTab {
});
}
private static String statusColor(DocumentCompletionStatus status) {
return switch (status) {
case SUCCESS -> "#2e7d32";
case FAILED_RETRYABLE -> "#e65100";
case FAILED_PERMANENT -> "#c62828";
case SKIPPED -> "#757575";
};
}
private static String formatDuration(Duration duration) {
double seconds = duration.toMillis() / 1000.0;
if (seconds < 10) {