navigation geht, grid ist da, farben passen noch nicht

This commit is contained in:
OliverT87 2025-05-27 15:35:07 +02:00
parent 11dccc04cb
commit b856ab9230
8 changed files with 404 additions and 59 deletions

View File

@ -1,3 +1,4 @@
using System;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
@ -17,10 +18,22 @@ namespace Project_Periodensystem.View
private void BackButton_Click(object sender, RoutedEventArgs e) private void BackButton_Click(object sender, RoutedEventArgs e)
{ {
var window = this.GetVisualRoot() as MainWindow; try
if (window != null)
{ {
window.ShowLanding(); var mainWindow = this.FindAncestorOfType<MainWindow>();
if (mainWindow != null)
{
mainWindow.ShowLanding();
}
else
{
Console.WriteLine("MainWindow nicht gefunden!");
}
}
catch (Exception ex)
{
Console.WriteLine($"Fehler in BackButton_Click: {ex.Message}");
Console.WriteLine($"StackTrace: {ex.StackTrace}");
} }
} }
} }

View File

@ -1,22 +1,18 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Project_Periodensystem.View.LandingPage"> x:Class="Project_Periodensystem.View.LandingPage">
<Grid> <Grid>
<TextBlock Text="Welcome to the periodic table of elements!" <Button Name="StartButton"
HorizontalAlignment="Center" Click="StartButton_Click"
VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="32" VerticalAlignment="Center"
Foreground="Red" Width="200"
Margin="0,0,0,60"/> Height="50"
<Button x:Name="StartButton" Background="DarkRed"
Content="Start" Foreground="White">
HorizontalAlignment="Center" <TextBlock Text="Start"
VerticalAlignment="Center" FontSize="24"
Margin="0,60,0,0" HorizontalAlignment="Center"/>
Width="160" </Button>
Height="50" </Grid>
Background="Red"
Foreground="White"
Click="StartButton_Click"/>
</Grid>
</UserControl> </UserControl>

View File

