mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-23 09:54:25 +08:00
0.2.1
完善了日历组件
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
@@ -15,8 +15,15 @@ public partial class DateWidget : UserControl
|
||||
{
|
||||
Interval = TimeSpan.FromMinutes(1)
|
||||
};
|
||||
private static readonly LunarCalendarService LunarCalendarService = new();
|
||||
|
||||
private static readonly string[] ZhWeekdayHeaders = ["日", "一", "二", "三", "四", "五", "六"];
|
||||
private static readonly string[] EnWeekdayHeaders = ["S", "M", "T", "W", "T", "F", "S"];
|
||||
|
||||
private TimeZoneService? _timeZoneService;
|
||||
private double _currentCellSize = 64;
|
||||
private double _calendarDayFontSize = 14;
|
||||
private double _calendarTodayDotSize = 28;
|
||||
|
||||
public DateWidget()
|
||||
{
|
||||
@@ -25,12 +32,10 @@ public partial class DateWidget : UserControl
|
||||
_timer.Tick += OnTimerTick;
|
||||
AttachedToVisualTree += OnAttachedToVisualTree;
|
||||
DetachedFromVisualTree += OnDetachedFromVisualTree;
|
||||
SizeChanged += OnSizeChanged;
|
||||
UpdateDate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置时区服务
|
||||
/// </summary>
|
||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||
{
|
||||
if (_timeZoneService != null)
|
||||
@@ -54,6 +59,11 @@ public partial class DateWidget : UserControl
|
||||
_timer.Stop();
|
||||
}
|
||||
|
||||
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
|
||||
{
|
||||
ApplyCellSize(_currentCellSize);
|
||||
}
|
||||
|
||||
private void OnTimerTick(object? sender, EventArgs e)
|
||||
{
|
||||
UpdateDate();
|
||||
@@ -68,30 +78,75 @@ public partial class DateWidget : UserControl
|
||||
{
|
||||
var now = _timeZoneService?.GetCurrentTime() ?? DateTime.Now;
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
|
||||
// 右侧:今日详情
|
||||
TodayDayTextBlock.Text = now.Day.ToString();
|
||||
TodayWeekdayTextBlock.Text = now.ToString("dddd", culture);
|
||||
|
||||
// 左侧:月历
|
||||
CalendarMonthYearTextBlock.Text = now.ToString("yyyy年M月", culture);
|
||||
|
||||
// 生成月历
|
||||
var isZh = culture.TwoLetterISOLanguageName.Equals("zh", StringComparison.OrdinalIgnoreCase);
|
||||
var lunar = LunarCalendarService.GetLunarInfo(now);
|
||||
|
||||
GregorianHeadlineTextBlock.Text = isZh
|
||||
? $"{now.Month}月{now.Day}日 {ToChineseWeekday(now.DayOfWeek)}"
|
||||
: now.ToString("MMM d ddd", culture);
|
||||
|
||||
if (isZh)
|
||||
{
|
||||
LunarDateTextBlock.Text = $"农历 {lunar.LunarDateZh}";
|
||||
LunarMetaTextBlock.Text = $"{lunar.GanzhiYearZh}年({lunar.ZodiacZh}年)";
|
||||
YiLabelTextBlock.Text = "宜";
|
||||
JiLabelTextBlock.Text = "忌";
|
||||
YiItemsTextBlock.Text = "祭祀 祈福 出行 会友";
|
||||
JiItemsTextBlock.Text = "动土 诉讼 远航 争执";
|
||||
}
|
||||
else
|
||||
{
|
||||
LunarDateTextBlock.Text = $"Lunar {lunar.LunarDateEn}";
|
||||
LunarMetaTextBlock.Text = $"Ganzhi year: {lunar.GanzhiYearEn} ({lunar.ZodiacEn})";
|
||||
YiLabelTextBlock.Text = "Do";
|
||||
JiLabelTextBlock.Text = "Avoid";
|
||||
YiItemsTextBlock.Text = "Worship Blessing Travel Meet";
|
||||
JiItemsTextBlock.Text = "Groundwork Lawsuit Voyage Dispute";
|
||||
}
|
||||
|
||||
UpdateWeekdayHeaders(isZh);
|
||||
GenerateCalendar(now);
|
||||
}
|
||||
|
||||
private static string ToChineseWeekday(DayOfWeek dayOfWeek)
|
||||
{
|
||||
return dayOfWeek switch
|
||||
{
|
||||
DayOfWeek.Sunday => "周日",
|
||||
DayOfWeek.Monday => "周一",
|
||||
DayOfWeek.Tuesday => "周二",
|
||||
DayOfWeek.Wednesday => "周三",
|
||||
DayOfWeek.Thursday => "周四",
|
||||
DayOfWeek.Friday => "周五",
|
||||
_ => "周六"
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateWeekdayHeaders(bool isZh)
|
||||
{
|
||||
var headers = isZh ? ZhWeekdayHeaders : EnWeekdayHeaders;
|
||||
WeekdayText0.Text = headers[0];
|
||||
WeekdayText1.Text = headers[1];
|
||||
WeekdayText2.Text = headers[2];
|
||||
WeekdayText3.Text = headers[3];
|
||||
WeekdayText4.Text = headers[4];
|
||||
WeekdayText5.Text = headers[5];
|
||||
WeekdayText6.Text = headers[6];
|
||||
}
|
||||
|
||||
private void GenerateCalendar(DateTime currentDate)
|
||||
{
|
||||
// 清空之前的日期(保留星期标题)
|
||||
var childrenToRemove = new List<Control>();
|
||||
var removeList = new List<Control>();
|
||||
foreach (var child in CalendarGrid.Children)
|
||||
{
|
||||
if (child is TextBlock tb && tb.Tag?.ToString() == "day")
|
||||
if (child is Control control && control.Tag is string tag &&
|
||||
(tag == "day" || tag == "today-dot"))
|
||||
{
|
||||
childrenToRemove.Add(tb);
|
||||
removeList.Add(control);
|
||||
}
|
||||
}
|
||||
foreach (var child in childrenToRemove)
|
||||
|
||||
foreach (var child in removeList)
|
||||
{
|
||||
CalendarGrid.Children.Remove(child);
|
||||
}
|
||||
@@ -99,66 +154,62 @@ public partial class DateWidget : UserControl
|
||||
var year = currentDate.Year;
|
||||
var month = currentDate.Month;
|
||||
var today = currentDate.Day;
|
||||
|
||||
// 获取该月第一天
|
||||
|
||||
var firstDayOfMonth = new DateTime(year, month, 1);
|
||||
var daysInMonth = DateTime.DaysInMonth(year, month);
|
||||
var startDayOfWeek = (int)firstDayOfMonth.DayOfWeek; // 0 = Sunday
|
||||
var startDayOfWeek = (int)firstDayOfMonth.DayOfWeek;
|
||||
|
||||
// 生成日期
|
||||
for (int day = 1; day <= daysInMonth; day++)
|
||||
for (var day = 1; day <= daysInMonth; day++)
|
||||
{
|
||||
var row = ((day + startDayOfWeek - 1) / 7) + 1; // +1 because row 0 is weekday headers
|
||||
var row = (day + startDayOfWeek - 1) / 7;
|
||||
var col = (day + startDayOfWeek - 1) % 7;
|
||||
|
||||
if (row > 5) continue; // 最多显示6行
|
||||
if (row > 4)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var dayText = new TextBlock
|
||||
{
|
||||
Text = day.ToString(),
|
||||
Text = day.ToString(CultureInfo.CurrentCulture),
|
||||
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
||||
FontSize = 10,
|
||||
FontSize = _calendarDayFontSize,
|
||||
FontWeight = FontWeight.SemiBold,
|
||||
Tag = "day"
|
||||
};
|
||||
|
||||
// 今天高亮
|
||||
if (day == today)
|
||||
{
|
||||
// 使用主题色高亮今天
|
||||
var accentBrush = this.TryFindResource("AdaptiveAccentBrush", out var accent)
|
||||
? accent as IBrush
|
||||
var accentBrush = this.TryFindResource("AdaptiveAccentBrush", out var accent)
|
||||
? accent as IBrush
|
||||
: Brushes.Blue;
|
||||
var onAccentBrush = this.TryFindResource("AdaptiveOnAccentBrush", out var onAccent)
|
||||
? onAccent as IBrush
|
||||
var onAccentBrush = this.TryFindResource("AdaptiveOnAccentBrush", out var onAccent)
|
||||
? onAccent as IBrush
|
||||
: Brushes.White;
|
||||
|
||||
|
||||
dayText.Foreground = onAccentBrush;
|
||||
dayText.FontWeight = FontWeight.Bold;
|
||||
dayText.Background = new SolidColorBrush(Colors.Transparent);
|
||||
|
||||
// 添加背景圆
|
||||
var highlight = new Border
|
||||
var dot = new Border
|
||||
{
|
||||
Width = _calendarTodayDotSize,
|
||||
Height = _calendarTodayDotSize,
|
||||
CornerRadius = new CornerRadius(_calendarTodayDotSize * 0.5),
|
||||
Background = accentBrush,
|
||||
CornerRadius = new CornerRadius(10),
|
||||
Width = 20,
|
||||
Height = 20,
|
||||
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
||||
Child = dayText
|
||||
Child = dayText,
|
||||
Tag = "today-dot"
|
||||
};
|
||||
Grid.SetRow(highlight, row);
|
||||
Grid.SetColumn(highlight, col);
|
||||
CalendarGrid.Children.Add(highlight);
|
||||
|
||||
Grid.SetRow(dot, row);
|
||||
Grid.SetColumn(dot, col);
|
||||
CalendarGrid.Children.Add(dot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 使用主题次要文本颜色
|
||||
var secondaryBrush = this.TryFindResource("AdaptiveTextSecondaryBrush", out var secondary)
|
||||
? secondary as IBrush
|
||||
: Brushes.Gray;
|
||||
dayText.Foreground = secondaryBrush;
|
||||
var isWeekend = col is 0 or 6;
|
||||
dayText.Foreground = isWeekend
|
||||
? GetThemeBrush("AdaptiveTextSecondaryBrush", 0.82)
|
||||
: GetThemeBrush("AdaptiveTextPrimaryBrush", 0.92);
|
||||
Grid.SetRow(dayText, row);
|
||||
Grid.SetColumn(dayText, col);
|
||||
CalendarGrid.Children.Add(dayText);
|
||||
@@ -168,13 +219,59 @@ public partial class DateWidget : UserControl
|
||||
|
||||
public void ApplyCellSize(double cellSize)
|
||||
{
|
||||
// 根据格子大小调整圆角
|
||||
RootBorder.CornerRadius = new CornerRadius(Math.Clamp(cellSize * 0.12, 8, 20));
|
||||
|
||||
// 调整字体大小
|
||||
var baseFontSize = cellSize * 0.25;
|
||||
TodayDayTextBlock.FontSize = Math.Clamp(baseFontSize * 2.8, 28, 72);
|
||||
TodayWeekdayTextBlock.FontSize = Math.Clamp(baseFontSize * 0.6, 10, 16);
|
||||
CalendarMonthYearTextBlock.FontSize = Math.Clamp(baseFontSize * 0.55, 9, 14);
|
||||
_currentCellSize = Math.Max(1, cellSize);
|
||||
var scale = ResolveScale();
|
||||
|
||||
RootBorder.CornerRadius = new CornerRadius(Math.Clamp(28 * scale, 16, 40));
|
||||
RootBorder.Padding = new Thickness(Math.Clamp(12 * scale, 8, 18));
|
||||
|
||||
LeftPanelGrid.RowSpacing = Math.Clamp(8 * scale, 5, 14);
|
||||
RightPanelGrid.RowSpacing = Math.Clamp(10 * scale, 6, 16);
|
||||
LunarCardBorder.CornerRadius = new CornerRadius(Math.Clamp(24 * scale, 14, 34));
|
||||
LunarCardBorder.Padding = new Thickness(Math.Clamp(14 * scale, 9, 20));
|
||||
|
||||
GregorianHeadlineTextBlock.FontSize = Math.Clamp(22 * scale, 14, 34);
|
||||
WeekdayText0.FontSize = Math.Clamp(13 * scale, 9, 18);
|
||||
WeekdayText1.FontSize = WeekdayText0.FontSize;
|
||||
WeekdayText2.FontSize = WeekdayText0.FontSize;
|
||||
WeekdayText3.FontSize = WeekdayText0.FontSize;
|
||||
WeekdayText4.FontSize = WeekdayText0.FontSize;
|
||||
WeekdayText5.FontSize = WeekdayText0.FontSize;
|
||||
WeekdayText6.FontSize = WeekdayText0.FontSize;
|
||||
|
||||
LunarDateTextBlock.FontSize = Math.Clamp(28 * scale, 17, 44);
|
||||
LunarMetaTextBlock.FontSize = Math.Clamp(14 * scale, 10, 22);
|
||||
YiLabelTextBlock.FontSize = Math.Clamp(18 * scale, 12, 28);
|
||||
JiLabelTextBlock.FontSize = YiLabelTextBlock.FontSize;
|
||||
YiItemsTextBlock.FontSize = Math.Clamp(16 * scale, 11, 24);
|
||||
JiItemsTextBlock.FontSize = YiItemsTextBlock.FontSize;
|
||||
|
||||
_calendarDayFontSize = Math.Clamp(14 * scale, 9, 22);
|
||||
_calendarTodayDotSize = Math.Clamp(28 * scale, 17, 38);
|
||||
|
||||
UpdateDate();
|
||||
}
|
||||
|
||||
private double ResolveScale()
|
||||
{
|
||||
var cellScale = Math.Clamp(_currentCellSize / 48d, 0.72, 1.55);
|
||||
var heightScale = Bounds.Height > 1 ? Math.Clamp(Bounds.Height / 220d, 0.65, 1.65) : 1;
|
||||
var widthScale = Bounds.Width > 1 ? Math.Clamp(Bounds.Width / 460d, 0.65, 1.65) : 1;
|
||||
return Math.Clamp(Math.Min(cellScale, Math.Min(heightScale, widthScale) * 1.08), 0.65, 1.6);
|
||||
}
|
||||
|
||||
private IBrush GetThemeBrush(string key, double opacity)
|
||||
{
|
||||
if (this.TryFindResource(key, out var value) && value is IBrush brush)
|
||||
{
|
||||
if (brush is ISolidColorBrush solid)
|
||||
{
|
||||
return new SolidColorBrush(solid.Color, opacity);
|
||||
}
|
||||
|
||||
return brush;
|
||||
}
|
||||
|
||||
return new SolidColorBrush(Colors.Gray, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user