Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
16 KiB
Architektur-Übersicht: GUI (adapter-in-gui)
Diese Datei beschreibt den Inbound-Adapter pdf-umbenenner-adapter-in-gui – die JavaFX-Desktop-GUI des PDF-Umbenenners. Sie ist zusammen mit CLAUDE.md im Projektroot als alleiniger Architekturkontext für GUI-Arbeit gedacht. Domain-Typen, Application-Ports und Outbound-Adapter (Dateisystem, SQLite, KI-HTTP) sind hier bewusst nicht beschrieben; dafür gelten docs/architecture/domain-overview.md und docs/architecture/adapter-overview.md. Das JavaFX-Threading-Modell (Abschnitt 4) ist verbindlich und muss strikt eingehalten werden – GUI-Entwickler sollten diesen Abschnitt als erstes lesen.
1. Modulzweck
pdf-umbenenner-adapter-in-gui ist der Inbound-Adapter für die Desktop-Oberfläche. Er:
- empfängt den Startaufruf von der Bootstrap-Schicht über
GuiAdapter, - baut das JavaFX-Hauptfenster auf,
- delegiert alle fachlichen und technischen Operationen an Bootstrap-seitig verdrahtete Ports,
- zeigt Ergebnisse ausschließlich auf dem JavaFX Application Thread an.
Das Modul enthält keine fachliche Logik, keinen Datenbankzugriff, keinen HTTP-Code und keine PDF-Verarbeitung. Es koordiniert lediglich Benutzereingaben, Worker-Threads und JavaFX-Controls.
2. Paketstruktur
de.gecheckt.pdf.umbenenner.adapter.in.gui
│
├── (root) Einstiegspunkt, Hauptfenster, Orchestrierung, GUI-interne
│ Ports, Hilfsklassen für Fenstertitel, System-Tray,
│ Dateiladen/-schreiben und Startkontext.
│ Enthält außerdem: GuiStatusBar, GuiPromptEditorTab und
│ GuiPromptEditorPort.
│
├── batchrun Komponenten für den Tab „Verarbeitungslauf":
│ Worker-Koordinator, Tab-Ansicht, Ergebniszeilen,
│ PDF-Vorschau, Dateiname-Editor sowie GUI-interne
│ Port-Interfaces für Batch-Run, Mini-Run, manuelles
│ Umbenennen/Kopieren, Status-Reset und historischen Kontext.
│ Enthält außerdem: BatchRunSummaryBanner und
│ ProcessingStatusPresentation.
│
├── editor View-Modell- und Zustandstypen ohne JavaFX-Controls
│ (Ausnahme: GuiModelFieldContainer). Enthält Snapshot,
│ Baseline/Current-Values, Dirty-State-Berechnung,
│ Provider-Konfigurationszustände, API-Key-Zustände,
│ Validierungsergebnisse, Meldungs- und Feldbefund-Typen.
│
└── history Komponenten für den Tab „Verlauf": Tab-Ansicht mit
zweigeteiltem Layout (Liste + Detail), Filter, Aktionen
(Status-Reset / vollständiges Löschen) sowie die vier
Bridge-Interfaces GuiHistoryOverviewPort,
GuiHistoryDetailsPort, GuiHistoryResetDocumentStatusPort
und GuiDeleteDocumentHistoryPort.
Tab-Reihenfolge: Konfiguration | Verarbeitungslauf | Verlauf | Prompt
3. Schlüsselklassen
Root-Paket
| Klasse (Kurzname) | Rolle |
|---|---|
GuiAdapter |
Einziger öffentlicher Bootstrap-Einstiegspunkt. Speichert GuiStartupContext im GuiStartupContextHolder und startet JavaFX via Application.launch. Genau einmal pro JVM aufrufbar. |
PdfUmbenennerGuiApplication |
JavaFX-Application-Unterklasse. Baut in start(Stage) Hauptfenster, GuiConfigurationEditorWorkspace, Titelaktualisierungs-Listener, Close-Handler und System-Tray auf. Triggert nach Anzeige autoLoadLastConfiguration(). |
GuiStartupContext |
Immutable Record mit allen Bootstrap-gelieferten Ports und Services: Dateilader/-schreiber, Modellkatalog-Port, API-Key-Resolution-Port, Technical-Test-Orchestrator, Correction-Execution-Service, Batch-Run-Launcher, Mini-Run-Launcher, Reset-Port, Manual-Rename-Port, Manual-Copy-Port, Historical-Context-Port, applicationVersion (Versions-String aus ApplicationVersionProvider), promptEditorPort, historyOverviewPort, historyDetailsPort, historyResetDocumentStatusPort, deleteDocumentHistoryPort. Bietet blank()-Fabrikmethode für Tests. |
GuiConfigurationEditorWorkspace |
Herzstück der Oberfläche. Baut TabPane mit den vier Tabs (Konfiguration, Verarbeitungslauf, Verlauf, Prompt), verwaltet GuiConfigurationEditorState, koordiniert Lade- und Schreibvorgänge auf Worker-Threads, steuert Dirty-State-Anzeige und Fenstertitel. |
GuiStatusBar |
Permanente Statuszeile am unteren Rand des Hauptfensters. Drei Segmente: links Anwendungsversion im Format V<version> (z. B. Vdev), Mitte aktiver Provider und Modell aus geladener Konfiguration, rechts Pfad der geladenen Konfigurationsdatei. Ohne geladene Konfiguration zeigen Mitte und Rechts den Platzhaltertext. |
GuiPromptEditorTab |
Tab „Prompt" mit TextArea zum Lesen, Bearbeiten und Speichern der Prompt-Datei. Dirty-State markiert den Tab-Titel mit einem Asterisk. Speichert atomar via GuiPromptEditorPort. Bietet „Auf Standard zurücksetzen" (füllt TextArea ohne zu speichern) und „Standard-Prompt erstellen" bei fehlender Datei. |
GuiModelCatalogCoordinator |
Asynchroner Modellabruf über AiModelCatalogPort auf Daemon-Thread gui-model-catalog. Liefert Ergebnis via Platform.runLater und aktualisiert ComboBox oder manuelles TextField. |
GuiTechnicalTestCoordinator |
Führt TechnicalTestOrchestrator asynchron auf Daemon-Thread gui-technical-test aus, ohne implizites Speichern. Replace-Semantik in pendingMessages. |
GuiCorrectionDialogCoordinator |
Empfängt TechnicalTestReport, leitet CorrectionPlan ab, zeigt gesammelten Bestätigungsdialog. Kein stiller Schreibzugriff. |
GuiUnsavedChangesGuard |
Drei-Wege-Schutzdialog (Speichern / Verwerfen / Abbrechen) vor Neu, Öffnen und Schließen. Dialog-Supplier ist injizierbar für Tests ohne Scene. |
SystemTrayManager |
Verwaltet Windows-System-Tray-Icon. Überbrückt AWT-EDT nach JavaFX via Platform.runLater für Stage-Operationen. |
Paket editor
| Klasse (Kurzname) | Rolle |
|---|---|
GuiConfigurationEditorState |
Record mit loadedFileSnapshot, baselineValues, values, pendingMigrationMessage. Dirty-State wird per Vergleich berechnet, kein Flag. |
GuiConfigurationValues |
Hält alle editierbaren Konfigurationsfelder als JavaFX-freie Plain-Java-Typen. |
Paket batchrun
| Klasse (Kurzname) | Rolle |
|---|---|
GuiBatchRunCoordinator |
Besitzt den Worker-Thread für Batch- und Mini-Run. Übersetzt BatchRunProgressObserver-Callbacks via Platform.runLater. Soft-Stop per AtomicBoolean. Enthält toRow() inkl. historischem Kontext-Nachladen. |
GuiBatchRunTab |
Zweiter Haupt-Tab mit TableView, ProgressBar, Start-/Stop-Buttons und Detailbereich. Implementiert GuiBatchRunCoordinator.Listener. |
BatchRunSummaryBanner |
Einzeilige Zusammenfassungsleiste nach Laufabschluss, unterhalb des Fortschrittsbalkens. Zeigt nur Kategorien mit Zähler > 0. Farbe ist niemals das einzige Unterscheidungsmerkmal: jedes Segment enthält Icon und Text. |
ProcessingStatusPresentation |
Zentrale Mapping-Klasse für Status-Icons, CSS-Farben, Tooltip-Texte und Summary-Kategoriebeschriften aller DocumentCompletionStatus-Werte. Einzige autoritative Quelle für alle Anzeigeorte (Tabelle, Detail, Banner). Enthält keine JavaFX-Typen; zustandslos und statisch. Farbe ist niemals das einzige Unterscheidungsmerkmal. |
PdfPreviewPane |
Asynchrones PDF-Rendering via PDFBox auf Single-Thread-Executor pdf-preview-worker. Stale-Request-Schutz via AtomicLong-Sequenznummer, In-Memory-Seiten-Cache. |
FileNameEditorPane |
Editor für den Zieldateinamen. Drei-Zustands-Modell: KI-Vorschlag / letzter gespeicherter / aktuelle Eingabe. Clientseitige Validierung; Speicher-Aufruf delegiert an Tab. |
AiFailureMessageTranslator |
Übersetzt englische technische Fehlermeldungen in deutsche Benutzertexte. Paket-privat, zustandslos. |
Paket history
| Klasse (Kurzname) | Rolle |
|---|---|
GuiHistoryTab |
Tab „Verlauf" mit zweigeteiltem Layout: links Dokumentenliste mit Freitext- und Statusfilter, rechts Detailbereich mit Stammsatz und Versuchshistorie. Aktionen: Status-Reset (feldgenau, Versuchshistorie bleibt) und vollständiges Löschen (mit Bestätigungsdialog). Alle Datenbankoperationen auf Worker-Thread, UI-Updates via Platform.runLater. |
4. Threading-Modell
Das Modell ist verbindlich. Jede Verletzung dieser Regeln führt zu sporadischen IllegalStateException-Fehlern oder einer eingefrorenen Oberfläche.
4.1 Worker-Threads
Alle blockierenden Operationen laufen auf benannten Daemon-Threads außerhalb des JavaFX Application Thread.
| Thread-Name | Koordinator-Klasse | Operationen |
|---|---|---|
gui-batch-run |
GuiBatchRunCoordinator |
Batch-Launcher, Mini-Run-Launcher, Reset-Port, historischer Kontext |
gui-model-catalog |
GuiModelCatalogCoordinator |
modelCatalogPort.fetchAvailableModels(...) |
gui-technical-test |
GuiTechnicalTestCoordinator |
orchestrator.runTests(...) |
| Korrektur-Worker (anonym) | GuiCorrectionDialogCoordinator |
correctionExecutionService.execute(...) |
pdf-preview-worker |
PdfPreviewPane |
PDDocument laden, PDFRenderer.renderImageWithDPI, PDDocument.close |
| Dateisystem-Worker (inline) | GuiConfigurationEditorWorkspace |
configurationFileLoader.load(...), configurationFileWriter.write(...) |
| Inline-Worker (anonym) | GuiHistoryTab |
historyOverviewPort.loadOverview(...), historyDetailsPort.loadDetails(...), historyResetDocumentStatusPort.resetStatus(...), deleteDocumentHistoryPort.deleteHistory(...) |
| Inline-Worker (anonym) | GuiPromptEditorTab |
promptEditorPort.loadCurrentPrompt(), promptEditorPort.save(...), promptEditorPort.createDefaultPromptIfMissing(...) |
4.2 JavaFX Application Thread
Alle Mutationen an JavaFX-Controls und alle Dialoganzeigen ausschließlich auf dem JavaFX Application Thread. Kein direktes Schreiben auf Controls vom Worker-Thread.
4.3 Übergangsmechanismus Worker → FX
Der Übergang erfolgt grundsätzlich via:
Platform.runLater(runnable);
Es werden keine javafx.concurrent.Task und kein Service verwendet. Die Koordinatoren steuern Threading manuell über zwei injizierbare Strategien:
| Injektionspunkt | Typ | Produktion | Tests |
|---|---|---|---|
threadFactory |
Function<Runnable, Thread> |
Thread::new (Daemon) |
synchroner Direktaufruf |
fxDispatcher |
Consumer<Runnable> |
Platform::runLater |
synchroner Direktaufruf |
Durch diese Injektion sind Unit-Tests vollständig ohne JavaFX-Runtime möglich.
4.4 Stale-Request-Schutz
PdfPreviewPane vergibt für jede Renderanfrage eine inkrementelle AtomicLong-Sequenznummer. Ein abgeschlossenes Render-Ergebnis wird nur dann auf der UI angezeigt, wenn seine Sequenznummer noch der aktuellen entspricht. Veraltete Ergebnisse werden still verworfen.
5. GUI-interne Ports
Abgrenzung: Die folgenden Interfaces sind keine hexagonalen Outbound-Ports der Application-Schicht. Sie sind modul-interne Brücken, über die
GuiAdapterdie Bootstrap-seitig verdrahteten Implementierungen in die GUI-Klassen einschleust. Die eigentlichen Application-Ports (AiInvocationPort,AiModelCatalogPortusw.) und deren Outbound-Adapter-Implementierungen sind indocs/architecture/domain-overview.mdunddocs/architecture/adapter-overview.mdbeschrieben.
Root-Paket
| Interface | Zweck |
|---|---|
GuiConfigurationFileLoader |
Lädt eine .properties-Datei und liefert einen GuiConfigurationEditorState. Abstrahiert Migration und Bootstrap-Verdrahtung vom GUI-Code. |
GuiConfigurationFileWriter |
Schreibt aktuelle GuiConfigurationValues als normalisierte .properties inkl. Backup-Schema. |
Paket batchrun
| Interface | Zweck |
|---|---|
GuiBatchRunLauncher |
Bootstrap-Brücke für den regulären Batch-Run auf dem Worker-Thread. |
GuiMiniRunLauncher |
Bootstrap-Brücke für einen auf einen Fingerprint-Filter beschränkten Mini-Run. |
GuiResetDocumentStatusPort |
Bootstrap-Brücke für den vollständigen Persistenz-Reset (Stammsatz und Versuchshistorie werden gelöscht) ohne Folge-Run. |
GuiManualFileRenamePort |
Bootstrap-Brücke für die manuelle Umbenennung der Zieldatei (Worker-Thread). |
GuiManualFileCopyPort |
Bootstrap-Brücke für die Kopie mit benutzerdefiniertem Zieldateinamen bei FAILED/SKIPPED-Dokumenten (Worker-Thread). |
GuiHistoricalDocumentContextPort |
Nachladen des vollständigen historischen Verarbeitungskontexts für übersprungene Dokumente (Worker-Thread). |
GuiHistoricalFileNamePort |
Spezialisierter Port für den letzten bekannten KI-Dateinamen. Weitgehend durch GuiHistoricalDocumentContextPort abgelöst, aber noch im Einsatz. |
Root-Paket (GUI-interne Ports)
| Interface | Zweck |
|---|---|
GuiPromptEditorPort |
Bootstrap-Brücke zum Prompt-Editor-Use-Case: Laden (loadCurrentPrompt()), atomares Speichern (save(String)) und Standard-Anlegen (createDefaultPromptIfMissing(...)) der Prompt-Datei. |
Paket history
| Interface | Zweck |
|---|---|
GuiHistoryOverviewPort |
Bootstrap-Brücke zur Historien-Übersicht; lädt gefilterte Dokumentenliste via loadOverview(Path configFilePath, HistoryQuery). configFilePath ermöglicht der Bootstrap-Implementierung, die SQLite-Datenbank aus der aktuell geladenen Konfiguration abzuleiten. |
GuiHistoryDetailsPort |
Bootstrap-Brücke zur Detailansicht; lädt Stammsatz und alle Verarbeitungsversuche für einen Fingerprint via loadDetails(Path, DocumentFingerprint). |
GuiHistoryResetDocumentStatusPort |
Bootstrap-Brücke für den feldgenauen Status-Reset im Historien-Tab (overall_status → READY_FOR_AI, Fehlerzähler → 0, last_failure_instant → null). Die Versuchshistorie bleibt vollständig erhalten. Abgrenzung: GuiResetDocumentStatusPort im batchrun-Paket löscht dagegen Stammsatz und Versuchshistorie vollständig. |
GuiDeleteDocumentHistoryPort |
Bootstrap-Brücke zum vollständigen Löschen von Stammsatz und Versuchshistorie via deleteHistory(Path, DocumentFingerprint); destruktiv und nicht rückgängig zu machen. Die GUI zeigt vor dem Aufruf einen Bestätigungsdialog. |
Alle Implementierungen dieser Interfaces liegen in pdf-umbenenner-bootstrap. Das GUI-Modul kennt ausschließlich die Interface-Typen.
6. Einstiegspunkte für neue Entwickler
Folgende Klassen und Dateien decken den schnellsten Einstieg ab:
-
GuiAdapter– Architekturgrenze zur Bootstrap-Schicht in zwei Methoden. Zeigt, wie die GUI aus Bootstrap-Sicht aufgerufen wird. -
GuiStartupContext– Vollständige Liste aller Ports und Services, die Bootstrap in die GUI injiziert. Wer wissen will, was die GUI von außen bekommt, liest diesen Record. -
GuiConfigurationEditorWorkspace– Zentrale UI-Klasse: Tab-Aufbau, Sektionen, Editor-Zustand, Dirty-State, Datei-I/O, Sub-Koordinatoren. Einstieg für alle Arbeiten am Konfigurationseditor-Tab. -
GuiConfigurationEditorState/GuiConfigurationValues– View-Modell ohne JavaFX-Controls. Einstieg für alle Änderungen an editierbaren Konfigurationsfeldern und Dirty-State-Logik. -
GuiBatchRunCoordinator– Threading-Modell in seiner reinsten Form: Worker-Thread,Platform.runLater-Übergabe, Soft-Stop, Listener-Protokoll. Einstieg für alle Arbeiten am Verarbeitungslauf-Tab. -
batchrun/package-info.java– Kompakte Beschreibung des Threading-Kontrakts, der Abbruch-Semantik und der Konfigurationsquelle für dieses Paket.
Querverweise
- Application-Ports und Domain-Typen (
NamingProposal,ProcessingStatus,DocumentFingerprintusw.):docs/architecture/domain-overview.md - Outbound-Adapter-Implementierungen (Dateisystem, SQLite, KI-HTTP, PDFBox) und Bootstrap-Verdrahtung:
docs/architecture/adapter-overview.md