Files
LanMountainDesktop/LanMontainDesktop/Views/Components/ClockWidget.axaml.cs
lincube 2436e43f65 0.2.1
完善了日历组件
2026-03-02 20:02:14 +08:00

130 lines
3.8 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;
using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Threading;
using LanMontainDesktop.Services;
namespace LanMontainDesktop.Views.Components;
public enum ClockDisplayFormat
{
HourMinuteSecond, // HH:mm:ss
HourMinute // HH:mm
}
public partial class ClockWidget : UserControl
{
private readonly DispatcherTimer _timer = new()
{
Interval = TimeSpan.FromSeconds(1)
};
private TimeZoneService? _timeZoneService;
private ClockDisplayFormat _displayFormat = ClockDisplayFormat.HourMinuteSecond;
public ClockWidget()
{
InitializeComponent();
_timer.Tick += OnTimerTick;
AttachedToVisualTree += OnAttachedToVisualTree;
DetachedFromVisualTree += OnDetachedFromVisualTree;
UpdateClock();
}
public ClockDisplayFormat DisplayFormat
{
get => _displayFormat;
set
{
_displayFormat = value;
UpdateClock();
}
}
public void SetDisplayFormat(ClockDisplayFormat format)
{
DisplayFormat = format;
}
public void SetTimeZoneService(TimeZoneService timeZoneService)
{
if (_timeZoneService != null)
{
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
}
_timeZoneService = timeZoneService;
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
UpdateClock();
}
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
UpdateClock();
_timer.Start();
}
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
_timer.Stop();
}
private void OnTimerTick(object? sender, EventArgs e)
{
UpdateClock();
}
private void OnTimeZoneChanged(object? sender, EventArgs e)
{
UpdateClock();
}
private void UpdateClock()
{
var now = _timeZoneService?.GetCurrentTime() ?? DateTime.Now;
MainTimeTextBlock.Text = now.ToString("HH:mm", CultureInfo.CurrentCulture);
SecondsTextBlock.Text = now.ToString("ss", CultureInfo.CurrentCulture);
SecondsTextBlock.IsVisible = _displayFormat == ClockDisplayFormat.HourMinuteSecond;
}
public void ApplyCellSize(double cellSize)
{
// --- Class Island “满盈”风格算法 ---
// 1. 计算组件高度:保持与任务栏核心比例一致 (0.74x)
var targetHeight = Math.Clamp(cellSize * 0.74, 34, 74);
RootBorder.Height = targetHeight;
// 2. 动态圆角:确保始终是完美的胶囊半圆
RootBorder.CornerRadius = new CornerRadius(targetHeight / 2);
RootBorder.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center;
// 3. 核心:满盈字阶 (Filled Typography)
// 使主时间文字占据容器高度的 ~68%,产生饱满的视觉张力
var mainFontSize = targetHeight * 0.68;
MainTimeTextBlock.FontSize = mainFontSize;
MainTimeTextBlock.FontWeight = FontWeight.SemiBold;
// 4. 次级信息:秒数维持 0.7x 比例,并增强透明度呼吸感
SecondsTextBlock.FontSize = mainFontSize * 0.7;
SecondsTextBlock.Opacity = 0.55;
// 5. 视觉占比:占据约 2.2 个单元格的感官宽度 (cellSize * 2 + gaps)
RootBorder.MinWidth = cellSize * 2.2;
// 6. 间距微调
if (MainTimeTextBlock.Parent is StackPanel panel)
{
panel.Spacing = Math.Clamp(cellSize * 0.06, 2, 8);
}
// 确保清除可能存在的固定 Padding由代码控制“紧密感”
RootBorder.Padding = new Thickness(Math.Clamp(cellSize * 0.15, 12, 24), 0);
}
}