Files
LehrerApp/LehrerApp.Desktop/Views/Groups/AttendanceHomeworkQuickInputDialog.axaml.cs
T

226 lines
8.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using LehrerApp.Core.Models;
using LehrerApp.Desktop.ViewModels.Groups;
namespace LehrerApp.Desktop.Views.Groups;
public partial class AttendanceHomeworkQuickInputDialog : Window
{
public AttendanceHomeworkQuickInputDialog()
{
InitializeComponent();
BuildColumns();
}
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
StatusGrid.Focus();
if (ViewModel?.SelectedRow is { } row)
StatusGrid.ScrollIntoView(row, null);
}
private void BuildColumns()
{
StatusGrid.Columns.Add(new DataGridTextColumn
{
Header = "Schüler",
Binding = new Binding(nameof(ParticipationStudentRow.Name)),
Width = new DataGridLength(1, DataGridLengthUnitType.Star),
});
StatusGrid.Columns.Add(new DataGridTemplateColumn
{
Header = "Anwesenheit",
Width = new DataGridLength(210, DataGridLengthUnitType.Pixel),
CellTemplate = BuildAttendanceTemplate(),
});
StatusGrid.Columns.Add(new DataGridTemplateColumn
{
Header = "Hausaufgaben",
Width = new DataGridLength(270, DataGridLengthUnitType.Pixel),
CellTemplate = BuildHomeworkTemplate(),
});
}
private IDataTemplate BuildAttendanceTemplate() =>
new FuncDataTemplate<ParticipationStudentRow>((row, _) =>
{
if (row is null) return new TextBlock();
var button = StatusButton(185);
var flyout = new MenuFlyout { Placement = PlacementMode.BottomEdgeAlignedLeft };
AddAttendanceItem(flyout, row, "· Nicht kontrolliert", null);
AddAttendanceItem(flyout, row, "✓ Anwesend", AttendanceStatus.Present);
AddAttendanceItem(flyout, row, "? Entschuldigung offen", AttendanceStatus.ExcusePending);
AddAttendanceItem(flyout, row, "⊘ Krank, entschuldigt", AttendanceStatus.Excused);
AddAttendanceItem(flyout, row, "! Unentschuldigt", AttendanceStatus.Unexcused);
AddAttendanceItem(flyout, row, "✕ Geschwänzt", AttendanceStatus.Truant);
AddAttendanceItem(flyout, row, "◇ Andere Schulveranstaltung", AttendanceStatus.OtherSchoolEvent);
button.Flyout = flyout;
void Refresh()
{
UpdateButton(button,
string.IsNullOrEmpty(row.AttendanceLabel) ? "·" : row.AttendanceLabel,
row.AttendanceTooltip, AttendanceDisplay.Color(row.Attendance));
}
Refresh();
row.PropertyChanged += (_, args) =>
{
if (args.PropertyName == nameof(ParticipationStudentRow.AttendanceLabel)) Refresh();
};
return Center(button);
});
private IDataTemplate BuildHomeworkTemplate() =>
new FuncDataTemplate<ParticipationStudentRow>((row, _) =>
{
if (row is null) return new TextBlock();
var button = StatusButton(245);
var flyout = new MenuFlyout { Placement = PlacementMode.BottomEdgeAlignedLeft };
AddHomeworkItem(flyout, row, "· Keine Hausaufgabe", null);
AddHomeworkItem(flyout, row, "✓ Gemacht", HomeworkStatus.Completed);
AddHomeworkItem(flyout, row, "◐ Teilweise, Rest offen", HomeworkStatus.PartiallyCompleted);
AddHomeworkItem(flyout, row, "◕ Rest nachgereicht", HomeworkStatus.PartialSubmittedLate);
AddHomeworkItem(flyout, row, "◒ Rest nicht nachgereicht", HomeworkStatus.PartialMissingOverdue);
AddHomeworkItem(flyout, row, "! Nicht gemacht, Nachreichen offen", HomeworkStatus.MissingOpen);
AddHomeworkItem(flyout, row, "✕ Nicht mehr nachgereicht", HomeworkStatus.MissingOverdue);
AddHomeworkItem(flyout, row, "↺ Nachgereicht", HomeworkStatus.SubmittedLate);
button.Flyout = flyout;
void Refresh() => UpdateButton(button, row.HomeworkSymbol, row.HomeworkTooltip,
HomeworkDisplay.Color(row.Homework));
Refresh();
row.PropertyChanged += (_, args) =>
{
if (args.PropertyName == nameof(ParticipationStudentRow.HomeworkSymbol)) Refresh();
};
return Center(button);
});
private void AddAttendanceItem(MenuFlyout flyout, ParticipationStudentRow row,
string header, AttendanceStatus? status)
{
var item = new MenuItem { Header = header };
item.Click += (_, _) => ViewModel?.ApplyAttendance(row, status);
flyout.Items.Add(item);
}
private void AddHomeworkItem(MenuFlyout flyout, ParticipationStudentRow row,
string header, HomeworkStatus? status)
{
var item = new MenuItem { Header = header };
item.Click += (_, _) => ViewModel?.ApplyHomework(row, status);
flyout.Items.Add(item);
}
private static Button StatusButton(double width) => new()
{
Width = width,
Height = 29,
Padding = new Thickness(8, 2),
FontSize = 12,
HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center,
};
private static Control Center(Control child) => new Grid
{
Margin = new Thickness(0, 2),
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
Children = { child },
};
private static void UpdateButton(Button button, string symbol, string tooltip, string color)
{
button.Content = $"{symbol} {tooltip}";
ToolTip.SetTip(button, tooltip + " klicken, um Status auszuwählen");
if (Color.TryParse(color, out var parsed))
{
button.Background = new SolidColorBrush(parsed);
button.Foreground = Brushes.White;
button.Opacity = 1;
}
else
{
button.ClearValue(Button.BackgroundProperty);
button.ClearValue(Button.ForegroundProperty);
button.Opacity = 0.48;
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
var vm = ViewModel;
var row = vm?.SelectedRow;
if (vm is null || row is null) { base.OnKeyDown(e); return; }
if (e.KeyModifiers.HasFlag(KeyModifiers.Alt))
{
var homework = e.Key switch
{
Key.D0 or Key.NumPad0 => (HomeworkStatus?)null,
Key.M => HomeworkStatus.Completed,
Key.T => HomeworkStatus.PartiallyCompleted,
Key.R => HomeworkStatus.PartialSubmittedLate,
Key.X => HomeworkStatus.PartialMissingOverdue,
Key.O => HomeworkStatus.MissingOpen,
Key.F => HomeworkStatus.MissingOverdue,
Key.S => HomeworkStatus.SubmittedLate,
_ => null,
};
var recognized = e.Key is Key.D0 or Key.NumPad0 or Key.M or Key.T or Key.R or Key.X or Key.O or Key.F or Key.S;
if (recognized)
{
vm.ApplyHomework(row, homework);
BringSelectionIntoView();
e.Handled = true;
return;
}
}
AttendanceStatus? attendance = e.Key switch
{
Key.A => AttendanceStatus.Present,
Key.K => AttendanceStatus.ExcusePending,
Key.E => AttendanceStatus.Excused,
Key.U => AttendanceStatus.Unexcused,
Key.G => AttendanceStatus.Truant,
Key.V => AttendanceStatus.OtherSchoolEvent,
_ => null,
};
var attendanceRecognized = e.Key is Key.D0 or Key.NumPad0 or Key.A or Key.K or Key.E or Key.U or Key.G or Key.V;
if (attendanceRecognized)
{
vm.ApplyAttendance(row, attendance);
BringSelectionIntoView();
e.Handled = true;
return;
}
switch (e.Key)
{
case Key.Up: vm.MoveSelection(-1); BringSelectionIntoView(); e.Handled = true; break;
case Key.Down or Key.Enter: vm.MoveSelection(1); BringSelectionIntoView(); e.Handled = true; break;
case Key.Escape: Close(); e.Handled = true; break;
default: base.OnKeyDown(e); break;
}
}
private AttendanceHomeworkQuickInputViewModel? ViewModel =>
DataContext as AttendanceHomeworkQuickInputViewModel;
private void BringSelectionIntoView()
{
if (ViewModel?.SelectedRow is { } row)
StatusGrid.ScrollIntoView(row, null);
}
private void OnClose(object? sender, RoutedEventArgs e) => Close();
}