Milestone, eigentlich fertig!

This commit is contained in:
OliverT87 2025-06-24 13:50:41 +02:00
parent 18099cd77c
commit 8453b0d2c7
8 changed files with 339 additions and 162 deletions

View File

@ -0,0 +1,25 @@
namespace Project_Periodensystem.Model
{
public class ElementModel
{
public string Symbol { get; set; } = "";
public int Number { get; set; }
public int Row { get; set; }
public int Column { get; set; }
public ElementSeries Series { get; set; }
}
public enum ElementSeries
{
Alkali,
AlkalineEarth,
Transition,
PostTransition,
Metalloid,
Nonmetal,
Halogen,
NobleGas,
Lanthanide,
Actinide
}
}

View File

@ -2,13 +2,18 @@
<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"
Background="#5C5144">
x:Class="Project_Periodensystem.View.AboutPage">
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="Black"/>
<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>
<Style Selector="Button:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="DarkRed"/>
@ -16,6 +21,11 @@
<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"/>
</Style>
</UserControl.Styles>
<Grid>
@ -29,47 +39,32 @@
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock Text="Author: Oliver Träger"
FontSize="20"
HorizontalAlignment="Center"
Margin="0,0,0,10"/>
FontSize="24"
Margin="0,0,0,20"/>
<TextBlock Text="Klasse: ITFS2"
FontSize="20"
HorizontalAlignment="Center"
Margin="0,0,0,10"/>
<TextBlock Text="SS2025"
FontSize="20"
Foreground="White"
HorizontalAlignment="Center"
Margin="0,0,0,40"/>
FontSize="24"
Margin="0,0,0,20"/>
</StackPanel>
<!-- Footer with Buttons -->
<Grid Grid.Row="1"
HorizontalAlignment="Stretch"
Margin="20,0,20,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Name="ThemeButton"
Grid.Column="0"
Click="ThemeButton_Click"
Width="250"
Height="40">
<TextBlock Text="Theme wechseln"
FontSize="16"
HorizontalAlignment="Center"/>
<Button Grid.Column="0"
HorizontalAlignment="Left"
Click="ThemeButton_Click">
<TextBlock Text="Theme wechseln"/>
</Button>
<Button x:Name="BackButton"
Grid.Column="2"
Click="BackButton_Click"
Width="200"
Height="40">
<TextBlock Text="Back"
FontSize="16"
HorizontalAlignment="Center"/>
<Button Grid.Column="1"
HorizontalAlignment="Right"
Click="BackButton_Click">
<TextBlock Text="Zurück"/>
</Button>
</Grid>
</Grid>

View File

@ -1,4 +1,5 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
@ -14,6 +15,16 @@ namespace Project_Periodensystem.View
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);
@ -21,24 +32,20 @@ namespace Project_Periodensystem.View
private void BackButton_Click(object? sender, RoutedEventArgs e)
{
if (this.Parent is ContentControl content && content.Parent is MainWindow mainWindow)
if (MainWindow.Instance != null)
{
mainWindow.ShowLandingPage();
MainWindow.Instance.ShowLandingPage();
}
}
private void ThemeButton_Click(object? sender, RoutedEventArgs e)
{
var nextTheme = MainWindow.CurrentTheme switch
var themes = Enum.GetValues<AppTheme>();
MainWindow.CurrentTheme = themes[(Array.IndexOf(themes, MainWindow.CurrentTheme) + 1) % themes.Length];
if (MainWindow.Instance != null)
{
AppTheme.Dark => AppTheme.Light,
AppTheme.Light => AppTheme.Classic,
_ => AppTheme.Dark
};
if (this.Parent is ContentControl content && content.Parent is MainWindow mainWindow)
{
mainWindow.UpdateTheme(nextTheme);
MainWindow.Instance.UpdateTheme(MainWindow.CurrentTheme);
}
}
}

View File

@ -1,11 +1,15 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Project_Periodensystem.View.LandingPage"
Background="#5C5144">
x:Class="Project_Periodensystem.View.LandingPage">
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<Style Selector="Button:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="DarkRed"/>
@ -25,18 +29,24 @@
<Grid Grid.Row="0">
<StackPanel VerticalAlignment="Center"
Margin="0,-100,0,0">
<TextBlock Text="Willkommen zum Periodensystem der Elemente!"
FontSize="36"
HorizontalAlignment="Center"
Margin="0,0,0,20"/>
<Button Name="StartButton"
Click="StartButton_Click"
HorizontalAlignment="Center"
<TextBlock Text="Willkommen zum"
FontSize="36"
FontWeight="Light"
HorizontalAlignment="Center"
Margin="0,0,0,10"/>
<TextBlock Text="Periodensystem der Elemente!"
FontSize="72"
FontWeight="Bold"
HorizontalAlignment="Center"
Margin="0,0,0,40"/>
<Button Name="StartButton"
Width="200"
Height="50">
<TextBlock Text="Start"
FontSize="24"
HorizontalAlignment="Center"/>
Height="60"
HorizontalAlignment="Center"
Click="StartButton_Click">
<TextBlock Text="Start" FontSize="24"/>
</Button>
</StackPanel>
</Grid>
@ -50,9 +60,7 @@
Width="250"
Height="40"
Margin="20,0,0,20">
<TextBlock Text="Theme wechseln"
FontSize="16"
HorizontalAlignment="Center"/>
<TextBlock Text="Theme wechseln" FontSize="16"/>
</Button>
</Grid>
</UserControl>

