using System; using Avalonia; using Avalonia.Controls; using Project_Periodensystem.Model; using Project_Periodensystem.Persistence; using Project_Periodensystem.Controller; namespace Project_Periodensystem.View { /// /// Concrete Implementation des Navigation Service für Avalonia UI /// /// ZWECK UND ARCHITEKTUR: /// - Implementiert INavigationService Interface aus dem Controller-Layer /// - Trennt sauber "WAS navigiert wird" (Controller) von "WIE navigiert wird" (View) /// - Kapselt alle Avalonia-spezifische Navigation-Logik /// - Ermöglicht verschiedene UI-Frameworks ohne Controller-Änderungen /// /// DESIGN PATTERNS: /// - Interface Implementation: Konkrete Umsetzung der abstrakten Navigation /// - Dependency Injection: MainWindow wird von außen injiziert /// - Facade Pattern: Vereinfacht komplexe UI-Navigation für Controller /// - Bridge Pattern: Verbindet Controller (Abstraktion) mit View (Implementation) /// /// C# KONZEPTE: /// - Interface Implementation: public class NavigationService : INavigationService /// - Constructor Injection: MainWindow als Dependency /// - Null-Conditional Checks: Robuste Parameter-Validierung /// - Exception Handling: Try-Catch für alle UI-Operationen /// - Method Delegation: Weiterleitung von Interface-Aufrufen an UI-Code /// /// AVALONIA-INTEGRATION: /// - MainWindow.Content: Zentrale Inhaltsbereich für Page-Wechsel /// - UserControl-basierte Pages: PeriodicTablePage, AboutPage, LandingPage /// - Theme-Management: Avalonia Application Resources /// - Application.Current: Globaler Zugriff auf App-Instance /// /// ZIRKULÄRE ABHÄNGIGKEITEN: /// - Problem: Controller braucht NavigationService, NavigationService braucht Controller /// - Lösung: Zweistufige Initialisierung mit SetDataController() /// - Constructor nimmt MainWindow, SetDataController() löst Zirkularität auf /// public class NavigationService : INavigationService { // ===== PRIVATE FELDER ===== /// /// Referenz zum Hauptfenster der Avalonia-Anwendung /// /// ZWECK: /// - Zentrale Kontrolle über den Hauptinhaltsbereich /// - Zugriff auf MainWindow.Content für Page-Wechsel /// - Window-Eigenschaften (Titel, Größe, etc.) ändern /// /// C# KONZEPTE: /// - Readonly Field: Kann nur im Konstruktor gesetzt werden /// - Reference Type: Hält Verweis auf MainWindow-Objekt /// - Encapsulation: Private field mit controlled access /// private readonly MainWindow _mainWindow; /// /// Referenz zum Data Controller (für Daten-Zugriff) /// /// ZWECK: /// - Navigation-Pages benötigen Zugriff auf Element-Daten /// - Vermeidung direkter Model/Persistence-Zugriffe aus View /// - Konsistente Daten-API für alle UI-Komponenten /// /// ZIRKULÄRE ABHÄNGIGKEIT: /// - Controller erstellt NavigationService /// - NavigationService braucht Controller für Daten /// - Lösung: Nullable field + SetDataController() nach Konstruktion /// private PeriodensystemController? _dataController; // ===== KONSTRUKTOR UND INITIALISIERUNG ===== /// /// Konstruktor mit Dependency Injection des MainWindow /// /// ZWECK: /// - Initialisiert Navigation Service mit UI-Kontext /// - Stellt sicher, dass MainWindow verfügbar ist /// - Validiert kritische Dependencies /// /// C# KONZEPTE: /// - Constructor Dependency Injection: MainWindow als Parameter /// - ArgumentNullException: Robuste Parameter-Validierung /// - Null-Coalescing Throw: mainWindow ?? throw new ArgumentNullException() /// - Self-Documenting Code: Logging der Initialisierung /// /// PARAMETER-VALIDIERUNG: /// - Null-Check mit Exception: Verhindert spätere NullReferenceExceptions /// - Early Fail Principle: Probleme sofort erkennbar /// - Descriptive Exception: nameof() für präzise Fehlermeldung /// /// Das Hauptfenster der Avalonia-Anwendung /// Wenn mainWindow null ist public NavigationService(MainWindow mainWindow) { _mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); Logger.Log("NavigationService initialisiert - implementiert Interface-basierte Navigation"); } /// /// Setzt den Data Controller nach der Konstruktion (löst zirkuläre Abhängigkeit) /// /// ZWECK: /// - Zweistufige Initialisierung zur Auflösung zirkulärer Dependencies /// - Ermöglicht Controller-Access für datenabhängige Navigation /// - Trennt UI-Initialisierung von Daten-Initialisierung /// /// ZIRKULÄRES ABHÄNGIGKEITS-PROBLEM: /// 1. MainWindow erstellt PeriodensystemController /// 2. Controller braucht NavigationService (this) /// 3. NavigationService braucht Controller für Daten /// 4. Lösung: Controller nach NavigationService-Konstruktion setzen /// /// C# KONZEPTE: /// - Two-Phase Construction: Konstruktor + Setter für komplexe Dependencies /// - Null-Conditional Assignment: _dataController wird aus null zu gültigem Objekt /// - Method Chaining möglich: SetDataController() könnte 'this' zurückgeben /// /// Der PeriodensystemController für Datenzugriff /// Wenn dataController null ist public void SetDataController(PeriodensystemController dataController) { _dataController = dataController ?? throw new ArgumentNullException(nameof(dataController)); Logger.Log("DataController in NavigationService gesetzt - zirkuläre Abhängigkeit aufgelöst"); } /// /// Navigation zum Periodensystem (Interface Implementation) /// public void NavigateToPeriodicTable() { try { if (_dataController == null) { Logger.LogError("DataController nicht gesetzt"); return; } var periodicTablePage = new PeriodicTablePage(); periodicTablePage.SetController(_dataController); var mainContent = _mainWindow.FindControl("MainContent"); if (mainContent != null) { mainContent.Content = periodicTablePage; Logger.Log("NavigationService: Navigation zum Periodensystem"); } else { Logger.LogError("MainContent Control nicht gefunden"); } } catch (Exception ex) { Logger.LogException(ex, "NavigateToPeriodicTable"); } } /// /// Navigation zur About-Seite (Interface Implementation) /// public void NavigateToAbout() { try { if (_dataController == null) { Logger.LogError("DataController nicht gesetzt"); return; } var aboutPage = new AboutPage(); aboutPage.SetController(_dataController); var mainContent = _mainWindow.FindControl("MainContent"); if (mainContent != null) { mainContent.Content = aboutPage; Logger.Log("NavigationService: Navigation zu About"); } else { Logger.LogError("MainContent Control nicht gefunden"); } } catch (Exception ex) { Logger.LogException(ex, "NavigateToAbout"); } } /// /// Navigation zur Landing Page (Interface Implementation) /// public void NavigateToLanding() { try { if (_dataController == null) { Logger.LogError("DataController nicht gesetzt"); return; } var landingPage = new LandingPage(); landingPage.SetController(_dataController); var mainContent = _mainWindow.FindControl("MainContent"); if (mainContent != null) { mainContent.Content = landingPage; Logger.Log("NavigationService: Navigation zur Landing Page"); } else { Logger.LogError("MainContent Control nicht gefunden"); } } catch (Exception ex) { Logger.LogException(ex, "NavigateToLanding"); } } /// /// Theme-Wechsel (Interface Implementation) /// public void ToggleTheme() { try { var app = Application.Current; if (app != null) { var currentTheme = app.ActualThemeVariant; var newTheme = currentTheme == Avalonia.Styling.ThemeVariant.Dark ? Avalonia.Styling.ThemeVariant.Light : Avalonia.Styling.ThemeVariant.Dark; app.RequestedThemeVariant = newTheme; // Settings speichern var settings = new AppSettings { LastTheme = newTheme.ToString() ?? "Dark", LastUsed = DateTime.Now, PreferredLanguage = "German" }; DataManager.SaveSettings(settings); Logger.Log($"NavigationService: Theme gewechselt zu {newTheme}"); } } catch (Exception ex) { Logger.LogException(ex, "ToggleTheme"); } } /// /// Export-Bestätigung anzeigen (Interface Implementation) /// public void ShowExportConfirmation() { try { Logger.Log("NavigationService: Export-Bestätigung angezeigt"); // Hier könnte ein Dialog oder Notification angezeigt werden } catch (Exception ex) { Logger.LogException(ex, "ShowExportConfirmation"); } } } }