Files
DeskCore/MainWindow.Pages.cs
T
2026-10-04 14:48:53 +00:00

265 lines
12 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 System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace DeskCore;
/// <summary>Einstellungen für Desktop-Seiten, das Aufziehen neuer Boxen und die Tönung der Desktop-Icons.</summary>
public partial class MainWindow
{
public record PageRow(int Index, string Name, string Info, Brush Dot);
private bool _loadingDesktopSettings;
private void LoadDesktopSettings()
{
_loadingDesktopSettings = true;
DrawFencesToggle.IsChecked = S.DrawFences;
PageWheelBox.IsChecked = S.PageWheel;
PageWheelBox.IsEnabled = S.Pages.Count > 1;
var res = Application.Current.Resources;
PageList.ItemsSource = S.Pages.Select((name, i) =>
{
int boxes = S.Fences.Count(f => f.Page == i);
var info = (boxes == 1 ? "1 Box" : $"{boxes} Boxen") + (i == S.CurrentPage ? " · wird gerade angezeigt" : "");
var o = S.PageOptions.GetValueOrDefault(name);
if (o?.Scheduled == true) info += " · " + PageScheduler.Describe(o);
if (string.Equals(S.PageFallback, name, StringComparison.OrdinalIgnoreCase)) info += " · sonst immer";
if (o?.Wallpaper is not null) info += " · eigenes Hintergrundbild";
return new PageRow(i, name, info, (Brush)res[i == S.CurrentPage ? "AccentBrush" : "ControlStrongStrokeBrush"]);
}).ToList();
DesktopTintSwatches.Children.Clear();
void AddSwatch(string? hex, Brush brush, string tip)
{
var rb = new RadioButton
{
Style = (Style)res["SwatchRadio"], GroupName = "desktoptint", Background = brush, ToolTip = tip,
IsChecked = S.DesktopTint == hex,
};
rb.Checked += (_, _) =>
{
if (_loadingDesktopSettings) return;
S.DesktopTint = hex;
S.Save();
DesktopTintStrength.IsEnabled = hex is not null;
DesktopIcons.RefreshCache();
DesktopTint.Refresh(force: true);
};
DesktopTintSwatches.Children.Add(rb);
}
AddSwatch(null, Brushes.Transparent, "Keine Tönung");
foreach (var (name, hex) in CategoryColors.All.Concat([("Weiß", "#F5F5F5")]))
AddSwatch(hex, CategoryColors.Brush(hex)!, name);
DesktopTintStrength.Value = Math.Round(S.DesktopTintStrength * 100);
DesktopTintStrength.IsEnabled = S.DesktopTint is not null;
_loadingDesktopSettings = false;
}
private void DrawFencesToggle_Click(object sender, RoutedEventArgs e)
{
S.DrawFences = DrawFencesToggle.IsChecked == true;
S.Save();
DesktopToggle.Apply();
}
private void PageWheel_Click(object sender, RoutedEventArgs e)
{
S.PageWheel = PageWheelBox.IsChecked == true;
S.Save();
DesktopToggle.Apply();
}
private void DesktopTintStrength_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (_loadingDesktopSettings || !IsLoaded) return;
S.DesktopTintStrength = DesktopTintStrength.Value / 100;
S.Save();
DesktopTint.Refresh(force: true);
}
// ---------- Seiten ----------
private static string? ValidatePageName(string t, int except) =>
t.Trim().Length == 0 ? "Bitte einen Namen eingeben."
: S.Pages.Where((_, i) => i != except).Any(p => string.Equals(p, t.Trim(), StringComparison.OrdinalIgnoreCase))
? "Diesen Namen gibt es schon." : null;
private void AddPage_Click(object sender, RoutedEventArgs e)
{
var name = Dialog.Prompt(this, "Neue Desktop-Seite", "Name der Seite (z. B. „Arbeit“ oder „Freizeit“):",
$"Seite {S.Pages.Count + 1}", "Hinzufügen", t => ValidatePageName(t, -1));
if (name is null) return;
S.Pages.Add(name.Trim());
S.Save();
DesktopToggle.Apply();
LoadDesktopSettings();
ShowToast($"Seite „{name.Trim()}“ hinzugefügt",
"Mit „Anzeigen“ wechselst du hin – neue Boxen landen immer auf der gerade angezeigten Seite.");
}
private void ShowPage_Click(object sender, RoutedEventArgs e)
{
if ((sender as FrameworkElement)?.Tag is int i) FenceManager.SwitchPage(i);
LoadDesktopSettings();
}
private void RenamePage_Click(object sender, RoutedEventArgs e)
{
if ((sender as FrameworkElement)?.Tag is not int i || i >= S.Pages.Count) return;
var name = Dialog.Prompt(this, "Seite umbenennen", "Neuer Name:", S.Pages[i], "Umbenennen", t => ValidatePageName(t, i));
if (name is null) return;
S.RenamePage(i, name.Trim());
S.Save();
LoadDesktopSettings();
}
// ---------- Zeitplan & Hintergrundbild ----------
private void PageSchedule_Click(object sender, RoutedEventArgs e)
{
if ((sender as FrameworkElement)?.Tag is not int i || i >= S.Pages.Count) return;
var page = S.Pages[i];
var o = S.PageOption(page);
var res = Application.Current.Resources;
var panel = new StackPanel();
TextBlock Label(string t, double top = 18) => new()
{
Text = t, Margin = new Thickness(0, top, 0, 8), FontWeight = FontWeights.SemiBold, FontSize = 13,
};
TextBlock Hint(string t) => new()
{
Text = t, FontSize = 12, TextWrapping = TextWrapping.Wrap, Foreground = (Brush)res["TextSecondaryBrush"],
Margin = new Thickness(0, 4, 0, 0),
};
// Zeitplan
var scheduled = new CheckBox { Content = "Diese Seite automatisch anzeigen", IsChecked = o.Scheduled };
panel.Children.Add(scheduled);
var details = new StackPanel { Margin = new Thickness(28, 0, 0, 0) };
details.Children.Add(Label("An diesen Tagen", 12));
var days = new WrapPanel();
string[] dayNames = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];
var dayBoxes = new List<CheckBox>();
for (int d = 0; d < 7; d++)
{
var cb = new CheckBox { Content = dayNames[d], IsChecked = (o.Days & (1 << d)) != 0, Margin = new Thickness(0, 0, 14, 4) };
dayBoxes.Add(cb);
days.Children.Add(cb);
}
details.Children.Add(days);
details.Children.Add(Label("Von – bis"));
var from = new TextBox { Text = o.From, Width = 76, HorizontalContentAlignment = HorizontalAlignment.Center };
var to = new TextBox { Text = o.To, Width = 76, HorizontalContentAlignment = HorizontalAlignment.Center };
details.Children.Add(new StackPanel
{
Orientation = Orientation.Horizontal,
Children =
{
from,
new TextBlock { Text = "bis", Margin = new Thickness(12, 0, 12, 0), VerticalAlignment = VerticalAlignment.Center },
to,
new TextBlock { Text = "Uhr", Margin = new Thickness(12, 0, 0, 0), VerticalAlignment = VerticalAlignment.Center },
},
});
details.Children.Add(Hint("Über Mitternacht geht auch, z. B. 22:00 bis 06:00."));
panel.Children.Add(details);
void UpdateEnabled() => details.IsEnabled = scheduled.IsChecked == true;
scheduled.Click += (_, _) => UpdateEnabled();
UpdateEnabled();
var fallback = new CheckBox
{
Content = "Zu allen anderen Zeiten diese Seite anzeigen", Margin = new Thickness(0, 18, 0, 0),
IsChecked = string.Equals(S.PageFallback, page, StringComparison.OrdinalIgnoreCase),
};
panel.Children.Add(fallback);
panel.Children.Add(Hint("Beispiel: „Arbeit“ Mo–Fr 08:00–17:00 und bei „Freizeit“ diesen Haken setzen."));
// Hintergrundbild
panel.Children.Add(Label("Hintergrundbild", 22));
string? wallpaper = o.Wallpaper;
var wpText = new TextBlock { TextTrimming = TextTrimming.CharacterEllipsis, VerticalAlignment = VerticalAlignment.Center };
var wpRemove = new Button { Content = "Entfernen", Margin = new Thickness(8, 0, 0, 0) };
void UpdateWallpaper()
{
wpText.Text = wallpaper is null ? "Keins – der Hintergrund bleibt, wie er ist" : Path.GetFileName(wallpaper);
wpText.ToolTip = wallpaper;
wpRemove.IsEnabled = wallpaper is not null;
}
var wpPick = new Button { Content = "Bild wählen …" };
wpPick.Click += (_, _) =>
{
var dlg = new Microsoft.Win32.OpenFileDialog
{
Title = $"Hintergrundbild für „{page}“", Filter = "Bilder|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.webp|Alle Dateien|*.*",
};
if (wallpaper is not null) dlg.InitialDirectory = Path.GetDirectoryName(wallpaper);
if (dlg.ShowDialog() == true) { wallpaper = dlg.FileName; UpdateWallpaper(); }
};
wpRemove.Click += (_, _) => { wallpaper = null; UpdateWallpaper(); };
UpdateWallpaper();
var wpRow = new DockPanel();
var wpButtons = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(12, 0, 0, 0), Children = { wpPick, wpRemove } };
DockPanel.SetDock(wpButtons, Dock.Right);
wpRow.Children.Add(wpButtons);
wpRow.Children.Add(wpText);
panel.Children.Add(wpRow);
panel.Children.Add(Hint("Wechselst du auf eine Seite ohne eigenes Bild, kommt dein ursprünglicher Hintergrund zurück."));
string? Validate()
{
if (scheduled.IsChecked != true) return null;
if (!TimeSpan.TryParse(from.Text.Trim(), out var f) || f.TotalHours >= 24 ||
!TimeSpan.TryParse(to.Text.Trim(), out var t) || t.TotalHours >= 24)
return "Bitte die Uhrzeiten so eingeben: 08:00";
if (f == t) return "Start und Ende dürfen nicht gleich sein.";
if (!dayBoxes.Any(b => b.IsChecked == true)) return "Bitte mindestens einen Tag auswählen.";
return null;
}
if (!Dialog.Show(this, $"Seite „{page}“", panel, "Speichern", "Abbrechen", Validate)) return;
o.Scheduled = scheduled.IsChecked == true;
o.Days = dayBoxes.Select((b, d) => b.IsChecked == true ? 1 << d : 0).Sum();
if (TimeSpan.TryParse(from.Text.Trim(), out var ff)) o.From = ff.ToString(@"hh\:mm");
if (TimeSpan.TryParse(to.Text.Trim(), out var tt)) o.To = tt.ToString(@"hh\:mm");
if (fallback.IsChecked == true) S.PageFallback = page;
else if (string.Equals(S.PageFallback, page, StringComparison.OrdinalIgnoreCase)) S.PageFallback = null;
bool wallpaperChanged = !string.Equals(o.Wallpaper, wallpaper, StringComparison.OrdinalIgnoreCase);
o.Wallpaper = wallpaper;
S.Save();
if (wallpaperChanged && i == S.CurrentPage) PageScheduler.ApplyWallpaper(i);
PageScheduler.Reset();
PageScheduler.Tick();
LoadDesktopSettings();
ShowToast($"Seite „{page}“ gespeichert", "");
}
private void DeletePage_Click(object sender, RoutedEventArgs e)
{
if ((sender as FrameworkElement)?.Tag is not int i || i >= S.Pages.Count) return;
if (S.Pages.Count < 2)
{
ShowToast("Die letzte Seite kann nicht gelöscht werden", "", info: true);
return;
}
var name = S.Pages[i];
int boxes = S.Fences.Count(f => f.Page == i);
if (boxes > 0 && !Dialog.Confirm(this, "Seite löschen",
$"Auf „{name}“ liegen {boxes} Box(en). Sie wandern auf die Seite „{S.Pages[i == 0 ? 1 : i - 1]}“.",
"Löschen"))
return;
FenceManager.DeletePage(i);
S.ForgetPage(name);
S.Save();
DesktopToggle.Apply();
Refresh();
LoadDesktopSettings();
ShowToast($"Seite „{name}“ gelöscht", "");
}
}