@ -1,15 +1,34 @@
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using System;
namespace Project_Periodensystem.View namespace Project_Periodensystem.View
{ {
public partial class LandingPage : UserControl public partial class LandingPage : UserControl
{ {
private Button? startButton;
private DateTime lastClickTime = DateTime.MinValue;
private const int DEBOUNCE_MS = 500;
public LandingPage() public LandingPage()
{ {
Logger.Log("=== LandingPage wird initialisiert ===");
InitializeComponent(); InitializeComponent();
startButton = this.Find<Button>("StartButton");
if (startButton != null)
{
Logger.Log("StartButton gefunden und wird initialisiert");
startButton.Click += StartButton_Click;
Logger.Log("Click-Handler wurde registriert");
}
else
{
Logger.Log("FEHLER: StartButton nicht gefunden!");
}
} }
private void InitializeComponent() private void InitializeComponent()
@ -17,12 +36,39 @@ namespace Project_Periodensystem.View
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
private void StartButton_Click(object sender, RoutedEventArgs e) private void StartButton_Click(object? sender, RoutedEventArgs e)
{ {
var window = this.GetVisualRoot() as MainWindow; // Stop event propagation
if (window != null) e.Handled = true;
var now = DateTime.Now;
// Prüfe ob genug Zeit seit dem letzten Klick vergangen ist
if ((now - lastClickTime).TotalMilliseconds < DEBOUNCE_MS)
{ {
window.ShowPeriodicTable(); Logger.Log("Click ignoriert (Debounce)");
return;
}
lastClickTime = now;
Logger.Log("StartButton_Click wurde aufgerufen");
try
{
var mainWindow = this.FindAncestorOfType<MainWindow>();
if (mainWindow != null)
{
Logger.Log("MainWindow gefunden, starte Navigation...");
mainWindow.ShowPeriodicTable();
Logger.Log("Navigation ausgeführt");
}
else
{
Logger.Log("FEHLER: MainWindow nicht gefunden!");
}
}
catch (Exception ex)
{
Logger.Log($"FEHLER im Click-Handler: {ex.Message}");
} }
} }
} }

View File

@ -2,8 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Project_Periodensystem.View.MainWindow" x:Class="Project_Periodensystem.View.MainWindow"
Title="Periodensystem" Title="Periodensystem"
Width="900" Height="650"> Width="1024"
Height="768">
<Grid> <Grid>
<ContentControl x:Name="MainContent"/> <ContentControl Name="MainContent"/>
</Grid> </Grid>
</Window> </Window>

View File

@ -1,41 +1,101 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using System;
namespace Project_Periodensystem.View namespace Project_Periodensystem.View
{ {
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
private readonly ContentControl mainContent; private readonly ContentControl? mainContent;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
var content = this.Find<ContentControl>("MainContent"); try
if (content == null) {
throw new System.Exception("MainContent control not found."); Console.WriteLine("MainWindow wird initialisiert...");
var content = this.Find<ContentControl>("MainContent");
mainContent = content; if (content == null)
ShowLanding(); // Show initial page {
Console.WriteLine("FEHLER: MainContent nicht gefunden!");
throw new Exception("MainContent control not found.");
}
mainContent = content;
Console.WriteLine("Navigation zur Landing Page...");
ShowLanding();
}
catch (Exception ex)
{
Console.WriteLine($"FEHLER in MainWindow Constructor: {ex.Message}");
}
}
public void ShowLanding()
{
try
{
Console.WriteLine("ShowLanding wird aufgerufen...");
if (mainContent != null)
{
mainContent.Content = new LandingPage();
}
else
{
Console.WriteLine("FEHLER: mainContent ist null in ShowLanding!");
}
}
catch (Exception ex)
{
Console.WriteLine($"FEHLER in ShowLanding: {ex.Message}");
}
}
public void ShowPeriodicTable()
{
try
{
Logger.Log("ShowPeriodicTable wird aufgerufen...");
if (mainContent != null)
{
var periodicTablePage = new PeriodicTablePage();
mainContent.Content = periodicTablePage;
Logger.Log("PeriodicTablePage wurde geladen");
}
else
{
Logger.Log("FEHLER: mainContent ist null in ShowPeriodicTable!");
}
}
catch (Exception ex)
{
Logger.Log($"FEHLER in ShowPeriodicTable: {ex.Message}");
}
}
public void ShowAbout()
{
try
{
Console.WriteLine("ShowAbout wird aufgerufen...");
if (mainContent != null)
{
mainContent.Content = new AboutPage();
}
else
{
Console.WriteLine("FEHLER: mainContent ist null in ShowAbout!");
}
}
catch (Exception ex)
{
Console.WriteLine($"FEHLER in ShowAbout: {ex.Message}");
}
} }
private void InitializeComponent() private void InitializeComponent()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
public void ShowLanding()
{
mainContent.Content = new LandingPage();
}
public void ShowPeriodicTable()
{
mainContent.Content = new PeriodicTablePage();
}
public void ShowAbout()
{
mainContent.Content = new AboutPage();
}
} }
} }

View File

@ -2,10 +2,67 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Project_Periodensystem.View.PeriodicTablePage"> x:Class="Project_Periodensystem.View.PeriodicTablePage">
<Grid>
<Button Name="AboutButton" <Grid>
Click="AboutButton_Click"> <Grid.RowDefinitions>
About <RowDefinition Height="Auto"/>
</Button> <RowDefinition Height="*"/>
</Grid> <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Header -->
<TextBlock Grid.Row="0"
Text="Periodensystem der Elemente"
FontSize="24"
HorizontalAlignment="Center"
Margin="0,20,0,20"/>
<!-- Periodensystem Grid -->
<Grid Grid.Row="1"
Name="PeriodicGrid"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="30"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
</Grid>
<!-- Footer with About Button -->
<Button Grid.Row="2"
x:Name="AboutButton"
Click="AboutButton_Click"
HorizontalAlignment="Right"
Margin="20">
About
</Button>
</Grid>
</UserControl> </UserControl>

View File

