Files
2026-04-30 15:29:07 +02:00

16 KiB
Raw Permalink Blame History

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 GuiAdapter die Bootstrap-seitig verdrahteten Implementierungen in die GUI-Klassen einschleust. Die eigentlichen Application-Ports (AiInvocationPort, AiModelCatalogPort usw.) und deren Outbound-Adapter-Implementierungen sind in docs/architecture/domain-overview.md und docs/architecture/adapter-overview.md beschrieben.

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:

  1. GuiAdapter Architekturgrenze zur Bootstrap-Schicht in zwei Methoden. Zeigt, wie die GUI aus Bootstrap-Sicht aufgerufen wird.

  2. 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.

  3. GuiConfigurationEditorWorkspace Zentrale UI-Klasse: Tab-Aufbau, Sektionen, Editor-Zustand, Dirty-State, Datei-I/O, Sub-Koordinatoren. Einstieg für alle Arbeiten am Konfigurationseditor-Tab.

  4. GuiConfigurationEditorState / GuiConfigurationValues View-Modell ohne JavaFX-Controls. Einstieg für alle Änderungen an editierbaren Konfigurationsfeldern und Dirty-State-Logik.

  5. GuiBatchRunCoordinator Threading-Modell in seiner reinsten Form: Worker-Thread, Platform.runLater-Übergabe, Soft-Stop, Listener-Protokoll. Einstieg für alle Arbeiten am Verarbeitungslauf-Tab.

  6. 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, DocumentFingerprint usw.): docs/architecture/domain-overview.md
  • Outbound-Adapter-Implementierungen (Dateisystem, SQLite, KI-HTTP, PDFBox) und Bootstrap-Verdrahtung: docs/architecture/adapter-overview.md