themes verbessert, inkl about page
This commit is contained in:
parent
abb0d8c06a
commit
961cbd198a
@ -1,17 +1,196 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Project_Periodensystem.Model;
|
||||
using Project_Periodensystem.Persistence;
|
||||
|
||||
namespace Project_Periodensystem.Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Controller für das Periodensystem - verwaltet die Geschäftslogik
|
||||
/// und trennt View von Model gemäß MVC-Pattern
|
||||
/// </summary>
|
||||
public class PeriodensystemController
|
||||
{
|
||||
public ObservableCollection<Element> Elements { get; }
|
||||
// Nullable Field um Warning zu vermeiden
|
||||
private List<Element> _elements = new List<Element>();
|
||||
|
||||
/// <summary>
|
||||
/// Konstruktor - initialisiert den Controller
|
||||
/// </summary>
|
||||
public PeriodensystemController()
|
||||
{
|
||||
// Gießt die statische List<> in eine ObservableCollection
|
||||
Elements = new ObservableCollection<Element>(PeriodicTableData.Elements);
|
||||
LoadElements();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lädt alle Elemente über den Persistence-Layer
|
||||
/// </summary>
|
||||
private void LoadElements()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Verwende die korrekte statische Methode aus PeriodicTableData
|
||||
_elements = PeriodicTableData.Elements.ToList();
|
||||
Logger.Log($"Controller: {_elements.Count} Elemente erfolgreich geladen");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"EXCEPTION in LoadElements: {ex.Message}");
|
||||
_elements = new List<Element>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt alle verfügbaren Elemente zurück
|
||||
/// </summary>
|
||||
/// <returns>Liste aller Elemente</returns>
|
||||
public List<Element> GetAllElements()
|
||||
{
|
||||
return _elements;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sucht ein Element nach Atomnummer
|
||||
/// </summary>
|
||||
/// <param name="atomicNumber">Atomnummer des gesuchten Elements</param>
|
||||
/// <returns>Element oder null wenn nicht gefunden</returns>
|
||||
public Element? GetElementByAtomicNumber(int atomicNumber)
|
||||
{
|
||||
if (atomicNumber <= 0)
|
||||
{
|
||||
Logger.Log($"Ungültige Atomnummer: {atomicNumber}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return _elements.FirstOrDefault(e => e.AtomicNumber == atomicNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sucht ein Element nach Symbol
|
||||
/// </summary>
|
||||
/// <param name="symbol">Symbol des gesuchten Elements</param>
|
||||
/// <returns>Element oder null wenn nicht gefunden</returns>
|
||||
public Element? GetElementBySymbol(string symbol)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(symbol))
|
||||
{
|
||||
Logger.Log("Leeres Symbol übergeben");
|
||||
return null;
|
||||
}
|
||||
|
||||
return _elements.FirstOrDefault(e =>
|
||||
string.Equals(e.Symbol, symbol, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filtert Elemente nach Serie
|
||||
/// </summary>
|
||||
/// <param name="series">Gewünschte Elementserie</param>
|
||||
/// <returns>Liste der Elemente der angegebenen Serie</returns>
|
||||
public List<Element> GetElementsBySeries(string series)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(series))
|
||||
{
|
||||
return new List<Element>();
|
||||
}
|
||||
|
||||
return _elements.Where(e =>
|
||||
string.Equals(e.Series, series, StringComparison.OrdinalIgnoreCase))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validiert Grid-Position eines Elements
|
||||
/// </summary>
|
||||
/// <param name="element">Zu validierendes Element</param>
|
||||
/// <returns>True wenn Position gültig ist</returns>
|
||||
public bool ValidateElementPosition(Element element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
Logger.Log("Null-Element kann nicht validiert werden");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Periodensystem hat 7 Perioden (0-6) und 18 Gruppen (0-17)
|
||||
// Plus Lanthanoid/Actinoid-Reihen bei Zeile 8 und 9
|
||||
bool validRow = element.Row >= 0 && element.Row <= 9;
|
||||
bool validColumn = element.Column >= 0 && element.Column <= 17;
|
||||
|
||||
if (!validRow || !validColumn)
|
||||
{
|
||||
Logger.Log($"Ungültige Position für {element.Symbol}: ({element.Row},{element.Column})");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt alle verfügbaren Element-Serien zurück
|
||||
/// </summary>
|
||||
/// <returns>Liste aller Serien</returns>
|
||||
public List<string> GetAllSeries()
|
||||
{
|
||||
return _elements.Select(e => e.Series)
|
||||
.Distinct()
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
.OrderBy(s => s)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Überprüft ob alle Elemente korrekt geladen wurden
|
||||
/// </summary>
|
||||
/// <returns>True wenn Daten vollständig sind</returns>
|
||||
public bool ValidateData()
|
||||
{
|
||||
if (_elements.Count == 0)
|
||||
{
|
||||
Logger.Log("Keine Elemente geladen");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Überprüfe auf Duplikate bei Atomnummern
|
||||
var duplicateNumbers = _elements.GroupBy(e => e.AtomicNumber)
|
||||
.Where(g => g.Count() > 1)
|
||||
.Select(g => g.Key);
|
||||
|
||||
if (duplicateNumbers.Any())
|
||||
{
|
||||
Logger.Log($"Doppelte Atomnummern gefunden: {string.Join(", ", duplicateNumbers)}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Überprüfe auf leere Symbole
|
||||
var emptySymbols = _elements.Where(e => string.IsNullOrWhiteSpace(e.Symbol));
|
||||
if (emptySymbols.Any())
|
||||
{
|
||||
Logger.Log("Elemente mit leeren Symbolen gefunden");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger.Log($"Datenvalidierung erfolgreich - {_elements.Count} Elemente validiert");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lädt Daten neu (für Refresh-Funktionalität)
|
||||
/// </summary>
|
||||
public void RefreshData()
|
||||
{
|
||||
Logger.Log("Daten werden neu geladen...");
|
||||
LoadElements();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt die Anzahl der geladenen Elemente zurück
|
||||
/// </summary>
|
||||
/// <returns>Anzahl der Elemente</returns>
|
||||
public int GetElementCount()
|
||||
{
|
||||
return _elements.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
136
Project_Periodensystem.Model/Logger.cs
Normal file
136
Project_Periodensystem.Model/Logger.cs
Normal file
@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Project_Periodensystem.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// Einfacher Logger für Debug-Ausgaben und Fehlerprotokollierung
|
||||
/// </summary>
|
||||
public static class Logger
|
||||
{
|
||||
private static readonly string LogFilePath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"Periodensystem", "app.log");
|
||||
|
||||
/// <summary>
|
||||
/// Statischer Initializer - erstellt Log-Verzeichnis
|
||||
/// </summary>
|
||||
static Logger()
|
||||
{
|
||||
try
|
||||
{
|
||||
var logDirectory = Path.GetDirectoryName(LogFilePath);
|
||||
if (logDirectory != null && !Directory.Exists(logDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(logDirectory);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Falls Log-Datei nicht erstellt werden kann, nur Konsole verwenden
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Protokolliert eine Nachricht sowohl in Konsole als auch Datei
|
||||
/// </summary>
|
||||
/// <param name="message">Zu protokollierende Nachricht</param>
|
||||
public static void Log(string message)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
return;
|
||||
|
||||
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
var logEntry = $"[{timestamp}] {message}";
|
||||
|
||||
// Konsolen-Ausgabe (für Debug)
|
||||
Console.WriteLine(logEntry);
|
||||
|
||||
// Datei-Ausgabe (für Persistenz)
|
||||
try
|
||||
{
|
||||
File.AppendAllText(LogFilePath, logEntry + Environment.NewLine);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fehler beim Schreiben ignorieren um App nicht zum Absturz zu bringen
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Protokolliert eine Exception mit Stack-Trace
|
||||
/// </summary>
|
||||
/// <param name="ex">Exception die protokolliert werden soll</param>
|
||||
/// <param name="context">Zusätzlicher Kontext</param>
|
||||
public static void LogException(Exception ex, string context = "")
|
||||
{
|
||||
if (ex == null)
|
||||
{
|
||||
Log("Null-Exception übergeben");
|
||||
return;
|
||||
}
|
||||
|
||||
var message = string.IsNullOrWhiteSpace(context)
|
||||
? $"EXCEPTION: {ex.Message}\nStack: {ex.StackTrace}"
|
||||
: $"EXCEPTION in {context}: {ex.Message}\nStack: {ex.StackTrace}";
|
||||
|
||||
Log(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Protokolliert eine Warnung
|
||||
/// </summary>
|
||||
/// <param name="message">Warnung</param>
|
||||
public static void LogWarning(string message)
|
||||
{
|
||||
Log($"WARNING: {message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Protokolliert einen Fehler
|
||||
/// </summary>
|
||||
/// <param name="message">Fehlermeldung</param>
|
||||
public static void LogError(string message)
|
||||
{
|
||||
Log($"ERROR: {message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Protokolliert Debug-Informationen (nur in Debug-Build)
|
||||
/// </summary>
|
||||
/// <param name="message">Debug-Nachricht</param>
|
||||
[System.Diagnostics.Conditional("DEBUG")]
|
||||
public static void LogDebug(string message)
|
||||
{
|
||||
Log($"DEBUG: {message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Löscht die Log-Datei (für Cleanup)
|
||||
/// </summary>
|
||||
public static void ClearLog()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(LogFilePath))
|
||||
{
|
||||
File.Delete(LogFilePath);
|
||||
Log("Log-Datei gelöscht");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"Fehler beim Löschen der Log-Datei: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt den Pfad zur Log-Datei zurück
|
||||
/// </summary>
|
||||
/// <returns>Vollständiger Pfad zur Log-Datei</returns>
|
||||
public static string GetLogFilePath()
|
||||
{
|
||||
return LogFilePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Project_Periodensystem.Model
|
||||
{
|
||||
public enum AppTheme
|
||||
{
|
||||
Dark,
|
||||
Light,
|
||||
Classic
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
<!-- Datei: Project_Periodensystem.View/AboutPage.axaml -->
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:i="using:Avalonia.Interactivity"
|
||||
x:Class="Project_Periodensystem.View.AboutPage">
|
||||
|
||||
<UserControl.Styles>
|
||||
@ -10,10 +9,11 @@
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontFamily" Value="Arial"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Width" Value="250"/>
|
||||
<Setter Property="Width" Value="200"/>
|
||||
<Setter Property="Height" Value="40"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="CornerRadius" Value="5"/>
|
||||
</Style>
|
||||
<Style Selector="Button:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="DarkRed"/>
|
||||
@ -22,49 +22,142 @@
|
||||
<Setter Property="Background" Value="Red"/>
|
||||
</Style>
|
||||
<Style Selector="Button TextBlock">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="FontFamily" Value="Arial"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
|
||||
<!-- Spezielle Styles für About-Seite -->
|
||||
<Style Selector="TextBlock.Title">
|
||||
<Setter Property="FontSize" Value="36"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="Margin" Value="0,0,0,30"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.Subtitle">
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
<Setter Property="FontWeight" Value="Normal"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="Margin" Value="0,10"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.InfoBold">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="Margin" Value="0,5"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.Info">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="FontWeight" Value="Normal"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="Margin" Value="0,3"/>
|
||||
</Style>
|
||||
|
||||
<!-- Einfache Theme-unabhängige Styles -->
|
||||
<Style Selector="Border.InfoCard">
|
||||
<Setter Property="CornerRadius" Value="10"/>
|
||||
<Setter Property="Padding" Value="30,25"/>
|
||||
<Setter Property="Margin" Value="20"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="BoxShadow" Value="0 4 8 0 #40000000"/>
|
||||
</Style>
|
||||
|
||||
<!-- Theme-Ressourcen verwenden -->
|
||||
<Style Selector="Border.InfoCard">
|
||||
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundChromeMediumBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Rectangle.Divider">
|
||||
<Setter Property="Fill" Value="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"/>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
|
||||
<Grid>
|
||||
<Grid Margin="20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Content -->
|
||||
<StackPanel Grid.Row="0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<TextBlock Text="Author: Oliver Träger"
|
||||
FontSize="24"
|
||||
Margin="0,0,0,20"/>
|
||||
<TextBlock Text="Klasse: ITFS2"
|
||||
FontSize="24"
|
||||
Margin="0,0,0,20"/>
|
||||
</StackPanel>
|
||||
<!-- Titel -->
|
||||
<TextBlock Grid.Row="1"
|
||||
Classes="Title"
|
||||
Text="Periodensystem der Elemente"/>
|
||||
|
||||
<!-- Footer with Buttons -->
|
||||
<Grid Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Margin="20,0,20,20">
|
||||
<!-- Info-Card -->
|
||||
<Border Grid.Row="2"
|
||||
Classes="InfoCard"
|
||||
MaxWidth="600">
|
||||
<StackPanel>
|
||||
<!-- Projekt Info -->
|
||||
<TextBlock Classes="Subtitle"
|
||||
Text="Projekt Information"/>
|
||||
|
||||
<Rectangle Classes="Divider"
|
||||
Height="2"
|
||||
Margin="0,10,0,20"/>
|
||||
|
||||
<TextBlock Classes="InfoBold"
|
||||
Text="Author:"/>
|
||||
<TextBlock Classes="Info"
|
||||
Text="Oliver Träger"/>
|
||||
|
||||
<TextBlock Classes="InfoBold"
|
||||
Text="Klasse:"
|
||||
Margin="0,15,0,0"/>
|
||||
<TextBlock Classes="Info"
|
||||
FontWeight="Bold"
|
||||
Text="ITFS2"/>
|
||||
|
||||
<TextBlock Classes="InfoBold"
|
||||
Text="Semester:"
|
||||
Margin="0,15,0,0"/>
|
||||
<TextBlock Classes="Info"
|
||||
FontWeight="Bold"
|
||||
Text="Sommersemester 2025"/>
|
||||
|
||||
<Rectangle Classes="Divider"
|
||||
Height="2"
|
||||
Margin="0,25,0,15"/>
|
||||
|
||||
<!-- Technische Details -->
|
||||
<TextBlock Classes="Info"
|
||||
Text="Entwickelt mit Avalonia UI Framework"/>
|
||||
<TextBlock Classes="Info"
|
||||
Text="MVC-Architektur mit C# .NET"/>
|
||||
<TextBlock Classes="Info"
|
||||
Text="Interaktives Periodensystem mit 118 Elementen"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Button-Bereich -->
|
||||
<Grid Grid.Row="3"
|
||||
Margin="0,30,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
Click="ThemeButton_Click">
|
||||
<TextBlock Text="Theme wechseln"/>
|
||||
<Button Name="BackButton"
|
||||
Grid.Column="1"
|
||||
Click="BackButton_Click">
|
||||
<TextBlock Text="← Zurück"/>
|
||||
</Button>
|
||||
|
||||
<Button Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
Click="BackButton_Click">
|
||||
<TextBlock Text="Zurück"/>
|
||||
<Button Name="ThemeButton"
|
||||
Grid.Column="3"
|
||||
Click="ThemeButton_Click">
|
||||
<TextBlock Text="Theme wechseln"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@ -8,44 +8,67 @@ using Project_Periodensystem.Model;
|
||||
|
||||
namespace Project_Periodensystem.View
|
||||
{
|
||||
/// <summary>
|
||||
/// Code-Behind für die About-Seite
|
||||
/// </summary>
|
||||
public partial class AboutPage : UserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Konstruktor
|
||||
/// </summary>
|
||||
public AboutPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
|
||||
if (this.GetVisualRoot() is MainWindow mainWindow)
|
||||
{
|
||||
mainWindow.UpdateTheme(MainWindow.CurrentTheme);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zurück-Button - Navigation zur Landing Page
|
||||
/// </summary>
|
||||
private void BackButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (MainWindow.Instance != null)
|
||||
try
|
||||
{
|
||||
MainWindow.Instance.ShowLandingPage();
|
||||
var mainWindow = TopLevel.GetTopLevel(this) as Window;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
var landingPage = new LandingPage();
|
||||
mainWindow.Content = landingPage;
|
||||
Logger.Log("Navigation zurück zur Landing Page");
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Logger.Log($"Fehler bei Navigation zurück: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event-Handler für Theme-Button - VEREINHEITLICHT mit anderen Seiten
|
||||
/// </summary>
|
||||
private void ThemeButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var themes = Enum.GetValues<AppTheme>();
|
||||
MainWindow.CurrentTheme = themes[(Array.IndexOf(themes, MainWindow.CurrentTheme) + 1) % themes.Length];
|
||||
|
||||
if (MainWindow.Instance != null)
|
||||
try
|
||||
{
|
||||
MainWindow.Instance.UpdateTheme(MainWindow.CurrentTheme);
|
||||
// GLEICHE LOGIK wie auf LandingPage und PeriodicTablePage
|
||||
var app = Application.Current;
|
||||
if (app != null)
|
||||
{
|
||||
var currentTheme = app.ActualThemeVariant;
|
||||
app.RequestedThemeVariant = currentTheme == Avalonia.Styling.ThemeVariant.Dark
|
||||
? Avalonia.Styling.ThemeVariant.Light
|
||||
: Avalonia.Styling.ThemeVariant.Dark;
|
||||
|
||||
Logger.Log($"Theme gewechselt zu: {app.RequestedThemeVariant}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"Fehler beim Theme-Wechsel: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Project_Periodensystem.View.App">
|
||||
x:Class="Project_Periodensystem.View.App"
|
||||
RequestedThemeVariant="Dark">
|
||||
|
||||
<Application.Styles>
|
||||
<FluentTheme />
|
||||
</Application.Styles>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Project_Periodensystem.Model;
|
||||
|
||||
namespace Project_Periodensystem.View
|
||||
{
|
||||
@ -15,7 +16,11 @@ namespace Project_Periodensystem.View
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
// Standard Dark Theme beim Start
|
||||
RequestedThemeVariant = Avalonia.Styling.ThemeVariant.Dark;
|
||||
|
||||
desktop.MainWindow = new MainWindow();
|
||||
Logger.Log("Application initialized with Dark theme");
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontFamily" Value="Arial"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Width" Value="250"/>
|
||||
<Setter Property="Height" Value="40"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
@ -17,50 +19,53 @@
|
||||
<Style Selector="Button:pressed /template/ ContentPresenter">
|
||||
<Setter Property="Background" Value="Red"/>
|
||||
</Style>
|
||||
<Style Selector="Button TextBlock">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontFamily" Value="Arial"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Hauptcontent -->
|
||||
<Grid Grid.Row="0">
|
||||
<StackPanel VerticalAlignment="Center"
|
||||
Margin="0,-100,0,0">
|
||||
<TextBlock Text="Willkommen zum"
|
||||
FontSize="36"
|
||||
FontWeight="Light"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,10"/>
|
||||
|
||||
<TextBlock Text="Periodensystem der Elemente!"
|
||||
FontSize="72"
|
||||
<TextBlock Grid.Row="1"
|
||||
Text="Periodensystem der Elemente"
|
||||
FontSize="32"
|
||||
FontWeight="Bold"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,40"/>
|
||||
Margin="0,0,0,50"/>
|
||||
|
||||
<Button Name="StartButton"
|
||||
Width="200"
|
||||
Height="60"
|
||||
<Button Grid.Row="2"
|
||||
Name="PeriodicTableButton"
|
||||
Click="PeriodicTableButton_Click"
|
||||
HorizontalAlignment="Center"
|
||||
Click="StartButton_Click">
|
||||
<TextBlock Text="Start" FontSize="24"/>
|
||||
Margin="0,10">
|
||||
<TextBlock Text="Periodensystem anzeigen"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Theme Button -->
|
||||
<Button Name="ThemeButton"
|
||||
Grid.Row="1"
|
||||
<Button Grid.Row="3"
|
||||
Name="ThemeButton"
|
||||
Click="ThemeButton_Click"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="250"
|
||||
Height="40"
|
||||
Margin="20,0,0,20">
|
||||
<TextBlock Text="Theme wechseln" FontSize="16"/>
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,10">
|
||||
<TextBlock Text="Theme wechseln"/>
|
||||
</Button>
|
||||
|
||||
<Button Grid.Row="4"
|
||||
Name="AboutButton"
|
||||
Click="AboutButton_Click"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,10">
|
||||
<TextBlock Text="About"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@ -1,79 +1,95 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.VisualTree;
|
||||
using Project_Periodensystem.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Project_Periodensystem.View
|
||||
{
|
||||
/// <summary>
|
||||
/// Code-Behind für die Landing Page
|
||||
/// </summary>
|
||||
public partial class LandingPage : UserControl
|
||||
{
|
||||
private readonly Random random = new();
|
||||
private readonly Dictionary<AppTheme, string> themeColors;
|
||||
private DateTime lastClickTime = DateTime.MinValue;
|
||||
private const int DEBOUNCE_MS = 500;
|
||||
|
||||
/// <summary>
|
||||
/// Konstruktor
|
||||
/// </summary>
|
||||
public LandingPage()
|
||||
{
|
||||
Logger.Log($"=== LandingPage wird initialisiert am {DateTime.Now:dd.MM.yyyy HH:mm:ss} ===");
|
||||
InitializeComponent();
|
||||
|
||||
themeColors = new Dictionary<AppTheme, string>
|
||||
{
|
||||
{ AppTheme.Dark, "#5C5144" },
|
||||
{ AppTheme.Light, "#E8DFD8" },
|
||||
{ AppTheme.Classic, "#7B8B6F" }
|
||||
};
|
||||
|
||||
Logger.Log("LandingPage initialisiert");
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
/// <summary>
|
||||
/// Event-Handler für Periodensystem-Button
|
||||
/// </summary>
|
||||
private void PeriodicTableButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void ThemeButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var themes = Enum.GetValues<AppTheme>();
|
||||
MainWindow.CurrentTheme = themes[(Array.IndexOf(themes, MainWindow.CurrentTheme) + 1) % themes.Length];
|
||||
|
||||
if (MainWindow.Instance != null)
|
||||
{
|
||||
MainWindow.Instance.UpdateTheme(MainWindow.CurrentTheme);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
// Add multiple ways to see if this method is called
|
||||
System.Diagnostics.Debug.WriteLine("StartButton_Click CALLED!");
|
||||
Console.WriteLine("StartButton_Click CALLED!");
|
||||
// Remove the MessageBox line - it's not available
|
||||
|
||||
Logger.Log("=== StartButton_Click CALLED ===");
|
||||
|
||||
try
|
||||
{
|
||||
if (MainWindow.Instance != null)
|
||||
var mainWindow = TopLevel.GetTopLevel(this) as Window;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
Logger.Log("Found MainWindow instance - calling ShowPeriodicTable");
|
||||
MainWindow.Instance.ShowPeriodicTable();
|
||||
Logger.Log("ShowPeriodicTable called successfully");
|
||||
var periodicTablePage = new PeriodicTablePage();
|
||||
mainWindow.Content = periodicTablePage;
|
||||
Logger.Log("Navigation zum Periodensystem");
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Logger.Log($"Fehler bei Navigation zum Periodensystem: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event-Handler für About-Button
|
||||
/// </summary>
|
||||
private void AboutButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mainWindow = TopLevel.GetTopLevel(this) as Window;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
var aboutPage = new AboutPage();
|
||||
mainWindow.Content = aboutPage;
|
||||
Logger.Log("Navigation zur About-Seite");
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Logger.Log($"Fehler bei Navigation zu About: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event-Handler für Theme-Button
|
||||
/// </summary>
|
||||
private void ThemeButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Log("Theme-Button geklickt");
|
||||
|
||||
var app = Application.Current;
|
||||
if (app != null)
|
||||
{
|
||||
var currentTheme = app.ActualThemeVariant;
|
||||
Logger.Log($"Aktuelles Theme: {currentTheme}");
|
||||
|
||||
var newTheme = currentTheme == Avalonia.Styling.ThemeVariant.Dark
|
||||
? Avalonia.Styling.ThemeVariant.Light
|
||||
: Avalonia.Styling.ThemeVariant.Dark;
|
||||
|
||||
app.RequestedThemeVariant = newTheme;
|
||||
Logger.Log($"Theme gewechselt zu: {newTheme}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("MainWindow.Instance is null!");
|
||||
Logger.Log("Application.Current ist null!");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Logger.Log($"ERROR in StartButton_Click: {ex.Message}");
|
||||
Logger.Log($"Fehler beim Theme-Wechsel: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,152 +1,65 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.VisualTree;
|
||||
using Avalonia.Threading;
|
||||
using Project_Periodensystem.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static Project_Periodensystem.Model.AppTheme;
|
||||
|
||||
namespace Project_Periodensystem.View
|
||||
{
|
||||
/// <summary>
|
||||
/// Vereinfachtes MainWindow - nur noch Container für Content
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private ContentControl? mainContent;
|
||||
public static AppTheme CurrentTheme { get; set; } = AppTheme.Dark;
|
||||
public static MainWindow? Instance { get; private set; } // Add this line
|
||||
|
||||
public static Dictionary<AppTheme, (string Background, string Foreground)> ThemeColors { get; } = new()
|
||||
{
|
||||
{ AppTheme.Dark, ("#2F2F2F", "#FFFFFF") },
|
||||
{ AppTheme.Light, ("#FFFFFF", "#000000") },
|
||||
{ AppTheme.Classic, ("#E8E8E8", "#000000") }
|
||||
};
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Instance = this; // Set the static reference
|
||||
mainContent = this.FindControl<ContentControl>("MainContent");
|
||||
ShowLandingPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zeigt die Landing Page an
|
||||
/// </summary>
|
||||
public void ShowLandingPage()
|
||||
{
|
||||
mainContent!.Content = new LandingPage();
|
||||
Dispatcher.UIThread.Post(() => UpdateTheme(CurrentTheme), DispatcherPriority.Loaded);
|
||||
if (mainContent != null)
|
||||
{
|
||||
mainContent.Content = new LandingPage();
|
||||
Logger.Log("Landing Page angezeigt");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zeigt das Periodensystem an
|
||||
/// </summary>
|
||||
public void ShowPeriodicTable()
|
||||
{
|
||||
Logger.Log("ShowPeriodicTable called");
|
||||
try
|
||||
{
|
||||
mainContent!.Content = new PeriodicTablePage();
|
||||
if (mainContent != null)
|
||||
{
|
||||
mainContent.Content = new PeriodicTablePage();
|
||||
Logger.Log("PeriodicTablePage created and set");
|
||||
Dispatcher.UIThread.Post(() => UpdateTheme(CurrentTheme), DispatcherPriority.Loaded);
|
||||
Logger.Log("Theme update posted");
|
||||
}
|
||||
catch (Exception ex)
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Logger.Log($"Error in ShowPeriodicTable: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zeigt die About Page an
|
||||
/// </summary>
|
||||
public void ShowAboutPage()
|
||||
{
|
||||
mainContent!.Content = new AboutPage();
|
||||
Dispatcher.UIThread.Post(() => UpdateTheme(CurrentTheme), DispatcherPriority.Loaded);
|
||||
if (mainContent != null)
|
||||
{
|
||||
mainContent.Content = new AboutPage();
|
||||
Logger.Log("About Page angezeigt");
|
||||
}
|
||||
|
||||
public void UpdateTheme(AppTheme theme)
|
||||
{
|
||||
CurrentTheme = theme;
|
||||
if (mainContent?.Content is UserControl control)
|
||||
{
|
||||
var (background, foreground) = ThemeColors[theme];
|
||||
control.Background = new SolidColorBrush(Color.Parse(background));
|
||||
|
||||
// For PeriodicTablePage, use a timer to ensure visual tree is ready
|
||||
if (control is PeriodicTablePage)
|
||||
{
|
||||
// Wait a bit longer for the visual tree to be fully constructed
|
||||
var timer = new System.Timers.Timer(100); // 100ms delay
|
||||
timer.Elapsed += (sender, e) =>
|
||||
{
|
||||
timer.Stop();
|
||||
timer.Dispose();
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var allButtons = control.GetVisualDescendants().OfType<Button>().ToList();
|
||||
Logger.Log($"Timer: Found {allButtons.Count} buttons in PeriodicTablePage");
|
||||
|
||||
foreach (var button in allButtons)
|
||||
{
|
||||
// Skip navigation buttons
|
||||
if ((button.Width == 250 && button.Height == 40) ||
|
||||
(button.Width == 200 && button.Height == 40))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Force white text for element tiles
|
||||
button.Foreground = new SolidColorBrush(Colors.WhiteSmoke);
|
||||
|
||||
// Force white for TextBlocks inside
|
||||
var buttonTextBlocks = button.GetVisualDescendants().OfType<TextBlock>().ToList();
|
||||
foreach (var tb in buttonTextBlocks)
|
||||
{
|
||||
tb.Foreground = new SolidColorBrush(Colors.White);
|
||||
Logger.Log($"Timer: Set element tile text to white: '{tb.Text}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"Timer error: {ex.Message}");
|
||||
}
|
||||
});
|
||||
};
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
// Update regular text colors
|
||||
var textBlocks = control.GetVisualDescendants().OfType<TextBlock>().ToList();
|
||||
foreach (var textBlock in textBlocks)
|
||||
{
|
||||
var parent = textBlock.Parent;
|
||||
if (parent is Button)
|
||||
continue;
|
||||
textBlock.Foreground = new SolidColorBrush(Color.Parse(foreground));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsElementTileButton(Button button)
|
||||
{
|
||||
// Check if this button has element-related content or styling
|
||||
if (button.Content is StackPanel stackPanel)
|
||||
{
|
||||
var textBlocks = stackPanel.Children.OfType<TextBlock>().ToList();
|
||||
if (textBlocks.Count >= 2) // Element tiles typically have symbol and number
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if button content is directly a TextBlock with short text
|
||||
if (button.Content is TextBlock textBlock &&
|
||||
textBlock.Text?.Length <= 3)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,20 +193,33 @@
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Name="ThemeButton"
|
||||
<Button Name="BackButton"
|
||||
Grid.Column="0"
|
||||
Click="BackButton_Click"
|
||||
Width="200"
|
||||
Height="40">
|
||||
<TextBlock Text="← Zurück"
|
||||
FontSize="16"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Button>
|
||||
|
||||
<Button Name="ThemeButton"
|
||||
Grid.Column="2"
|
||||
Click="ThemeButton_Click"
|
||||
Width="250"
|
||||
Height="40">
|
||||
Height="40"
|
||||
HorizontalAlignment="Center">
|
||||
<TextBlock Text="Theme wechseln"
|
||||
FontSize="16"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Button>
|
||||
|
||||
<Button x:Name="AboutButton"
|
||||
Grid.Column="2"
|
||||
Grid.Column="4"
|
||||
Click="AboutButton_Click"
|
||||
Width="200"
|
||||
Height="40">
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using Project_Periodensystem.Model; // ElementModel should be here
|
||||
using Project_Periodensystem.Persistence;
|
||||
using Project_Periodensystem.Controller;
|
||||
using Project_Periodensystem.Model;
|
||||
using Project_Periodensystem.View.Converters;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
@ -12,92 +11,105 @@ using System.Linq;
|
||||
|
||||
namespace Project_Periodensystem.View
|
||||
{
|
||||
/// <summary>
|
||||
/// Code-Behind für das Periodensystem - nur UI-Logik, keine Geschäftslogik
|
||||
/// </summary>
|
||||
public partial class PeriodicTablePage : UserControl
|
||||
{
|
||||
private readonly Grid? periodicGrid;
|
||||
private readonly PeriodensystemController _controller;
|
||||
|
||||
/// <summary>
|
||||
/// Konstruktor - initialisiert UI und Controller
|
||||
/// </summary>
|
||||
public PeriodicTablePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
periodicGrid = this.Find<Grid>("PeriodicGrid");
|
||||
InitializePeriodicTable();
|
||||
|
||||
// Controller initialisieren (MVC-Pattern)
|
||||
_controller = new PeriodensystemController();
|
||||
|
||||
// Grid-Referenz für Element-Buttons
|
||||
periodicGrid = this.FindControl<Grid>("PeriodicGrid");
|
||||
|
||||
// Elemente laden und anzeigen
|
||||
LoadAndDisplayElements();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InitializePeriodicTable()
|
||||
/// <summary>
|
||||
/// Lädt Elemente über Controller und zeigt sie an
|
||||
/// </summary>
|
||||
private void LoadAndDisplayElements()
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Log("Initialisiere PeriodicTable...");
|
||||
// Daten über Controller laden (nicht direkt!)
|
||||
var elements = _controller.GetAllElements();
|
||||
|
||||
// Prüfen ob das Grid gefunden wurde
|
||||
if (periodicGrid == null)
|
||||
if (!elements.Any())
|
||||
{
|
||||
Logger.Log("FEHLER: PeriodicGrid nicht gefunden!");
|
||||
Logger.Log("Keine Elemente vom Controller erhalten");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfen ob Elemente vorhanden sind
|
||||
if (PeriodicTableData.Elements == null || !PeriodicTableData.Elements.Any())
|
||||
// Datenvalidierung über Controller
|
||||
if (!_controller.ValidateData())
|
||||
{
|
||||
Logger.Log("FEHLER: Keine Elemente in PeriodicTableData!");
|
||||
Logger.Log("Datenvalidierung fehlgeschlagen");
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug: Alle Elemente ausgeben
|
||||
Logger.Log($"Anzahl Elemente: {PeriodicTableData.Elements.Count()}");
|
||||
var firstFew = PeriodicTableData.Elements.Take(5);
|
||||
foreach (var el in firstFew)
|
||||
Logger.Log($"Lade {elements.Count} Elemente in das Grid");
|
||||
|
||||
// UI-Update für jedes Element
|
||||
int successCount = 0;
|
||||
foreach (var element in elements)
|
||||
{
|
||||
Logger.Log($"Element: {el.Symbol} - Row: {el.Row}, Column: {el.Column}");
|
||||
}
|
||||
|
||||
// Speziell nach H und He suchen
|
||||
var hydrogen = PeriodicTableData.Elements.FirstOrDefault(e => e.Symbol == "H");
|
||||
var helium = PeriodicTableData.Elements.FirstOrDefault(e => e.Symbol == "He");
|
||||
|
||||
if (hydrogen != null)
|
||||
Logger.Log($"Wasserstoff gefunden: Row {hydrogen.Row}, Column {hydrogen.Column}");
|
||||
else
|
||||
Logger.Log("Wasserstoff NICHT gefunden!");
|
||||
|
||||
if (helium != null)
|
||||
Logger.Log($"Helium gefunden: Row {helium.Row}, Column {helium.Column}");
|
||||
else
|
||||
Logger.Log("Helium NICHT gefunden!");
|
||||
|
||||
// Elemente hinzufügen
|
||||
foreach (var element in PeriodicTableData.Elements)
|
||||
if (_controller.ValidateElementPosition(element))
|
||||
{
|
||||
Logger.Log($"Füge Element hinzu: {element.Symbol} ({element.Row},{element.Column})");
|
||||
CreateElementButton(element);
|
||||
successCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log($"Element {element?.Symbol ?? "NULL"} übersprungen - ungültige Position");
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Log("PeriodicTable wurde initialisiert");
|
||||
Logger.Log($"{successCount} von {elements.Count} Elementen erfolgreich geladen");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"FEHLER beim Initialisieren des PeriodicTable: {ex.Message}");
|
||||
Logger.Log($"StackTrace: {ex.StackTrace}");
|
||||
Logger.Log($"EXCEPTION in LoadAndDisplayElements: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erstellt UI-Button für ein Element (nur View-Logik)
|
||||
/// </summary>
|
||||
/// <param name="element">Element für das der Button erstellt wird</param>
|
||||
private void CreateElementButton(Element element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
Logger.Log("Null-Element kann nicht angezeigt werden");
|
||||
return;
|
||||
}
|
||||
|
||||
// UI-Komponenten erstellen
|
||||
var button = new Button { Classes = { "ElementTile" } };
|
||||
var panel = new StackPanel();
|
||||
|
||||
// Set background color based on element series
|
||||
var backgroundColor = new SeriesToColorConverter().Convert(element.Series, typeof(Brush), null, CultureInfo.InvariantCulture) as Brush;
|
||||
// Hintergrundfarbe über Converter setzen
|
||||
var backgroundColor = new SeriesToColorConverter()
|
||||
.Convert(element.Series, typeof(Brush), null, CultureInfo.InvariantCulture) as Brush;
|
||||
|
||||
if (backgroundColor != null)
|
||||
{
|
||||
button.Background = backgroundColor;
|
||||
}
|
||||
|
||||
// Text-Elemente erstellen
|
||||
var symbolText = new TextBlock
|
||||
{
|
||||
Text = element.Symbol,
|
||||
@ -114,46 +126,96 @@ namespace Project_Periodensystem.View
|
||||
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center
|
||||
};
|
||||
|
||||
// Layout zusammenbauen
|
||||
panel.Children.Add(numberText); // Number on top
|
||||
panel.Children.Add(symbolText); // Symbol below
|
||||
button.Content = panel;
|
||||
|
||||
// FIX: Korrekte Grid-Positionierung ohne Math.Max für Spalten!
|
||||
int gridRow = element.Row; // Row direkt verwenden (0-basiert)
|
||||
int gridColumn = element.Column; // Column direkt verwenden (0-basiert)
|
||||
// Grid-Position setzen (0-basiert)
|
||||
int gridRow = element.Row;
|
||||
int gridColumn = element.Column;
|
||||
|
||||
Logger.Log($"Element {element.Symbol}: Original({element.Row},{element.Column}) -> Grid({gridRow},{gridColumn})");
|
||||
Logger.Log($"Element {element.Symbol}: Grid({gridRow},{gridColumn})");
|
||||
|
||||
Grid.SetRow(button, gridRow);
|
||||
Grid.SetColumn(button, gridColumn);
|
||||
|
||||
// Button zum Grid hinzufügen
|
||||
if (periodicGrid != null)
|
||||
{
|
||||
periodicGrid.Children.Add(button);
|
||||
Logger.Log($"Element {element.Symbol} wurde zum Grid hinzugefügt an Position ({gridRow},{gridColumn})");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("PeriodicGrid ist null - Button kann nicht hinzugefügt werden");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event-Handler für Theme-Button
|
||||
/// </summary>
|
||||
private void ThemeButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var nextTheme = MainWindow.CurrentTheme switch
|
||||
try
|
||||
{
|
||||
AppTheme.Dark => AppTheme.Light,
|
||||
AppTheme.Light => AppTheme.Classic,
|
||||
_ => AppTheme.Dark
|
||||
};
|
||||
// Theme-Wechsel über Application
|
||||
var app = Application.Current;
|
||||
if (app != null)
|
||||
{
|
||||
var currentTheme = app.ActualThemeVariant;
|
||||
app.RequestedThemeVariant = currentTheme == Avalonia.Styling.ThemeVariant.Dark
|
||||
? Avalonia.Styling.ThemeVariant.Light
|
||||
: Avalonia.Styling.ThemeVariant.Dark;
|
||||
|
||||
if (this.Parent is ContentControl content && content.Parent is MainWindow mainWindow)
|
||||
Logger.Log($"Theme gewechselt zu: {app.RequestedThemeVariant}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
mainWindow.UpdateTheme(nextTheme);
|
||||
Logger.Log($"Fehler beim Theme-Wechsel: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event-Handler für About-Button
|
||||
/// </summary>
|
||||
private void AboutButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (this.Parent is ContentControl content && content.Parent is MainWindow mainWindow)
|
||||
try
|
||||
{
|
||||
mainWindow.ShowAboutPage();
|
||||
// Navigation zur About-Seite
|
||||
var mainWindow = TopLevel.GetTopLevel(this) as Window;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
var aboutPage = new AboutPage();
|
||||
mainWindow.Content = aboutPage;
|
||||
Logger.Log("Navigation zur About-Seite");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"Fehler bei Navigation zu About: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event-Handler für Zurück-Button (falls gewünscht)
|
||||
/// </summary>
|
||||
private void BackButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mainWindow = TopLevel.GetTopLevel(this) as Window;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
var landingPage = new LandingPage();
|
||||
mainWindow.Content = landingPage;
|
||||
Logger.Log("Navigation zurück zur Landing Page");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"Fehler bei Navigation zurück: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user