From 349ee69a7fc519d9b9542800690618e935a40f5a Mon Sep 17 00:00:00 2001 From: "van Elst, Marcus" Date: Mon, 4 May 2026 12:31:18 +0200 Subject: [PATCH] #85: Verwerfen im Prompt-Tab setzt Dirty-State und laedt Inhalt neu Nach Bestaetigung des Verwerfen-Dialogs fehlte der Aufruf, der den Tab-Zustand zuruecksetzt. Neue Methode discardChanges() in GuiPromptEditorTab setzt loadedContent, dirty und Tab-Titel zurueck; ist der Tab sichtbar, wird loadPromptAsync() sofort ausgeloest, sonst greift der bestehende selectedProperty-Listener beim naechsten Oeffnen. GuiConfigurationEditorWorkspace ruft discardChanges() nach positivem Bestaedigungsdialog auf. Neuer Smoke-Test verifiziert das Verhalten. Co-Authored-By: Claude Sonnet 4.6 --- .../gui/GuiConfigurationEditorWorkspace.java | 2 + .../adapter/in/gui/GuiPromptEditorTab.java | 19 +++++++++ .../in/gui/GuiPromptEditorTabSmokeTest.java | 40 +++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiConfigurationEditorWorkspace.java b/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiConfigurationEditorWorkspace.java index fe8e026..ac62940 100644 --- a/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiConfigurationEditorWorkspace.java +++ b/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiConfigurationEditorWorkspace.java @@ -1389,6 +1389,8 @@ public final class GuiConfigurationEditorWorkspace { boolean shouldDiscard = promptEditorTab.confirmDiscardIfDirty(); if (!shouldDiscard) { Platform.runLater(() -> tabPane.getSelectionModel().select(oldTab)); + } else { + promptEditorTab.discardChanges(); } } }); diff --git a/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTab.java b/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTab.java index ac64404..de51bfe 100644 --- a/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTab.java +++ b/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTab.java @@ -154,6 +154,25 @@ public class GuiPromptEditorTab { } } + /** + * Verwirft alle ungespeicherten Änderungen und setzt den Tab in den Lade-Bereitschaftszustand. + *

+ * Setzt Dirty-State und Tab-Titel zurück. Ist der Tab zum Zeitpunkt des Aufrufs sichtbar, + * wird der Prompt-Inhalt sofort neu geladen; andernfalls erfolgt das Laden beim nächsten + * Öffnen des Tabs (gesteuert durch den Tab-Selektions-Listener). + *

+ * Muss auf dem JavaFX Application Thread aufgerufen werden. + */ + public void discardChanges() { + this.loadedContent = null; + this.dirty = false; + this.tab.setText(TAB_TITLE); + this.saveButton.setDisable(true); + if (tab.isSelected()) { + loadPromptAsync(); + } + } + /** * Zeigt einen Bestätigungsdialog, wenn ungespeicherte Änderungen vorhanden sind. * Gibt {@code true} zurück, wenn die Änderungen verworfen werden dürfen. diff --git a/pdf-umbenenner-adapter-in-gui/src/test/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTabSmokeTest.java b/pdf-umbenenner-adapter-in-gui/src/test/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTabSmokeTest.java index d0c9c86..f304d4a 100644 --- a/pdf-umbenenner-adapter-in-gui/src/test/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTabSmokeTest.java +++ b/pdf-umbenenner-adapter-in-gui/src/test/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/GuiPromptEditorTabSmokeTest.java @@ -328,4 +328,44 @@ class GuiPromptEditorTabSmokeTest { "Tab-Titel muss nach Bearbeitung (resetToDefault) einen Asterisk enthalten; Titel war: " + titleRef.get()); } + + @Test + void discardChanges_shouldResetDirtyStateAndTitle() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + AtomicReference fxError = new AtomicReference<>(); + AtomicBoolean dirtyRef = new AtomicBoolean(true); + AtomicReference titleRef = new AtomicReference<>(); + + Platform.runLater(() -> { + try { + SyncPromptEditorPort port = new SyncPromptEditorPort(); + GuiPromptEditorTab editorTab = buildSyncTab(port); + editorTab.loadPromptAsync(); + editorTab.resetToDefault(); + // Vorbedingung: Dirty-State muss aktiv sein + assertTrue(editorTab.hasDirtyContent(), + "Vorbedingung: Dirty-State muss nach resetToDefault aktiv sein"); + + // Verwerfen simulieren + editorTab.discardChanges(); + + dirtyRef.set(editorTab.hasDirtyContent()); + titleRef.set(editorTab.tab().getText()); + } catch (Throwable t) { + fxError.set(t); + } finally { + latch.countDown(); + } + }); + + assertTrue(latch.await(FX_TIMEOUT_SECONDS, TimeUnit.SECONDS)); + if (fxError.get() != null) { + throw new AssertionError("FX-Thread hat eine Ausnahme geworfen", fxError.get()); + } + assertFalse(dirtyRef.get(), + "Dirty-State muss nach discardChanges false sein"); + assertFalse(titleRef.get().contains("*"), + "Tab-Titel darf nach discardChanges keinen Asterisk enthalten; Titel war: " + + titleRef.get()); + } }