View File

@ -1,8 +1,10 @@
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;
@ -13,8 +15,6 @@ namespace Project_Periodensystem.View
{
private readonly Random random = new();
private readonly Dictionary<AppTheme, string> themeColors;
private AppTheme currentTheme;
private Button? startButton;
private DateTime lastClickTime = DateTime.MinValue;
private const int DEBOUNCE_MS = 500;
@ -30,19 +30,7 @@ namespace Project_Periodensystem.View
{ AppTheme.Classic, "#7B8B6F" }
};
SetRandomTheme();
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!");
}
Logger.Log("LandingPage initialisiert");
}
private void InitializeComponent()
@ -50,51 +38,42 @@ namespace Project_Periodensystem.View
AvaloniaXamlLoader.Load(this);
}
private void SetRandomTheme()
{
var themes = Enum.GetValues<AppTheme>();
currentTheme = themes[random.Next(themes.Length)];
this.Background = new SolidColorBrush(Color.Parse(themeColors[currentTheme]));
Logger.Log($"Theme gewählt: {currentTheme}");
}
private void ThemeButton_Click(object? sender, RoutedEventArgs e)
{
var themes = Enum.GetValues<AppTheme>();
currentTheme = themes[(Array.IndexOf(themes, currentTheme) + 1) % themes.Length];
MainWindow.CurrentTheme = themes[(Array.IndexOf(themes, MainWindow.CurrentTheme) + 1) % themes.Length];
if (this.Parent is ContentControl content && content.Parent is MainWindow mainWindow)
if (MainWindow.Instance != null)
{
mainWindow.UpdateTheme(currentTheme);
MainWindow.Instance.UpdateTheme(MainWindow.CurrentTheme);
}
}
private void StartButton_Click(object? sender, RoutedEventArgs e)
{
// Stop event propagation
e.Handled = true;
var now = DateTime.Now;
// Prüfe ob genug Zeit seit dem letzten Klick vergangen ist
if ((now - lastClickTime).TotalMilliseconds < DEBOUNCE_MS)
{
Logger.Log("Click ignoriert (Debounce)");
return;
}
lastClickTime = now;
Logger.Log("StartButton_Click wurde aufgerufen");
// 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 (this.Parent is ContentControl content && content.Parent is MainWindow mainWindow)
if (MainWindow.Instance != null)
{
mainWindow.ShowPeriodicTable();
Logger.Log("Found MainWindow instance - calling ShowPeriodicTable");
MainWindow.Instance.ShowPeriodicTable();
Logger.Log("ShowPeriodicTable called successfully");
}
else
{
Logger.Log("MainWindow.Instance is null!");
}
}
catch (Exception ex)
{
Logger.Log($"FEHLER im Click-Handler: {ex.Message}");
Logger.Log($"ERROR in StartButton_Click: {ex.Message}");
}
}
}

View File

@ -2,6 +2,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.VisualTree;
using Avalonia.Threading;
using Project_Periodensystem.Model;
using System;
using System.Collections.Generic;
@ -14,17 +15,19 @@ namespace Project_Periodensystem.View
{
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") }, // Dunkles Anthrazit & Weiß
{ AppTheme.Light, ("#FFFFFF", "#000000") }, // Weiß & Schwarz
{ AppTheme.Classic, ("#E8E8E8", "#000000") } // Stylisches Grau & Schwarz
{ 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();
}
@ -32,19 +35,29 @@ namespace Project_Periodensystem.View
public void ShowLandingPage()
{
mainContent!.Content = new LandingPage();
UpdateTheme(AppTheme.Dark);
Dispatcher.UIThread.Post(() => UpdateTheme(CurrentTheme), DispatcherPriority.Loaded);
}
public void ShowPeriodicTable()
{
mainContent!.Content = new PeriodicTablePage();
UpdateTheme(AppTheme.Dark);
Logger.Log("ShowPeriodicTable called");
try
{
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)
{
Logger.Log($"Error in ShowPeriodicTable: {ex.Message}");
}
}
public void ShowAboutPage()
{
mainContent!.Content = new AboutPage();
UpdateTheme(AppTheme.Dark);
Dispatcher.UIThread.Post(() => UpdateTheme(CurrentTheme), DispatcherPriority.Loaded);
}
public void UpdateTheme(AppTheme theme)
@ -55,20 +68,85 @@ namespace Project_Periodensystem.View
var (background, foreground) = ThemeColors[theme];
control.Background = new SolidColorBrush(Color.Parse(background));
// Update text colors for all direct TextBlocks
foreach (var textBlock in control.GetVisualDescendants().OfType<TextBlock>())
// 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 == null ||
parent is Button ||
parent?.GetType().ToString().Contains("ElementTile") == true)
{
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;
}
}
}