@ -1,15 +1,52 @@
using System;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using Project_Periodensystem.Persistence;
namespace Project_Periodensystem.View namespace Project_Periodensystem.View
{ {
// Converter to map element series to a color
public class SeriesToColorConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Example: Map series string to color
if (value == null) return new SolidColorBrush(Colors.Gray);
switch (value.ToString())
{
case "Alkali Metal":
return new SolidColorBrush(Colors.OrangeRed);
case "Alkaline Earth Metal":
return new SolidColorBrush(Colors.Gold);
case "Transition Metal":
return new SolidColorBrush(Colors.LightBlue);
case "Metalloid":
return new SolidColorBrush(Colors.LightGreen);
case "Nonmetal":
return new SolidColorBrush(Colors.LightGray);
case "Halogen":
return new SolidColorBrush(Colors.Violet);
case "Noble Gas":
return new SolidColorBrush(Colors.Cyan);
default:
return new SolidColorBrush(Colors.Gray);
}
}
}
public partial class PeriodicTablePage : UserControl public partial class PeriodicTablePage : UserControl
{ {
private readonly Grid periodicGrid;
public PeriodicTablePage() public PeriodicTablePage()
{ {
InitializeComponent(); InitializeComponent();
periodicGrid = this.Find<Grid>("PeriodicGrid") ?? throw new Exception("PeriodicGrid not found");
InitializePeriodicTable();
} }
private void InitializeComponent() private void InitializeComponent()
@ -17,12 +54,92 @@ namespace Project_Periodensystem.View
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
private void AboutButton_Click(object sender, RoutedEventArgs e) private void InitializePeriodicTable()
{ {
var window = this.GetVisualRoot() as MainWindow; try
if (window != null)
{ {
window.ShowAbout(); Logger.Log("Initialisiere PeriodicTable...");
foreach (var element in PeriodicTableData.Elements)
{
var border = new Border
{
Width = 58,
Height = 58,
Margin = new Thickness(1),
CornerRadius = new CornerRadius(4),
BorderThickness = new Thickness(1),
BorderBrush = new SolidColorBrush(Colors.Gray)
};
var stackPanel = new StackPanel();
// Symbol
stackPanel.Children.Add(new TextBlock
{
Text = element.Symbol,
FontSize = 20,
Foreground = new SolidColorBrush(Colors.White),
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center
});
// Atomic Number
stackPanel.Children.Add(new TextBlock
{
Text = element.AtomicNumber.ToString(),
FontSize = 12,
Foreground = new SolidColorBrush(Colors.White),
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center
});
border.Child = stackPanel;
// Set background color based on element series
var converter = new SeriesToColorConverter();
border.Background = converter.Convert(element.Series, typeof(IBrush), null!, System.Globalization.CultureInfo.CurrentCulture) as IBrush;
// Position the element - adjust for 0-based indexing
Grid.SetRow(border, Math.Max(0, element.Row - 1));
Grid.SetColumn(border, Math.Max(0, element.Column - 1));
periodicGrid.Children.Add(border);
}
Logger.Log("PeriodicTable wurde initialisiert");
}
catch (Exception ex)
{
var mainWindow = this.FindAncestorOfType<MainWindow>();
if (mainWindow != null)
{
Logger.Log("MainWindow gefunden, navigiere zu About...");
mainWindow.ShowAbout();
}
else
{
Logger.Log("FEHLER: MainWindow nicht gefunden!");
}
Logger.Log($"FEHLER im PeriodicTable-Initialisierer: {ex.Message}");
}
}
private void AboutButton_Click(object? sender, RoutedEventArgs e)
{
try
{
Logger.Log("AboutButton wurde geklickt");
var mainWindow = this.FindAncestorOfType<MainWindow>();
if (mainWindow != null)
{
Logger.Log("Navigation zu About Page");
mainWindow.ShowAbout();
}
else
{
Logger.Log("FEHLER: MainWindow nicht gefunden");
}
}
catch (Exception ex)
{
Logger.Log($"FEHLER im AboutButton_Click: {ex.Message}");
} }
} }
} }

View File

@ -0,0 +1,54 @@
using System;
using System.IO;
namespace Project_Periodensystem.View
{
public static class Logger
{
private static readonly string LogDirectory = AppDomain.CurrentDomain.BaseDirectory;
private static readonly string LogFile = Path.Combine(LogDirectory, "app_log.txt");
public static void Log(string message)
{
try
{
// Ensure directory exists
Directory.CreateDirectory(LogDirectory);
var logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {message}";
// Write immediately to console for direct feedback
Console.WriteLine(logMessage);
// Append to file with direct flush
using (StreamWriter sw = File.AppendText(LogFile))
{
sw.WriteLine(logMessage);
sw.Flush();
}
}
catch (Exception ex)
{
Console.WriteLine($"Logging failed: {ex.Message}");
Console.WriteLine($"Attempted to write to: {LogFile}");
Console.WriteLine($"Original message: {message}");
}
}
static Logger()
{
// Clear log on startup
try
{
if (File.Exists(LogFile))
{
File.Delete(LogFile);
}
Log("=== Logging started ===");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to initialize log file: {ex.Message}");
}
}
}
}