Schritte 11-13: Config-Tab-Sperre, Batch-Button-Sperre, Scheduler-Close-Guard
Schritt 11: updateLockState() implementiert in GuiConfigurationEditorWorkspace - schedulerLockActive-Feld eingeführt - applyBatchRunLockState() delegiert an neues applyConfigTabLockState() - applyConfigTabLockState() vereint Batch-Run- und Scheduler-Sperre: Banner, sectionsBox, Neu/Öffnen/Speichern/Speichern-unter werden gesperrt wenn Scheduler aktiv oder Lauf aktiv Schritt 12: updateSchedulerState() implementiert in GuiBatchRunTab - schedulerActive-Feld eingeführt - Starten-Button wird deaktiviert + Tooltip gesetzt wenn Scheduler läuft - updateButtonStates() berücksichtigt schedulerActive damit Sperre beim Laufende nicht verloren geht Schritt 13: Scheduler-Close-Guard in PdfUmbenennerGuiApplication - installSchedulerCloseGuard() als äußerste Schicht des Close-Handlers - Zeigt Informationsdialog und verhindert Beenden wenn Scheduler aktiv - Bestehender Workspace-/Tray-Handler bleibt erhalten wenn Scheduler gestoppt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+47
-23
@@ -477,13 +477,19 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
private final GuiPromptEditorTab promptEditorTab;
|
||||
|
||||
/**
|
||||
* Hint banner shown at the top of the configuration tab while a processing run is
|
||||
* active. Visible + managed state are flipped from the batch run tab's listener when
|
||||
* the running flag toggles.
|
||||
* Hint banner shown at the top of the configuration tab while a processing run or
|
||||
* the automatic scheduler is active. Visible + managed state are controlled by
|
||||
* {@link #applyConfigTabLockState()}.
|
||||
*/
|
||||
final Label configurationLockBanner = new Label(
|
||||
"Konfiguration während eines laufenden Verarbeitungslaufs nicht editierbar");
|
||||
|
||||
/**
|
||||
* {@code true} while the automatic scheduler is in any non-{@code STOPPED} state.
|
||||
* Updated by {@link #updateLockState(SchedulerStatus)} from the 1 Hz refresh timeline.
|
||||
*/
|
||||
private boolean schedulerLockActive = false;
|
||||
|
||||
/**
|
||||
* Reference to the configuration tab so the running-state listener can disable its
|
||||
* content while a batch run is active.
|
||||
@@ -695,23 +701,41 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the "batch run active" UI lock state to the configuration tab and the
|
||||
* action bar.
|
||||
* Applies the "batch run active" UI lock state to the configuration tab.
|
||||
* <p>
|
||||
* While a run is active the configuration editor is made non-interactive, the lock
|
||||
* banner is shown at the top of Tab 1, and the main action buttons (Neu, Öffnen,
|
||||
* Speichern, Speichern unter) are disabled. When the run ends, the locks are
|
||||
* released and the editor returns to its normal state.
|
||||
* Delegates to {@link #applyConfigTabLockState()} so that both the batch-run lock
|
||||
* and the scheduler lock are evaluated together. Called whenever the batch-run
|
||||
* running state changes.
|
||||
*/
|
||||
void applyBatchRunLockState() {
|
||||
boolean running = batchRunTab != null && batchRunTab.isRunning();
|
||||
configurationLockBanner.setVisible(running);
|
||||
configurationLockBanner.setManaged(running);
|
||||
sectionsBox.setDisable(running);
|
||||
newButton.setDisable(running);
|
||||
openButton.setDisable(running);
|
||||
saveButton.setDisable(running);
|
||||
saveAsButton.setDisable(running);
|
||||
applyConfigTabLockState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the combined lock state (batch run active <em>or</em> scheduler active)
|
||||
* and applies it to the configuration tab.
|
||||
* <p>
|
||||
* When either source is locked the banner is shown, all input sections are disabled
|
||||
* and the action buttons (Neu, Öffnen, Speichern, Speichern unter) are disabled.
|
||||
* The banner text describes the dominant lock source.
|
||||
*/
|
||||
private void applyConfigTabLockState() {
|
||||
boolean batchRunning = batchRunTab != null && batchRunTab.isRunning();
|
||||
boolean locked = batchRunning || schedulerLockActive;
|
||||
|
||||
String bannerText = schedulerLockActive
|
||||
? "⚠ Konfiguration gesperrt – Scheduler läuft (oder Lauf aktiv)."
|
||||
+ " Scheduler beenden bzw. Lauf abwarten um Änderungen vorzunehmen."
|
||||
: "Konfiguration während eines laufenden Verarbeitungslaufs nicht editierbar";
|
||||
|
||||
configurationLockBanner.setText(bannerText);
|
||||
configurationLockBanner.setVisible(locked);
|
||||
configurationLockBanner.setManaged(locked);
|
||||
sectionsBox.setDisable(locked);
|
||||
newButton.setDisable(locked);
|
||||
openButton.setDisable(locked);
|
||||
saveButton.setDisable(locked);
|
||||
saveAsButton.setDisable(locked);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1116,17 +1140,17 @@ public final class GuiConfigurationEditorWorkspace {
|
||||
/**
|
||||
* Aktualisiert den Sperr-Zustand des Konfig-Tabs anhand des aktuellen Scheduler-Status.
|
||||
* <p>
|
||||
* Muss auf dem JavaFX Application Thread aufgerufen werden. Wird von
|
||||
* {@link #onSchedulerStatusRefresh} und der Status-Refresh-Timeline (1 Hz) indirekt
|
||||
* aufgerufen.
|
||||
* Setzt {@link #schedulerLockActive} und ruft {@link #applyConfigTabLockState()} auf,
|
||||
* sodass Banner, Eingabefelder und Aktionsbuttons des Konfig-Tabs sofort in den
|
||||
* korrekten Zustand versetzt werden.
|
||||
* <p>
|
||||
* Die konkrete Reaktion (z. B. Banner-Anzeige und Speichern-Button-Sperre während ein
|
||||
* Scheduler-Lauf aktiv ist) wird in einem späteren Implementierungsschritt ergänzt.
|
||||
* Muss auf dem JavaFX Application Thread aufgerufen werden.
|
||||
*
|
||||
* @param status aktueller Scheduler-Status; darf nicht {@code null} sein
|
||||
*/
|
||||
public void updateLockState(SchedulerStatus status) {
|
||||
// Stub – Implementierung folgt in späterem Schritt
|
||||
schedulerLockActive = status.state().isActive();
|
||||
applyConfigTabLockState();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+37
@@ -8,6 +8,7 @@ import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Menu;
|
||||
import javafx.scene.control.MenuBar;
|
||||
import javafx.scene.control.MenuItem;
|
||||
@@ -110,6 +111,9 @@ public class PdfUmbenennerGuiApplication extends Application {
|
||||
installTrayCloseHandler(primaryStage, workspace);
|
||||
}
|
||||
|
||||
// Scheduler-Close-Guard als äußerste Schicht: verhindert Beenden während Scheduler aktiv
|
||||
installSchedulerCloseGuard(primaryStage);
|
||||
|
||||
primaryStage.setMaximized(true);
|
||||
primaryStage.show();
|
||||
|
||||
@@ -180,6 +184,39 @@ public class PdfUmbenennerGuiApplication extends Application {
|
||||
return new MenuBar(databaseMenu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Legt den Scheduler-Close-Guard als äußerste Schicht des Close-Request-Handlers an.
|
||||
* <p>
|
||||
* Ist kein {@link de.gecheckt.pdf.umbenenner.application.port.in.SchedulerControlUseCase}
|
||||
* vorhanden, bleibt der bestehende Handler unverändert. Ist der Scheduler aktiv
|
||||
* (Zustand != {@code STOPPED}), wird das Schließen verhindert und ein
|
||||
* Informationsdialog angezeigt. Ist der Scheduler gestoppt, wird der bisherige
|
||||
* Handler (SystemTray + Workspace-Dirty-Guard) aufgerufen.
|
||||
*
|
||||
* @param stage das primäre Fenster; darf nicht {@code null} sein
|
||||
*/
|
||||
private void installSchedulerCloseGuard(Stage stage) {
|
||||
guiStartupContext.schedulerControlUseCase().ifPresent(uc -> {
|
||||
EventHandler<WindowEvent> existingHandler = stage.getOnCloseRequest();
|
||||
stage.setOnCloseRequest(event -> {
|
||||
if (uc.getStatus().state().isActive()) {
|
||||
event.consume();
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle("Anwendung kann nicht beendet werden");
|
||||
alert.setHeaderText(null);
|
||||
alert.setContentText(
|
||||
"Ein Lauf ist aktiv oder der Scheduler läuft.\n"
|
||||
+ "Bitte beende den Scheduler bzw. warte auf das Ende des Laufs.");
|
||||
alert.showAndWait();
|
||||
return;
|
||||
}
|
||||
if (existingHandler != null) {
|
||||
existingHandler.handle(event);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Legt einen Close-Request-Handler an, der bei sauberem Zustand das Fenster in den
|
||||
* System-Tray minimiert statt es zu schließen.
|
||||
|
||||
+13
-6
@@ -196,6 +196,9 @@ public final class GuiBatchRunTab {
|
||||
private final Button resetStatusButton = new Button("Status zurücksetzen");
|
||||
private final ReadOnlyBooleanWrapper runningProperty = new ReadOnlyBooleanWrapper(false);
|
||||
|
||||
/** {@code true} while the automatic scheduler is in any non-{@code STOPPED} state. */
|
||||
private boolean schedulerActive = false;
|
||||
|
||||
/** Dateiname-Editor-Komponente im Detailbereich. */
|
||||
private final FileNameEditorPane fileNameEditor = new FileNameEditorPane();
|
||||
|
||||
@@ -496,16 +499,20 @@ public final class GuiBatchRunTab {
|
||||
/**
|
||||
* Aktualisiert den Tab-Zustand anhand des aktuellen Scheduler-Status.
|
||||
* <p>
|
||||
* Muss auf dem JavaFX Application Thread aufgerufen werden. Wird von der
|
||||
* zentralen Status-Refresh-Timeline (1 Hz) aufgerufen.
|
||||
* Deaktiviert den Starten-Button und setzt einen erklärenden Tooltip, solange
|
||||
* der Scheduler aktiv ist. Wenn der Scheduler gestoppt ist, wird der normale
|
||||
* Button-Zustand wiederhergestellt (Starten erlaubt sofern kein Lauf läuft).
|
||||
* <p>
|
||||
* Die konkrete Reaktion (z. B. Deaktivierung des Starten-Buttons während ein
|
||||
* Scheduler-Lauf aktiv ist) wird in einem späteren Implementierungsschritt ergänzt.
|
||||
* Muss auf dem JavaFX Application Thread aufgerufen werden.
|
||||
*
|
||||
* @param status aktueller Scheduler-Status; darf nicht {@code null} sein
|
||||
*/
|
||||
public void updateSchedulerState(SchedulerStatus status) {
|
||||
// Stub – Implementierung folgt in späterem Schritt
|
||||
schedulerActive = status.state().isActive();
|
||||
startButton.setDisable(runningProperty.get() || schedulerActive);
|
||||
startButton.setTooltip(new Tooltip(schedulerActive
|
||||
? "Manuelle Läufe sind während aktivem Scheduler nicht möglich."
|
||||
: GuiTooltipTexts.BATCHRUN_STARTEN));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -1485,7 +1492,7 @@ public final class GuiBatchRunTab {
|
||||
|
||||
private void updateButtonStates() {
|
||||
boolean running = runningProperty.get();
|
||||
startButton.setDisable(running);
|
||||
startButton.setDisable(running || schedulerActive);
|
||||
if (!running) {
|
||||
cancelButton.setDisable(true);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user