View File

@ -2,13 +2,18 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:Project_Periodensystem.View.Converters"
x:Class="Project_Periodensystem.View.PeriodicTablePage"
Background="#5C5144">
x:Class="Project_Periodensystem.View.PeriodicTablePage">
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="Black"/>
<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>
<Style Selector="Button:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="DarkRed"/>
@ -16,6 +21,55 @@
<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>
<!-- Separate styles for navigation buttons -->
<Style Selector="Button.NavigationButton">
<Setter Property="Width" Value="250"/>
<Setter Property="Height" Value="40"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<!-- Element tile specific styles - ALWAYS white text -->
<Style Selector="Button.ElementTile">
<Setter Property="Width" Value="55"/>
<Setter Property="Height" Value="55"/>
<Setter Property="Margin" Value="2"/>
</Style>
<!-- Specific styles for element tile content -->
<Style Selector="Button.ElementTile > StackPanel > TextBlock">
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
<!-- Different sizes for symbol and number -->
<Style Selector="Button.ElementTile > StackPanel > TextBlock.Symbol">
<Setter Property="FontSize" Value="16"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style Selector="Button.ElementTile > StackPanel > TextBlock.Number">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<!-- Force white text for element tiles and their content -->
<Style Selector="Grid#PeriodicGrid Button">
<Setter Property="Foreground" Value="White"/>
</Style>
<Style Selector="Grid#PeriodicGrid Button TextBlock">
<Setter Property="Foreground" Value="White"/>
</Style>
<Style Selector="Grid#PeriodicGrid Button > StackPanel > TextBlock">
<Setter Property="Foreground" Value="White"/>
</Style>
</UserControl.Styles>
<UserControl.Resources>
@ -110,4 +164,5 @@
</Button>
</Grid>
</Grid>
</UserControl>
</UserControl>

View File

@ -3,7 +3,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Project_Periodensystem.Model;
using Project_Periodensystem.Model; // ElementModel should be here
using Project_Periodensystem.Persistence;
using Project_Periodensystem.View.Converters;
using System;
@ -48,51 +48,33 @@ namespace Project_Periodensystem.View
return;
}
var converter = new SeriesToColorConverter();
// Debug: Alle Elemente ausgeben
Logger.Log($"Anzahl Elemente: {PeriodicTableData.Elements.Count()}");
var firstFew = PeriodicTableData.Elements.Take(5);
foreach (var el in firstFew)
{
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)
{
Logger.Log($"Füge Element hinzu: {element.Symbol} ({element.Row},{element.Column})");
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),
Background = converter.Convert(element.Series, typeof(IBrush), null!, CultureInfo.CurrentCulture) as IBrush // Hier wird die Farbe gesetzt
};
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;
// Position setzen
Grid.SetRow(border, Math.Max(0, element.Row - 1));
Grid.SetColumn(border, Math.Max(0, element.Column - 1));
periodicGrid.Children.Add(border);
Logger.Log($"Element {element.Symbol} wurde hinzugefügt");
CreateElementButton(element);
}
Logger.Log("PeriodicTable wurde initialisiert");
@ -104,6 +86,54 @@ namespace Project_Periodensystem.View
}
}
private void CreateElementButton(Element element)
{
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;
if (backgroundColor != null)
{
button.Background = backgroundColor;
}
var symbolText = new TextBlock
{
Text = element.Symbol,
Classes = { "Symbol" },
Foreground = new SolidColorBrush(Colors.White),
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center
};
var numberText = new TextBlock
{
Text = element.AtomicNumber.ToString(),
Classes = { "Number" },
Foreground = new SolidColorBrush(Colors.White),
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center
};
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)
Logger.Log($"Element {element.Symbol}: Original({element.Row},{element.Column}) -> Grid({gridRow},{gridColumn})");
Grid.SetRow(button, gridRow);
Grid.SetColumn(button, gridColumn);
if (periodicGrid != null)
{
periodicGrid.Children.Add(button);
Logger.Log($"Element {element.Symbol} wurde zum Grid hinzugefügt an Position ({gridRow},{gridColumn})");
}
}
private void ThemeButton_Click(object? sender, RoutedEventArgs e)
{
var nextTheme = MainWindow.CurrentTheme switch