mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
0.2.0
组件系统
This commit is contained in:
@@ -4,4 +4,5 @@ public static class BuiltInComponentIds
|
||||
{
|
||||
public const string Clock = "Clock";
|
||||
public const string Blank2x4 = "Blank2x4";
|
||||
public const string Date = "Date";
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ public sealed class ComponentRegistry
|
||||
MinWidthCells: 1,
|
||||
MinHeightCells: 1,
|
||||
AllowStatusBarPlacement: true,
|
||||
AllowDesktopPlacement: true),
|
||||
AllowDesktopPlacement: false),
|
||||
new DesktopComponentDefinition(
|
||||
BuiltInComponentIds.Blank2x4,
|
||||
"Blank 2x4",
|
||||
"Rectangle",
|
||||
"Layout",
|
||||
MinWidthCells: 2,
|
||||
MinHeightCells: 4,
|
||||
BuiltInComponentIds.Date,
|
||||
"Date",
|
||||
"Calendar",
|
||||
"Date",
|
||||
MinWidthCells: 4,
|
||||
MinHeightCells: 2,
|
||||
AllowStatusBarPlacement: false,
|
||||
AllowDesktopPlacement: true)
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
|
||||
@@ -84,10 +84,14 @@
|
||||
"launcher.empty": "No Start Menu entries found.",
|
||||
"launcher.empty_folder": "This folder is empty.",
|
||||
"launcher.folder_items_format": "{0} apps",
|
||||
"button.component_library": "Component Library",
|
||||
"tooltip.component_library": "Component Library",
|
||||
"component_library.title": "Component Library",
|
||||
"component_library.empty": "No components yet. Components will appear here later.",
|
||||
"button.component_library": "Edit Desktop",
|
||||
"tooltip.component_library": "Edit Desktop",
|
||||
"component_library.title": "Edit Desktop",
|
||||
"component_library.empty": "Swipe to pick a category, tap to open, then drag a widget onto the desktop.",
|
||||
"component_library.drag_hint": "Drag to place",
|
||||
"component_category.date": "Date",
|
||||
"component.date": "Date",
|
||||
"desktop.add_page": "Add page",
|
||||
"placement.fill": "Fill",
|
||||
"placement.fit": "Fit",
|
||||
"placement.stretch": "Stretch",
|
||||
|
||||
@@ -84,10 +84,14 @@
|
||||
"launcher.empty": "未找到开始菜单条目。",
|
||||
"launcher.empty_folder": "此文件夹为空。",
|
||||
"launcher.folder_items_format": "{0} 个应用",
|
||||
"button.component_library": "组件库",
|
||||
"tooltip.component_library": "组件库",
|
||||
"component_library.title": "组件库",
|
||||
"component_library.empty": "暂无组件,后续会在这里显示。",
|
||||
"button.component_library": "桌面编辑",
|
||||
"tooltip.component_library": "桌面编辑",
|
||||
"component_library.title": "桌面编辑",
|
||||
"component_library.empty": "左右滑动选择类别,点击进入,然后拖动组件到桌面放置。",
|
||||
"component_library.drag_hint": "拖动放置",
|
||||
"component_category.date": "日期",
|
||||
"component.date": "日历",
|
||||
"desktop.add_page": "新增页面",
|
||||
"placement.fill": "填充",
|
||||
"placement.fit": "适应",
|
||||
"placement.stretch": "拉伸",
|
||||
|
||||
@@ -18,6 +18,8 @@ public sealed class AppSettingsSnapshot
|
||||
|
||||
public string LanguageCode { get; set; } = "zh-CN";
|
||||
|
||||
public string? TimeZoneId { get; set; }
|
||||
|
||||
public List<string> TopStatusComponentIds { get; set; } = [];
|
||||
|
||||
public List<string> PinnedTaskbarActions { get; set; } =
|
||||
@@ -33,4 +35,6 @@ public sealed class AppSettingsSnapshot
|
||||
public int DesktopPageCount { get; set; } = 1;
|
||||
|
||||
public int CurrentDesktopSurfaceIndex { get; set; } = 0;
|
||||
|
||||
public List<DesktopComponentPlacementSnapshot> DesktopComponentPlacements { get; set; } = [];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace LanMontainDesktop.Models;
|
||||
|
||||
public sealed class DesktopComponentPlacementSnapshot
|
||||
{
|
||||
public string PlacementId { get; set; } = string.Empty;
|
||||
|
||||
public int PageIndex { get; set; }
|
||||
|
||||
public string ComponentId { get; set; } = string.Empty;
|
||||
|
||||
public int Row { get; set; }
|
||||
|
||||
public int Column { get; set; }
|
||||
|
||||
public int WidthCells { get; set; } = 1;
|
||||
|
||||
public int HeightCells { get; set; } = 1;
|
||||
}
|
||||
@@ -3,6 +3,6 @@ namespace LanMontainDesktop.Models;
|
||||
public enum TaskbarActionId
|
||||
{
|
||||
MinimizeToWindows,
|
||||
OpenSettings
|
||||
OpenSettings,
|
||||
AddDesktopPage
|
||||
}
|
||||
|
||||
|
||||
97
LanMontainDesktop/Services/TimeZoneService.cs
Normal file
97
LanMontainDesktop/Services/TimeZoneService.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace LanMontainDesktop.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 时区服务,提供时区信息和时间转换功能
|
||||
/// </summary>
|
||||
public sealed class TimeZoneService
|
||||
{
|
||||
private TimeZoneInfo _currentTimeZone = TimeZoneInfo.Local;
|
||||
|
||||
/// <summary>
|
||||
/// 当前选中的时区
|
||||
/// </summary>
|
||||
public TimeZoneInfo CurrentTimeZone
|
||||
{
|
||||
get => _currentTimeZone;
|
||||
set
|
||||
{
|
||||
if (_currentTimeZone != value)
|
||||
{
|
||||
_currentTimeZone = value;
|
||||
TimeZoneChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 时区变更事件
|
||||
/// </summary>
|
||||
public event EventHandler? TimeZoneChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有可用的时区
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<TimeZoneInfo> GetAllTimeZones()
|
||||
{
|
||||
return TimeZoneInfo.GetSystemTimeZones();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前时区的当前时间
|
||||
/// </summary>
|
||||
public DateTime GetCurrentTime()
|
||||
{
|
||||
return TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, _currentTimeZone);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据时区ID设置当前时区
|
||||
/// </summary>
|
||||
public bool SetTimeZoneById(string timeZoneId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
||||
CurrentTimeZone = timeZone;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取时区显示名称(包含UTC偏移)
|
||||
/// </summary>
|
||||
public string GetTimeZoneDisplayName(TimeZoneInfo timeZone)
|
||||
{
|
||||
var offset = timeZone.BaseUtcOffset;
|
||||
var sign = offset >= TimeSpan.Zero ? "+" : "-";
|
||||
var hours = Math.Abs(offset.Hours);
|
||||
var minutes = Math.Abs(offset.Minutes);
|
||||
|
||||
return $"(UTC{sign}{hours:D2}:{minutes:D2}) {timeZone.DisplayName}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取常用时区列表
|
||||
/// </summary>
|
||||
public TimeZoneInfo[] GetCommonTimeZones()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
TimeZoneInfo.Local, // 本地时区
|
||||
TimeZoneInfo.FindSystemTimeZoneById("China Standard Time"), // 北京时间
|
||||
TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"), // 东京时间
|
||||
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"), // 太平洋时间
|
||||
TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"), // 东部时间
|
||||
TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time"), // 中欧时间
|
||||
TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"), // 伦敦时间
|
||||
TimeZoneInfo.FindSystemTimeZoneById("UTC"), // 协调世界时
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,9 @@
|
||||
x:Class="LanMontainDesktop.Views.Components.ClockWidget">
|
||||
|
||||
<Border x:Name="RootBorder"
|
||||
Classes="glass-panel"
|
||||
Padding="8"
|
||||
CornerRadius="0"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0"
|
||||
Background="Transparent">
|
||||
CornerRadius="8">
|
||||
<TextBlock x:Name="TimeTextBlock"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
|
||||
@@ -4,6 +4,7 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using LanMontainDesktop.Services;
|
||||
|
||||
namespace LanMontainDesktop.Views.Components;
|
||||
|
||||
@@ -14,6 +15,8 @@ public partial class ClockWidget : UserControl
|
||||
Interval = TimeSpan.FromSeconds(1)
|
||||
};
|
||||
|
||||
private TimeZoneService? _timeZoneService;
|
||||
|
||||
public ClockWidget()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -24,6 +27,21 @@ public partial class ClockWidget : UserControl
|
||||
UpdateClock();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置时区服务
|
||||
/// </summary>
|
||||
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();
|
||||
@@ -40,9 +58,14 @@ public partial class ClockWidget : UserControl
|
||||
UpdateClock();
|
||||
}
|
||||
|
||||
private void OnTimeZoneChanged(object? sender, EventArgs e)
|
||||
{
|
||||
UpdateClock();
|
||||
}
|
||||
|
||||
private void UpdateClock()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
var now = _timeZoneService?.GetCurrentTime() ?? DateTime.Now;
|
||||
TimeTextBlock.Text = now.ToString("HH:mm:ss", CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
|
||||
83
LanMontainDesktop/Views/Components/DateWidget.axaml
Normal file
83
LanMontainDesktop/Views/Components/DateWidget.axaml
Normal file
@@ -0,0 +1,83 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="400"
|
||||
d:DesignHeight="200"
|
||||
x:Class="LanMontainDesktop.Views.Components.DateWidget">
|
||||
|
||||
<Border x:Name="RootBorder"
|
||||
Background="Transparent"
|
||||
CornerRadius="16"
|
||||
ClipToBounds="True">
|
||||
<Grid ColumnDefinitions="*,*">
|
||||
<!-- 左侧:月历 -->
|
||||
<Border x:Name="CalendarBackgroundBorder"
|
||||
Grid.Column="0"
|
||||
Padding="12"
|
||||
Background="{DynamicResource AdaptiveSurfaceBaseBrush}">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<!-- 月份年份 -->
|
||||
<TextBlock x:Name="CalendarMonthYearTextBlock"
|
||||
Grid.Row="0"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="12"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Margin="0,0,0,8" />
|
||||
|
||||
<!-- 月历网格 -->
|
||||
<Grid x:Name="CalendarGrid"
|
||||
Grid.Row="1"
|
||||
RowDefinitions="Auto,*,*,*,*,*"
|
||||
ColumnDefinitions="*,*,*,*,*,*,*">
|
||||
<!-- 星期标题 -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="日" HorizontalAlignment="Center" FontSize="10" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="一" HorizontalAlignment="Center" FontSize="10" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="2" Text="二" HorizontalAlignment="Center" FontSize="10" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="3" Text="三" HorizontalAlignment="Center" FontSize="10" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="4" Text="四" HorizontalAlignment="Center" FontSize="10" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="5" Text="五" HorizontalAlignment="Center" FontSize="10" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="6" Text="六" HorizontalAlignment="Center" FontSize="10" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 右侧:今日详情 -->
|
||||
<Border x:Name="TodayBackgroundBorder"
|
||||
Grid.Column="1"
|
||||
Background="{DynamicResource AdaptiveAccentBrush}"
|
||||
Padding="16">
|
||||
<Grid RowDefinitions="Auto,*,Auto">
|
||||
<!-- 今日标签 -->
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="今天"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="11"
|
||||
FontWeight="Medium"
|
||||
Opacity="0.8"
|
||||
Foreground="{DynamicResource AdaptiveOnAccentBrush}" />
|
||||
|
||||
<!-- 日期数字 -->
|
||||
<TextBlock x:Name="TodayDayTextBlock"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="56"
|
||||
FontWeight="Light"
|
||||
Foreground="{DynamicResource AdaptiveOnAccentBrush}" />
|
||||
|
||||
<!-- 星期 -->
|
||||
<TextBlock x:Name="TodayWeekdayTextBlock"
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="13"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource AdaptiveOnAccentBrush}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
</UserControl>
|
||||
180
LanMontainDesktop/Views/Components/DateWidget.axaml.cs
Normal file
180
LanMontainDesktop/Views/Components/DateWidget.axaml.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using LanMontainDesktop.Services;
|
||||
|
||||
namespace LanMontainDesktop.Views.Components;
|
||||
|
||||
public partial class DateWidget : UserControl
|
||||
{
|
||||
private readonly DispatcherTimer _timer = new()
|
||||
{
|
||||
Interval = TimeSpan.FromMinutes(1)
|
||||
};
|
||||
|
||||
private TimeZoneService? _timeZoneService;
|
||||
|
||||
public DateWidget()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_timer.Tick += OnTimerTick;
|
||||
AttachedToVisualTree += OnAttachedToVisualTree;
|
||||
DetachedFromVisualTree += OnDetachedFromVisualTree;
|
||||
UpdateDate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置时区服务
|
||||
/// </summary>
|
||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||
{
|
||||
if (_timeZoneService != null)
|
||||
{
|
||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||
}
|
||||
|
||||
_timeZoneService = timeZoneService;
|
||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||
UpdateDate();
|
||||
}
|
||||
|
||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
UpdateDate();
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
private void OnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
|
||||
private void OnTimerTick(object? sender, EventArgs e)
|
||||
{
|
||||
UpdateDate();
|
||||
}
|
||||
|
||||
private void OnTimeZoneChanged(object? sender, EventArgs e)
|
||||
{
|
||||
UpdateDate();
|
||||
}
|
||||
|
||||
private void UpdateDate()
|
||||
{
|
||||
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);
|
||||
|
||||
// 生成月历
|
||||
GenerateCalendar(now);
|
||||
}
|
||||
|
||||
private void GenerateCalendar(DateTime currentDate)
|
||||
{
|
||||
// 清空之前的日期(保留星期标题)
|
||||
var childrenToRemove = new List<Control>();
|
||||
foreach (var child in CalendarGrid.Children)
|
||||
{
|
||||
if (child is TextBlock tb && tb.Tag?.ToString() == "day")
|
||||
{
|
||||
childrenToRemove.Add(tb);
|
||||
}
|
||||
}
|
||||
foreach (var child in childrenToRemove)
|
||||
{
|
||||
CalendarGrid.Children.Remove(child);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 生成日期
|
||||
for (int day = 1; day <= daysInMonth; day++)
|
||||
{
|
||||
var row = ((day + startDayOfWeek - 1) / 7) + 1; // +1 because row 0 is weekday headers
|
||||
var col = (day + startDayOfWeek - 1) % 7;
|
||||
|
||||
if (row > 5) continue; // 最多显示6行
|
||||
|
||||
var dayText = new TextBlock
|
||||
{
|
||||
Text = day.ToString(),
|
||||
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
||||
FontSize = 10,
|
||||
Tag = "day"
|
||||
};
|
||||
|
||||
// 今天高亮
|
||||
if (day == today)
|
||||
{
|
||||
// 使用主题色高亮今天
|
||||
var accentBrush = this.TryFindResource("AdaptiveAccentBrush", out var accent)
|
||||
? accent as IBrush
|
||||
: Brushes.Blue;
|
||||
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
|
||||
{
|
||||
Background = accentBrush,
|
||||
CornerRadius = new CornerRadius(10),
|
||||
Width = 20,
|
||||
Height = 20,
|
||||
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
||||
Child = dayText
|
||||
};
|
||||
Grid.SetRow(highlight, row);
|
||||
Grid.SetColumn(highlight, col);
|
||||
CalendarGrid.Children.Add(highlight);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 使用主题次要文本颜色
|
||||
var secondaryBrush = this.TryFindResource("AdaptiveTextSecondaryBrush", out var secondary)
|
||||
? secondary as IBrush
|
||||
: Brushes.Gray;
|
||||
dayText.Foreground = secondaryBrush;
|
||||
Grid.SetRow(dayText, row);
|
||||
Grid.SetColumn(dayText, col);
|
||||
CalendarGrid.Children.Add(dayText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -107,6 +107,11 @@ public partial class MainWindow
|
||||
Grid.SetColumnSpan(DesktopPagesViewport, gridMetrics.ColumnCount);
|
||||
DesktopPagesViewport.Width = pageWidth;
|
||||
DesktopPagesViewport.Height = pageHeight;
|
||||
if (DesktopEditDragLayer is not null)
|
||||
{
|
||||
DesktopEditDragLayer.Width = pageWidth;
|
||||
DesktopEditDragLayer.Height = pageHeight;
|
||||
}
|
||||
|
||||
DesktopPagesHost.RowDefinitions.Clear();
|
||||
DesktopPagesHost.RowDefinitions.Add(new RowDefinition(new GridLength(pageHeight, GridUnitType.Pixel)));
|
||||
@@ -123,31 +128,35 @@ public partial class MainWindow
|
||||
DesktopPagesContainer.Children.Clear();
|
||||
DesktopPagesContainer.Width = pageWidth * _desktopPageCount;
|
||||
DesktopPagesContainer.Height = pageHeight;
|
||||
_desktopPageComponentGrids.Clear();
|
||||
for (var index = 0; index < _desktopPageCount; index++)
|
||||
{
|
||||
DesktopPagesContainer.ColumnDefinitions.Add(new ColumnDefinition(new GridLength(pageWidth, GridUnitType.Pixel)));
|
||||
var pageSurface = new Border
|
||||
|
||||
var pageGrid = new Grid
|
||||
{
|
||||
Width = pageWidth,
|
||||
Height = pageHeight,
|
||||
Background = Brushes.Transparent,
|
||||
BorderThickness = new Thickness(0),
|
||||
Padding = new Thickness(10)
|
||||
ShowGridLines = false
|
||||
};
|
||||
|
||||
if (_desktopPageCount > 1)
|
||||
for (var row = 0; row < viewportRowSpan; row++)
|
||||
{
|
||||
pageSurface.Child = new TextBlock
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
Foreground = Foreground,
|
||||
Opacity = 0.72,
|
||||
Text = Lf("desktop.page_index_format", "Desktop {0}", index + 1)
|
||||
};
|
||||
pageGrid.RowDefinitions.Add(new RowDefinition(new GridLength(gridMetrics.CellSize, GridUnitType.Pixel)));
|
||||
}
|
||||
|
||||
Grid.SetColumn(pageSurface, index);
|
||||
Grid.SetRow(pageSurface, 0);
|
||||
DesktopPagesContainer.Children.Add(pageSurface);
|
||||
for (var col = 0; col < gridMetrics.ColumnCount; col++)
|
||||
{
|
||||
pageGrid.ColumnDefinitions.Add(new ColumnDefinition(new GridLength(gridMetrics.CellSize, GridUnitType.Pixel)));
|
||||
}
|
||||
|
||||
_desktopPageComponentGrids[index] = pageGrid;
|
||||
RestoreDesktopPageComponents(index);
|
||||
|
||||
Grid.SetColumn(pageGrid, index);
|
||||
Grid.SetRow(pageGrid, 0);
|
||||
DesktopPagesContainer.Children.Add(pageGrid);
|
||||
}
|
||||
|
||||
Grid.SetColumn(LauncherPagePanel, 1);
|
||||
@@ -290,12 +299,17 @@ public partial class MainWindow
|
||||
|
||||
private bool CanSwipeDesktopSurface()
|
||||
{
|
||||
return !_isSettingsOpen && !_isComponentLibraryOpen && _desktopSurfacePageWidth > 1;
|
||||
return !_isSettingsOpen && !_isDesktopComponentDragActive && _desktopSurfacePageWidth > 1;
|
||||
}
|
||||
|
||||
private void OnDesktopPagesPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (!CanSwipeDesktopSurface() || DesktopPagesViewport is null)
|
||||
if (DesktopPagesViewport is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CanSwipeDesktopSurface())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -326,6 +340,16 @@ public partial class MainWindow
|
||||
|
||||
foreach (var node in visual.GetSelfAndVisualAncestors())
|
||||
{
|
||||
if (node is Control control)
|
||||
{
|
||||
// Avoid swiping pages when interacting with desktop components/widgets.
|
||||
if (control.Classes.Contains("desktop-component") ||
|
||||
control.Classes.Contains("desktop-component-host"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (node is Button or TextBox or ComboBox or ListBoxItem or Slider or ToggleSwitch)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -59,14 +59,15 @@ public partial class MainWindow
|
||||
WallpaperPreviewBackButtonTextBlock.Text = L("button.back_to_windows", "Back to Windows");
|
||||
ToolTip.SetTip(BackToWindowsButton, L("tooltip.back_to_windows", "Back to Windows"));
|
||||
|
||||
OpenComponentLibraryTextBlock.Text = L("button.component_library", "Component Library");
|
||||
WallpaperPreviewComponentLibraryTextBlock.Text = L("button.component_library", "Component Library");
|
||||
ToolTip.SetTip(OpenComponentLibraryButton, L("tooltip.component_library", "Component Library"));
|
||||
ComponentLibraryTitleTextBlock.Text = L("component_library.title", "Component Library");
|
||||
OpenComponentLibraryTextBlock.Text = L("button.component_library", "Edit Desktop");
|
||||
WallpaperPreviewComponentLibraryTextBlock.Text = L("button.component_library", "Edit Desktop");
|
||||
GridPreviewComponentLibraryTextBlock.Text = L("button.component_library", "Edit Desktop");
|
||||
ToolTip.SetTip(OpenComponentLibraryButton, L("tooltip.component_library", "Edit Desktop"));
|
||||
ComponentLibraryTitleTextBlock.Text = L("component_library.title", "Edit Desktop");
|
||||
ToolTip.SetTip(CloseComponentLibraryButton, L("common.close", "Close"));
|
||||
ComponentLibraryEmptyTextBlock.Text = L(
|
||||
"component_library.empty",
|
||||
"No components yet. Components will appear here later.");
|
||||
"Swipe to pick a category, tap to open, then drag a widget onto the desktop.");
|
||||
|
||||
LauncherTitleTextBlock.Text = L("launcher.title", "应用启动台");
|
||||
LauncherSubtitleTextBlock.Text = L("launcher.subtitle", "按 Windows 开始菜单结构显示所有应用与文件夹");
|
||||
@@ -74,21 +75,19 @@ public partial class MainWindow
|
||||
ToolTip.SetTip(LauncherFolderCloseButton, L("common.close", "关闭"));
|
||||
|
||||
SettingsNavHeaderTextBlock.Text = L("settings.nav_header", "Settings");
|
||||
SettingsNavWallpaperItem.Content = L("settings.nav.wallpaper", "Wallpaper");
|
||||
SettingsNavGridItem.Content = L("settings.nav.grid", "Grid");
|
||||
SettingsNavColorItem.Content = L("settings.nav.color", "Color");
|
||||
SettingsNavStatusBarItem.Content = L("settings.nav.status_bar", "Status Bar");
|
||||
SettingsNavRegionItem.Content = L("settings.nav.region", "Region");
|
||||
SettingsNavWallpaperTextBlock.Text = L("settings.nav.wallpaper", "Wallpaper");
|
||||
SettingsNavGridTextBlock.Text = L("settings.nav.grid", "Grid");
|
||||
SettingsNavColorTextBlock.Text = L("settings.nav.color", "Color");
|
||||
SettingsNavStatusBarTextBlock.Text = L("settings.nav.status_bar", "Status Bar");
|
||||
SettingsNavRegionTextBlock.Text = L("settings.nav.region", "Region");
|
||||
|
||||
WallpaperPanelTitleTextBlock.Text = L("settings.wallpaper.title", "个性化您的背景");
|
||||
WallpaperPanelDescriptionTextBlock.Text = L("settings.wallpaper.description", "选择图片或视频");
|
||||
WallpaperPanelTitleTextBlock.Text = L("settings.wallpaper.title", "个性化我们的背景");
|
||||
WallpaperPlacementSettingsExpander.Header = L("settings.wallpaper.placement_label", "选择契合度");
|
||||
WallpaperPlacementSettingsExpander.Description = L("settings.wallpaper.placement_desc", "调整图像在桌面上的填充方式。");
|
||||
PickWallpaperButton.Content = L("settings.wallpaper.pick_button", "浏览照片");
|
||||
ClearWallpaperButton.Content = L("settings.wallpaper.clear_button", "重置");
|
||||
|
||||
GridPanelTitleTextBlock.Text = L("settings.grid.title", "Grid Layout");
|
||||
ApplyGridButton.Content = L("settings.grid.apply_button", "Apply");
|
||||
|
||||
ColorPanelTitleTextBlock.Text = L("settings.color.title", "Color");
|
||||
ThemeModeSettingsExpander.Header = L("settings.color.day_night_label", "Day/Night");
|
||||
@@ -123,7 +122,7 @@ public partial class MainWindow
|
||||
DesktopGrid.RowDefinitions.Count,
|
||||
DesktopGrid.RowDefinitions.Count > 0 ? DesktopGrid.RowDefinitions[0].Height.Value : 0d);
|
||||
|
||||
PopulateComponentLibraryItems();
|
||||
BuildComponentLibraryCategoryPages();
|
||||
RenderLauncherRootTiles();
|
||||
UpdateOpenSettingsActionVisualState();
|
||||
UpdateWallpaperDisplay();
|
||||
|
||||
@@ -71,6 +71,12 @@ public partial class MainWindow
|
||||
ColorSettingsPanel.IsVisible = selectedIndex == 2;
|
||||
StatusBarSettingsPanel.IsVisible = selectedIndex == 3;
|
||||
RegionSettingsPanel.IsVisible = selectedIndex == 4;
|
||||
|
||||
if (selectedIndex == 1)
|
||||
{
|
||||
UpdateGridPreviewLayout();
|
||||
}
|
||||
|
||||
ApplyTaskbarActionVisibility(GetCurrentTaskbarContext());
|
||||
}
|
||||
|
||||
@@ -633,12 +639,14 @@ public partial class MainWindow
|
||||
WallpaperPlacement = GetPlacementDisplayName(GetSelectedWallpaperPlacement()),
|
||||
SettingsTabIndex = Math.Max(0, SettingsNavListBox?.SelectedIndex ?? 0),
|
||||
LanguageCode = _languageCode,
|
||||
TimeZoneId = _timeZoneService.CurrentTimeZone.Id,
|
||||
TopStatusComponentIds = _topStatusComponentIds.ToList(),
|
||||
PinnedTaskbarActions = _pinnedTaskbarActions.Select(action => action.ToString()).ToList(),
|
||||
EnableDynamicTaskbarActions = _enableDynamicTaskbarActions,
|
||||
TaskbarLayoutMode = _taskbarLayoutMode,
|
||||
DesktopPageCount = _desktopPageCount,
|
||||
CurrentDesktopSurfaceIndex = _currentDesktopSurfaceIndex
|
||||
CurrentDesktopSurfaceIndex = _currentDesktopSurfaceIndex,
|
||||
DesktopComponentPlacements = _desktopComponentPlacements.ToList()
|
||||
};
|
||||
|
||||
_appSettingsService.Save(snapshot);
|
||||
@@ -1028,16 +1036,7 @@ public partial class MainWindow
|
||||
{
|
||||
WallpaperPlacementSettingsExpander.IconSource = new FluentIcons.Avalonia.Fluent.SymbolIconSource
|
||||
{
|
||||
Symbol = Symbol.Image,
|
||||
IconVariant = variant
|
||||
};
|
||||
}
|
||||
|
||||
if (GridSizeSettingsExpander is not null)
|
||||
{
|
||||
GridSizeSettingsExpander.IconSource = new FluentIcons.Avalonia.Fluent.SymbolIconSource
|
||||
{
|
||||
Symbol = Symbol.Grid,
|
||||
Symbol = Symbol.Wallpaper,
|
||||
IconVariant = variant
|
||||
};
|
||||
}
|
||||
@@ -1064,7 +1063,16 @@ public partial class MainWindow
|
||||
{
|
||||
LanguageSettingsExpander.IconSource = new FluentIcons.Avalonia.Fluent.SymbolIconSource
|
||||
{
|
||||
Symbol = Symbol.Earth,
|
||||
Symbol = Symbol.Translate,
|
||||
IconVariant = variant
|
||||
};
|
||||
}
|
||||
|
||||
if (TimeZoneSettingsExpander is not null)
|
||||
{
|
||||
TimeZoneSettingsExpander.IconSource = new FluentIcons.Avalonia.Fluent.SymbolIconSource
|
||||
{
|
||||
Symbol = Symbol.GlobeClock,
|
||||
IconVariant = variant
|
||||
};
|
||||
}
|
||||
|
||||
@@ -210,6 +210,8 @@
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<Canvas x:Name="DesktopEditDragLayer"
|
||||
IsHitTestVisible="False" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
@@ -259,8 +261,8 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8">
|
||||
<fi:SymbolIcon Classes="icon-m"
|
||||
Symbol="Window"
|
||||
<fi:FluentIcon x:Name="BackToWindowsIcon"
|
||||
Icon="Window"
|
||||
IconVariant="Regular" />
|
||||
<TextBlock x:Name="BackToWindowsTextBlock"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
@@ -301,7 +303,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8">
|
||||
<fi:FluentIcon Classes="icon-m"
|
||||
<fi:FluentIcon x:Name="OpenComponentLibraryIcon"
|
||||
Icon="Apps"
|
||||
IconVariant="Regular" />
|
||||
<TextBlock x:Name="OpenComponentLibraryTextBlock"
|
||||
@@ -324,8 +326,8 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="6">
|
||||
<fi:SymbolIcon Classes="icon-l"
|
||||
Symbol="Settings"
|
||||
<fi:FluentIcon x:Name="OpenSettingsIcon"
|
||||
Icon="Settings"
|
||||
IconVariant="Regular" />
|
||||
<TextBlock x:Name="OpenSettingsButtonTextBlock"
|
||||
IsVisible="False"
|
||||
@@ -413,32 +415,32 @@
|
||||
SelectionChanged="OnSettingsNavSelectionChanged">
|
||||
<ListBoxItem x:Name="SettingsNavWallpaperItem" ToolTip.Tip="壁纸">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<fi:SymbolIcon Symbol="Image" IconVariant="Regular" />
|
||||
<TextBlock Text="壁纸" VerticalAlignment="Center" />
|
||||
<fi:SymbolIcon x:Name="SettingsNavWallpaperIcon" Symbol="Wallpaper" IconVariant="Regular" />
|
||||
<TextBlock x:Name="SettingsNavWallpaperTextBlock" Text="壁纸" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem x:Name="SettingsNavGridItem" ToolTip.Tip="网格">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<fi:SymbolIcon Symbol="Grid" IconVariant="Regular" />
|
||||
<TextBlock Text="网格" VerticalAlignment="Center" />
|
||||
<fi:SymbolIcon x:Name="SettingsNavGridIcon" Symbol="Grid" IconVariant="Regular" />
|
||||
<TextBlock x:Name="SettingsNavGridTextBlock" Text="网格" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem x:Name="SettingsNavColorItem" ToolTip.Tip="颜色">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<fi:SymbolIcon Symbol="Color" IconVariant="Regular" />
|
||||
<TextBlock Text="颜色" VerticalAlignment="Center" />
|
||||
<fi:SymbolIcon x:Name="SettingsNavColorIcon" Symbol="Color" IconVariant="Regular" />
|
||||
<TextBlock x:Name="SettingsNavColorTextBlock" Text="颜色" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem x:Name="SettingsNavStatusBarItem" ToolTip.Tip="状态栏">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<fi:SymbolIcon Symbol="Clock" IconVariant="Regular" />
|
||||
<TextBlock Text="状态栏" VerticalAlignment="Center" />
|
||||
<fi:SymbolIcon x:Name="SettingsNavStatusBarIcon" Symbol="Status" IconVariant="Regular" />
|
||||
<TextBlock x:Name="SettingsNavStatusBarTextBlock" Text="状态栏" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem x:Name="SettingsNavRegionItem" ToolTip.Tip="地区">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<fi:SymbolIcon Symbol="Earth" IconVariant="Regular" />
|
||||
<TextBlock Text="地区" VerticalAlignment="Center" />
|
||||
<fi:SymbolIcon x:Name="SettingsNavRegionIcon" Symbol="Globe" IconVariant="Regular" />
|
||||
<TextBlock x:Name="SettingsNavRegionTextBlock" Text="地区" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</ListBoxItem>
|
||||
</ListBox>
|
||||
@@ -461,12 +463,6 @@
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Margin="0,0,0,24"
|
||||
Text="个性化您的背景" />
|
||||
<TextBlock x:Name="WallpaperPanelDescriptionTextBlock"
|
||||
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
Margin="0,-18,0,24"
|
||||
Text="更改您的壁纸并将预览投影到显示器上。" />
|
||||
|
||||
<!-- Left Column: Monitor Preview -->
|
||||
<Border x:Name="WallpaperPreviewHost"
|
||||
@@ -603,45 +599,120 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<StackPanel x:Name="GridSettingsPanel"
|
||||
IsVisible="False"
|
||||
Spacing="16">
|
||||
<Grid x:Name="GridSettingsPanel"
|
||||
IsVisible="False"
|
||||
ColumnDefinitions="*, *"
|
||||
RowDefinitions="Auto, *">
|
||||
<TextBlock x:Name="GridPanelTitleTextBlock"
|
||||
FontSize="24"
|
||||
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
FontSize="28"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Text="Grid layout" />
|
||||
Margin="0,0,0,24"
|
||||
Text="调整网格布局" />
|
||||
|
||||
<ui:SettingsExpander x:Name="GridSizeSettingsExpander"
|
||||
Header="短边格数"
|
||||
Description="决定桌面短边的基础格子数量">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
<!-- Left Column: Grid Preview -->
|
||||
<Border x:Name="GridPreviewHost"
|
||||
Grid.Row="1" Grid.Column="0"
|
||||
Margin="0,0,16,0"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Stretch">
|
||||
<Border x:Name="GridPreviewFrame"
|
||||
HorizontalAlignment="Stretch"
|
||||
CornerRadius="14"
|
||||
Background="#FF1A1A1A"
|
||||
Padding="12">
|
||||
<Border x:Name="GridPreviewViewport"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="4"
|
||||
Background="#30111827">
|
||||
<Panel>
|
||||
<Canvas x:Name="GridPreviewLinesCanvas" />
|
||||
<Grid x:Name="GridPreviewGrid"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<Border x:Name="GridPreviewTopStatusBarHost"
|
||||
Grid.Row="0"
|
||||
Background="Transparent"
|
||||
Padding="2">
|
||||
<StackPanel x:Name="GridPreviewTopStatusComponentsPanel"
|
||||
Orientation="Horizontal"
|
||||
Spacing="3">
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<Grid ColumnDefinitions="Auto,Auto"
|
||||
ColumnSpacing="8">
|
||||
<ui:NumberBox x:Name="GridSizeNumberBox"
|
||||
Grid.Column="0"
|
||||
Width="120"
|
||||
Minimum="6"
|
||||
Maximum="96"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Value="12" />
|
||||
<Button x:Name="ApplyGridButton"
|
||||
Grid.Column="1"
|
||||
Padding="12,6"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Click="OnApplyGridSizeClick"
|
||||
Content="应用" />
|
||||
</Grid>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
<Border x:Name="GridPreviewBottomTaskbarContainer"
|
||||
Classes="glass-strong"
|
||||
Grid.Row="1"
|
||||
Margin="3"
|
||||
CornerRadius="8"
|
||||
Padding="2">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto"
|
||||
ColumnSpacing="3">
|
||||
<Border x:Name="GridPreviewTaskbarFixedActionsHost" Grid.Column="0">
|
||||
<StackPanel x:Name="GridPreviewBackButtonVisual" Orientation="Horizontal" Spacing="3">
|
||||
<fi:SymbolIcon Classes="icon-s" Symbol="Window" />
|
||||
<TextBlock x:Name="GridPreviewBackButtonTextBlock" Text="回到Windows" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<StackPanel x:Name="GridPreviewTaskbarDynamicActionsHost"
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="3" />
|
||||
<Border x:Name="GridPreviewTaskbarSettingsActionHost" Grid.Column="2">
|
||||
<StackPanel Orientation="Horizontal" Spacing="3">
|
||||
<StackPanel x:Name="GridPreviewComponentLibraryVisual" IsVisible="False" Orientation="Horizontal" Spacing="3">
|
||||
<fi:FluentIcon x:Name="GridPreviewComponentLibraryIcon" Classes="icon-s" Icon="Apps" />
|
||||
<TextBlock x:Name="GridPreviewComponentLibraryTextBlock" Text="组件库" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<fi:SymbolIcon x:Name="GridPreviewSettingsButtonIcon" Classes="icon-s" Symbol="Settings" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Panel>
|
||||
</Border>
|
||||
</Border>
|
||||
</Border>
|
||||
|
||||
<TextBlock x:Name="GridInfoTextBlock"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
Text="Grid: - cols x - rows (1:1)" />
|
||||
</StackPanel>
|
||||
<!-- Right Column: Settings Content -->
|
||||
<StackPanel Grid.Row="1" Grid.Column="1"
|
||||
Margin="16,0,0,0"
|
||||
Spacing="16">
|
||||
<TextBlock Text="竖排格数" FontSize="16" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="12">
|
||||
<Slider x:Name="GridSizeSlider"
|
||||
Grid.Column="0"
|
||||
Minimum="6"
|
||||
Maximum="96"
|
||||
TickFrequency="1"
|
||||
TickPlacement="None"
|
||||
Value="12"
|
||||
ValueChanged="OnGridSizeSliderChanged" />
|
||||
<ui:NumberBox x:Name="GridSizeNumberBox"
|
||||
Grid.Column="1"
|
||||
Width="80"
|
||||
Minimum="6"
|
||||
Maximum="96"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Value="12" />
|
||||
</Grid>
|
||||
|
||||
<Button x:Name="ApplyGridButton"
|
||||
HorizontalAlignment="Stretch"
|
||||
Padding="0,10"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Click="OnApplyGridSizeClick"
|
||||
Content="应用" />
|
||||
|
||||
<TextBlock x:Name="GridInfoTextBlock"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
Text="Grid: - cols x - rows (1:1)" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<StackPanel x:Name="ColorSettingsPanel"
|
||||
IsVisible="False"
|
||||
@@ -899,6 +970,18 @@
|
||||
</ComboBox>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
<ui:SettingsExpander x:Name="TimeZoneSettingsExpander"
|
||||
Header="时区"
|
||||
Description="选择时区,时钟和日历将根据此时区显示时间。">
|
||||
<ui:SettingsExpander.IconSource>
|
||||
|
||||
</ui:SettingsExpander.IconSource>
|
||||
<ui:SettingsExpander.Footer>
|
||||
<ComboBox x:Name="TimeZoneComboBox"
|
||||
Width="280"
|
||||
SelectionChanged="OnTimeZoneSelectionChanged" />
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
@@ -956,20 +1039,89 @@
|
||||
CornerRadius="12"
|
||||
Padding="14">
|
||||
<Grid>
|
||||
<ScrollViewer x:Name="ComponentLibraryItemsScrollViewer"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled">
|
||||
<WrapPanel x:Name="ComponentLibraryItemsPanel"
|
||||
ItemWidth="190"
|
||||
ItemHeight="104"
|
||||
Orientation="Horizontal" />
|
||||
</ScrollViewer>
|
||||
<!-- Category picker (outer) -->
|
||||
<Grid x:Name="ComponentLibraryCategoriesView">
|
||||
<Border x:Name="ComponentLibraryCategoryViewport"
|
||||
Background="Transparent"
|
||||
ClipToBounds="True"
|
||||
PointerPressed="OnComponentLibraryCategoryViewportPointerPressed"
|
||||
PointerMoved="OnComponentLibraryCategoryViewportPointerMoved"
|
||||
PointerReleased="OnComponentLibraryCategoryViewportPointerReleased"
|
||||
PointerCaptureLost="OnComponentLibraryCategoryViewportPointerCaptureLost">
|
||||
<Grid>
|
||||
<Grid x:Name="ComponentLibraryCategoryPagesHost"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top">
|
||||
<Grid.RenderTransform>
|
||||
<TranslateTransform>
|
||||
<TranslateTransform.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="X" Duration="0:0:0.22" />
|
||||
</Transitions>
|
||||
</TranslateTransform.Transitions>
|
||||
</TranslateTransform>
|
||||
</Grid.RenderTransform>
|
||||
|
||||
<TextBlock x:Name="ComponentLibraryEmptyTextBlock"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
Text="暂无组件,后续将在这里显示。" />
|
||||
<Grid x:Name="ComponentLibraryCategoryPagesContainer" />
|
||||
</Grid>
|
||||
|
||||
<TextBlock x:Name="ComponentLibraryEmptyTextBlock"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||
Text="No components." />
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Component picker (inner) -->
|
||||
<Grid x:Name="ComponentLibraryComponentsView"
|
||||
IsVisible="False"
|
||||
RowDefinitions="Auto,*"
|
||||
RowSpacing="10">
|
||||
<Button x:Name="ComponentLibraryBackButton"
|
||||
Grid.Row="0"
|
||||
HorizontalAlignment="Left"
|
||||
Padding="8,6"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||
Click="OnComponentLibraryBackClick">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<fi:SymbolIcon Classes="icon-s" Symbol="ArrowLeft" IconVariant="Regular" />
|
||||
<TextBlock x:Name="ComponentLibraryBackTextBlock"
|
||||
VerticalAlignment="Center"
|
||||
Text="Back" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Border x:Name="ComponentLibraryComponentViewport"
|
||||
Grid.Row="1"
|
||||
Background="Transparent"
|
||||
ClipToBounds="True"
|
||||
PointerPressed="OnComponentLibraryComponentViewportPointerPressed"
|
||||
PointerMoved="OnComponentLibraryComponentViewportPointerMoved"
|
||||
PointerReleased="OnComponentLibraryComponentViewportPointerReleased"
|
||||
PointerCaptureLost="OnComponentLibraryComponentViewportPointerCaptureLost">
|
||||
<Grid>
|
||||
<Grid x:Name="ComponentLibraryComponentPagesHost"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top">
|
||||
<Grid.RenderTransform>
|
||||
<TranslateTransform>
|
||||
<TranslateTransform.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="X" Duration="0:0:0.22" />
|
||||
</Transitions>
|
||||
</TranslateTransform.Transitions>
|
||||
</TranslateTransform>
|
||||
</Grid.RenderTransform>
|
||||
|
||||
<Grid x:Name="ComponentLibraryComponentPagesContainer" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
1048
LanMontainDesktop/Views/MainWindow.axaml.backup
Normal file
1048
LanMontainDesktop/Views/MainWindow.axaml.backup
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,11 @@ using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Line = Avalonia.Controls.Shapes.Line;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Styling;
|
||||
@@ -66,6 +68,7 @@ public partial class MainWindow : Window
|
||||
private readonly MonetColorService _monetColorService = new();
|
||||
private readonly AppSettingsService _appSettingsService = new();
|
||||
private readonly LocalizationService _localizationService = new();
|
||||
private readonly TimeZoneService _timeZoneService = new();
|
||||
private readonly ComponentRegistry _componentRegistry = ComponentRegistry
|
||||
.CreateDefault()
|
||||
.RegisterExtensions(
|
||||
@@ -109,6 +112,7 @@ public partial class MainWindow : Window
|
||||
InitializeComponent();
|
||||
_fluentAvaloniaTheme = Application.Current?.Styles.OfType<FluentAvaloniaTheme>().FirstOrDefault();
|
||||
PropertyChanged += OnWindowPropertyChanged;
|
||||
InitializeDesktopComponentDragHandlers();
|
||||
}
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
@@ -118,11 +122,19 @@ public partial class MainWindow : Window
|
||||
_suppressSettingsPersistence = true;
|
||||
var snapshot = _appSettingsService.Load();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(snapshot.TimeZoneId))
|
||||
{
|
||||
_timeZoneService.SetTimeZoneById(snapshot.TimeZoneId);
|
||||
}
|
||||
|
||||
_targetShortSideCells = Math.Clamp(
|
||||
snapshot.GridShortSideCells > 0 ? snapshot.GridShortSideCells : CalculateDefaultShortSideCellCountFromDpi(),
|
||||
MinShortSideCells,
|
||||
MaxShortSideCells);
|
||||
GridSizeNumberBox.Value = _targetShortSideCells;
|
||||
GridSizeSlider.Value = _targetShortSideCells;
|
||||
GridSizeSlider.ValueChanged += OnGridSizeSliderChanged;
|
||||
GridSizeNumberBox.ValueChanged += OnGridSizeNumberBoxChanged;
|
||||
|
||||
SettingsNavListBox.SelectedIndex = Math.Clamp(snapshot.SettingsTabIndex, 0, 4);
|
||||
UpdateSettingsTabContent();
|
||||
@@ -132,6 +144,7 @@ public partial class MainWindow : Window
|
||||
ApplyTaskbarSettings(snapshot);
|
||||
InitializeLocalization(snapshot.LanguageCode);
|
||||
InitializeDesktopSurfaceState(snapshot);
|
||||
InitializeDesktopComponentPlacements(snapshot);
|
||||
InitializeSettingsIcons();
|
||||
|
||||
TryRestoreWallpaper(snapshot.WallpaperPath);
|
||||
@@ -153,9 +166,11 @@ public partial class MainWindow : Window
|
||||
_settingsContentPanelTransform = SettingsContentPanel.RenderTransform as TranslateTransform;
|
||||
DesktopHost.SizeChanged += OnDesktopHostSizeChanged;
|
||||
WallpaperPreviewHost.SizeChanged += OnWallpaperPreviewHostSizeChanged;
|
||||
GridPreviewHost.SizeChanged += OnGridPreviewHostSizeChanged;
|
||||
RebuildDesktopGrid();
|
||||
PopulateComponentLibraryItems();
|
||||
LoadLauncherEntriesAsync();
|
||||
InitializeTimeZoneSettings();
|
||||
ClockWidget.SetTimeZoneService(_timeZoneService);
|
||||
|
||||
_suppressSettingsPersistence = false;
|
||||
PersistSettings();
|
||||
@@ -181,6 +196,9 @@ public partial class MainWindow : Window
|
||||
PropertyChanged -= OnWindowPropertyChanged;
|
||||
DesktopHost.SizeChanged -= OnDesktopHostSizeChanged;
|
||||
WallpaperPreviewHost.SizeChanged -= OnWallpaperPreviewHostSizeChanged;
|
||||
GridPreviewHost.SizeChanged -= OnGridPreviewHostSizeChanged;
|
||||
GridSizeSlider.ValueChanged -= OnGridSizeSliderChanged;
|
||||
GridSizeNumberBox.ValueChanged -= OnGridSizeNumberBoxChanged;
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
@@ -202,6 +220,195 @@ public partial class MainWindow : Window
|
||||
UpdateWallpaperPreviewLayout();
|
||||
}
|
||||
|
||||
private void OnGridPreviewHostSizeChanged(object? sender, SizeChangedEventArgs e)
|
||||
{
|
||||
UpdateGridPreviewLayout();
|
||||
}
|
||||
|
||||
private void OnGridSizeSliderChanged(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var sliderValue = (int)Math.Round(GridSizeSlider.Value);
|
||||
if (Math.Abs(GridSizeNumberBox.Value - sliderValue) > double.Epsilon)
|
||||
{
|
||||
GridSizeNumberBox.Value = sliderValue;
|
||||
}
|
||||
UpdateGridPreviewLayout();
|
||||
}
|
||||
|
||||
private void OnGridSizeNumberBoxChanged(object? sender, NumberBoxValueChangedEventArgs e)
|
||||
{
|
||||
var numberBoxValue = (int)Math.Round(GridSizeNumberBox.Value);
|
||||
if (Math.Abs(GridSizeSlider.Value - numberBoxValue) > double.Epsilon)
|
||||
{
|
||||
GridSizeSlider.Value = numberBoxValue;
|
||||
}
|
||||
UpdateGridPreviewLayout();
|
||||
}
|
||||
|
||||
private void UpdateGridPreviewLayout()
|
||||
{
|
||||
if (GridPreviewFrame is null ||
|
||||
GridPreviewHost is null ||
|
||||
GridPreviewViewport is null ||
|
||||
GridPreviewGrid is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var previewShortSideCells = (int)Math.Round(GridSizeSlider.Value);
|
||||
if (previewShortSideCells < MinShortSideCells || previewShortSideCells > MaxShortSideCells)
|
||||
{
|
||||
previewShortSideCells = _targetShortSideCells;
|
||||
}
|
||||
|
||||
var desktopWidth = Math.Max(1, DesktopHost.Bounds.Width);
|
||||
var desktopHeight = Math.Max(1, DesktopHost.Bounds.Height);
|
||||
var aspectRatio = desktopWidth / desktopHeight;
|
||||
|
||||
var availableWidth = Math.Max(100, GridPreviewHost.Bounds.Width);
|
||||
|
||||
var framePadding = GridPreviewFrame.Padding;
|
||||
var horizontalPadding = framePadding.Left + framePadding.Right;
|
||||
var verticalPadding = framePadding.Top + framePadding.Bottom;
|
||||
|
||||
var gridPreviewWidth = availableWidth;
|
||||
var gridPreviewHeight = gridPreviewWidth / aspectRatio;
|
||||
|
||||
GridPreviewFrame.Width = gridPreviewWidth;
|
||||
GridPreviewFrame.Height = gridPreviewHeight;
|
||||
|
||||
var innerWidth = Math.Max(1, gridPreviewWidth - horizontalPadding);
|
||||
var innerHeight = Math.Max(1, gridPreviewHeight - verticalPadding);
|
||||
var gridMetrics = CalculateGridMetrics(innerWidth, innerHeight, previewShortSideCells);
|
||||
if (gridMetrics.CellSize <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GridPreviewGrid.Width = gridMetrics.ColumnCount * gridMetrics.CellSize;
|
||||
GridPreviewGrid.Height = gridMetrics.RowCount * gridMetrics.CellSize;
|
||||
|
||||
GridPreviewGrid.RowDefinitions.Clear();
|
||||
GridPreviewGrid.ColumnDefinitions.Clear();
|
||||
|
||||
for (var row = 0; row < gridMetrics.RowCount; row++)
|
||||
{
|
||||
GridPreviewGrid.RowDefinitions.Add(
|
||||
new RowDefinition(new GridLength(gridMetrics.CellSize, GridUnitType.Pixel)));
|
||||
}
|
||||
|
||||
for (var col = 0; col < gridMetrics.ColumnCount; col++)
|
||||
{
|
||||
GridPreviewGrid.ColumnDefinitions.Add(
|
||||
new ColumnDefinition(new GridLength(gridMetrics.CellSize, GridUnitType.Pixel)));
|
||||
}
|
||||
|
||||
PlaceStatusBarComponent(
|
||||
GridPreviewTopStatusBarHost,
|
||||
column: 0,
|
||||
requestedColumnSpan: gridMetrics.ColumnCount,
|
||||
totalColumns: gridMetrics.ColumnCount);
|
||||
|
||||
var taskbarRow = gridMetrics.RowCount - 1;
|
||||
Grid.SetRow(GridPreviewBottomTaskbarContainer, taskbarRow);
|
||||
Grid.SetColumn(GridPreviewBottomTaskbarContainer, 0);
|
||||
Grid.SetRowSpan(GridPreviewBottomTaskbarContainer, 1);
|
||||
Grid.SetColumnSpan(GridPreviewBottomTaskbarContainer, gridMetrics.ColumnCount);
|
||||
|
||||
ApplyGridPreviewWidgetSizing(gridMetrics.CellSize);
|
||||
|
||||
GridInfoTextBlock.Text = Lf(
|
||||
"settings.grid.info_format",
|
||||
"Grid: {0} cols x {1} rows | cell {2:F1}px (1:1)",
|
||||
gridMetrics.ColumnCount,
|
||||
gridMetrics.RowCount,
|
||||
gridMetrics.CellSize);
|
||||
|
||||
DrawGridPreviewLines(gridMetrics);
|
||||
}
|
||||
|
||||
private void DrawGridPreviewLines(GridMetrics gridMetrics)
|
||||
{
|
||||
if (GridPreviewLinesCanvas is null || GridPreviewViewport is null || GridPreviewGrid is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var viewportBackground = GridPreviewViewport.Background as SolidColorBrush;
|
||||
var backgroundColor = viewportBackground?.Color ?? Color.Parse("#30111827");
|
||||
var luminance = CalculateRelativeLuminance(backgroundColor);
|
||||
var lineColor = luminance >= LightBackgroundLuminanceThreshold
|
||||
? Color.Parse("#80000000")
|
||||
: Color.Parse("#80FFFFFF");
|
||||
|
||||
GridPreviewLinesCanvas.Children.Clear();
|
||||
|
||||
var cellSize = gridMetrics.CellSize;
|
||||
var gridWidth = gridMetrics.ColumnCount * cellSize;
|
||||
var gridHeight = gridMetrics.RowCount * cellSize;
|
||||
|
||||
GridPreviewLinesCanvas.Width = gridWidth;
|
||||
GridPreviewLinesCanvas.Height = gridHeight;
|
||||
|
||||
Canvas.SetLeft(GridPreviewLinesCanvas, 0);
|
||||
Canvas.SetTop(GridPreviewLinesCanvas, 0);
|
||||
|
||||
var dashLength = cellSize * 0.3;
|
||||
var gapLength = cellSize * 0.2;
|
||||
|
||||
for (var row = 0; row <= gridMetrics.RowCount; row++)
|
||||
{
|
||||
var y = row * cellSize;
|
||||
var line = new Line
|
||||
{
|
||||
StartPoint = new Point(0, y),
|
||||
EndPoint = new Point(gridWidth, y),
|
||||
Stroke = new SolidColorBrush(lineColor),
|
||||
StrokeThickness = 1,
|
||||
StrokeDashArray = new Avalonia.Collections.AvaloniaList<double> { dashLength, gapLength },
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
GridPreviewLinesCanvas.Children.Add(line);
|
||||
}
|
||||
|
||||
for (var col = 0; col <= gridMetrics.ColumnCount; col++)
|
||||
{
|
||||
var x = col * cellSize;
|
||||
var line = new Line
|
||||
{
|
||||
StartPoint = new Point(x, 0),
|
||||
EndPoint = new Point(x, gridHeight),
|
||||
Stroke = new SolidColorBrush(lineColor),
|
||||
StrokeThickness = 1,
|
||||
StrokeDashArray = new Avalonia.Collections.AvaloniaList<double> { dashLength, gapLength },
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
GridPreviewLinesCanvas.Children.Add(line);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyGridPreviewWidgetSizing(double cellSize)
|
||||
{
|
||||
var margin = Math.Clamp(cellSize * 0.08, 1, 6);
|
||||
var previewTaskbarCell = Math.Clamp(cellSize, 10, 36);
|
||||
var iconSize = Math.Clamp(cellSize * 0.35, 8, 16);
|
||||
|
||||
GridPreviewTopStatusBarHost.Padding = new Thickness(Math.Clamp(cellSize * 0.08, 1, 4));
|
||||
GridPreviewBottomTaskbarContainer.Margin = new Thickness(margin);
|
||||
GridPreviewBottomTaskbarContainer.CornerRadius = new CornerRadius(Math.Clamp(cellSize * 0.22, 4, 10));
|
||||
GridPreviewBottomTaskbarContainer.Padding = new Thickness(Math.Clamp(cellSize * 0.06, 1, 4));
|
||||
|
||||
GridPreviewBackButtonTextBlock.FontSize = Math.Clamp(cellSize * 0.19, 5, 13);
|
||||
GridPreviewComponentLibraryTextBlock.FontSize = Math.Clamp(cellSize * 0.18, 5, 12);
|
||||
GridPreviewComponentLibraryIcon.FontSize = iconSize;
|
||||
GridPreviewBackButtonVisual.MinHeight = previewTaskbarCell;
|
||||
GridPreviewBackButtonVisual.MinWidth = Math.Clamp(cellSize * 2.1, 30, 120);
|
||||
GridPreviewComponentLibraryVisual.MinHeight = previewTaskbarCell;
|
||||
GridPreviewComponentLibraryVisual.MinWidth = Math.Clamp(cellSize * 2.0, 28, 110);
|
||||
GridPreviewSettingsButtonIcon.Width = Math.Clamp(previewTaskbarCell * 0.42, 6, 14);
|
||||
GridPreviewSettingsButtonIcon.Height = Math.Clamp(previewTaskbarCell * 0.42, 6, 14);
|
||||
}
|
||||
|
||||
private void OnApplyGridSizeClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var requested = (int)Math.Round(GridSizeNumberBox.Value);
|
||||
@@ -217,7 +424,13 @@ public partial class MainWindow : Window
|
||||
GridSizeNumberBox.Value = _targetShortSideCells;
|
||||
}
|
||||
|
||||
if (Math.Abs(GridSizeSlider.Value - _targetShortSideCells) > double.Epsilon)
|
||||
{
|
||||
GridSizeSlider.Value = _targetShortSideCells;
|
||||
}
|
||||
|
||||
RebuildDesktopGrid();
|
||||
PersistSettings();
|
||||
}
|
||||
|
||||
private void RebuildDesktopGrid()
|
||||
@@ -328,6 +541,8 @@ public partial class MainWindow : Window
|
||||
var verticalPadding = Math.Clamp(cellSize * 0.08, 2, 12);
|
||||
var horizontalPadding = Math.Clamp(cellSize * 0.20, 4, 22);
|
||||
var taskbarCell = Math.Clamp(cellSize, 28, 128);
|
||||
var unifiedFontSize = Math.Clamp(cellSize * 0.22, 8, 22);
|
||||
var unifiedIconSize = Math.Clamp(cellSize * 0.28, 10, 26);
|
||||
|
||||
TopStatusBarHost.Padding = new Thickness(Math.Clamp(cellSize * 0.08, 1.5, 10));
|
||||
ClockWidget.Margin = new Thickness(margin);
|
||||
@@ -339,24 +554,29 @@ public partial class MainWindow : Window
|
||||
|
||||
BackToWindowsButton.Margin = new Thickness(0);
|
||||
BackToWindowsButton.Padding = new Thickness(horizontalPadding, verticalPadding);
|
||||
BackToWindowsButton.FontSize = Math.Clamp(cellSize * 0.22, 8, 22);
|
||||
BackToWindowsButton.FontSize = unifiedFontSize;
|
||||
BackToWindowsButton.MinHeight = taskbarCell;
|
||||
BackToWindowsButton.MinWidth = Math.Clamp(cellSize * 2.3, 90, 320);
|
||||
BackToWindowsIcon.FontSize = unifiedIconSize;
|
||||
|
||||
OpenComponentLibraryButton.Margin = new Thickness(0);
|
||||
OpenComponentLibraryButton.Padding = new Thickness(horizontalPadding, verticalPadding);
|
||||
OpenComponentLibraryButton.FontSize = Math.Clamp(cellSize * 0.22, 8, 22);
|
||||
OpenComponentLibraryButton.FontSize = unifiedFontSize;
|
||||
OpenComponentLibraryButton.MinHeight = taskbarCell;
|
||||
OpenComponentLibraryButton.MinWidth = Math.Clamp(cellSize * 2.0, 88, 300);
|
||||
OpenComponentLibraryIcon.FontSize = unifiedIconSize;
|
||||
|
||||
OpenSettingsButton.Margin = new Thickness(0);
|
||||
OpenSettingsButton.Height = taskbarCell;
|
||||
OpenSettingsButton.MinHeight = taskbarCell;
|
||||
OpenSettingsIcon.FontSize = unifiedIconSize;
|
||||
|
||||
if (_isSettingsOpen)
|
||||
{
|
||||
OpenSettingsButton.Width = double.NaN;
|
||||
OpenSettingsButton.MinWidth = Math.Clamp(cellSize * 2.3, 120, 340);
|
||||
OpenSettingsButton.Padding = new Thickness(horizontalPadding, verticalPadding);
|
||||
OpenSettingsButton.FontSize = unifiedFontSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -435,21 +655,23 @@ public partial class MainWindow : Window
|
||||
var desktopHeight = Math.Max(1, DesktopHost.Bounds.Height);
|
||||
var aspectRatio = desktopWidth / desktopHeight;
|
||||
|
||||
// Use the host width (which is roughly 50% of the settings area)
|
||||
// Subtract padding for the outer host container if needed, but let it stretch
|
||||
var availableWidth = Math.Max(100, WallpaperPreviewHost.Bounds.Width);
|
||||
|
||||
// Calculate height based on aspect ratio
|
||||
var framePadding = WallpaperPreviewFrame.Padding;
|
||||
var horizontalPadding = framePadding.Left + framePadding.Right;
|
||||
var verticalPadding = framePadding.Top + framePadding.Bottom;
|
||||
|
||||
var previewWidth = availableWidth;
|
||||
var previewHeight = previewWidth / aspectRatio;
|
||||
|
||||
// Apply sizes to the monitor frame
|
||||
WallpaperPreviewFrame.Width = previewWidth;
|
||||
WallpaperPreviewFrame.Height = previewHeight;
|
||||
|
||||
WallpaperPreviewClockTextBlock.Text = DateTime.Now.ToString("HH:mm");
|
||||
|
||||
var gridMetrics = CalculateGridMetrics(previewWidth, previewHeight, _targetShortSideCells);
|
||||
var innerWidth = Math.Max(1, previewWidth - horizontalPadding);
|
||||
var innerHeight = Math.Max(1, previewHeight - verticalPadding);
|
||||
var gridMetrics = CalculateGridMetrics(innerWidth, innerHeight, _targetShortSideCells);
|
||||
if (gridMetrics.CellSize <= 0)
|
||||
{
|
||||
return;
|
||||
@@ -542,4 +764,44 @@ public partial class MainWindow : Window
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeTimeZoneSettings()
|
||||
{
|
||||
// 填充时区下拉框
|
||||
TimeZoneComboBox.Items.Clear();
|
||||
var timeZones = _timeZoneService.GetAllTimeZones();
|
||||
foreach (var tz in timeZones)
|
||||
{
|
||||
var displayText = _timeZoneService.GetTimeZoneDisplayName(tz);
|
||||
var item = new ComboBoxItem
|
||||
{
|
||||
Content = displayText,
|
||||
Tag = tz.Id
|
||||
};
|
||||
TimeZoneComboBox.Items.Add(item);
|
||||
|
||||
// 选中当前时区
|
||||
if (tz.Id == _timeZoneService.CurrentTimeZone.Id)
|
||||
{
|
||||
TimeZoneComboBox.SelectedItem = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTimeZoneSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (_suppressLanguageSelectionEvents || TimeZoneComboBox.SelectedItem is not ComboBoxItem item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var timeZoneId = item.Tag?.ToString();
|
||||
if (string.IsNullOrEmpty(timeZoneId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_timeZoneService.SetTimeZoneById(timeZoneId);
|
||||
PersistSettings();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user