mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-25 02:55:55 +08:00
0.2.4
稳定性提升
This commit is contained in:
@@ -92,7 +92,8 @@ public sealed class ComponentRegistry
|
|||||||
MinWidthCells: 2,
|
MinWidthCells: 2,
|
||||||
MinHeightCells: 4,
|
MinHeightCells: 4,
|
||||||
AllowStatusBarPlacement: false,
|
AllowStatusBarPlacement: false,
|
||||||
AllowDesktopPlacement: true),
|
AllowDesktopPlacement: true,
|
||||||
|
ResizeMode: DesktopComponentResizeMode.Free),
|
||||||
new DesktopComponentDefinition(
|
new DesktopComponentDefinition(
|
||||||
BuiltInComponentIds.DesktopBlackboardLandscape,
|
BuiltInComponentIds.DesktopBlackboardLandscape,
|
||||||
"Blackboard Landscape",
|
"Blackboard Landscape",
|
||||||
@@ -101,7 +102,8 @@ public sealed class ComponentRegistry
|
|||||||
MinWidthCells: 4,
|
MinWidthCells: 4,
|
||||||
MinHeightCells: 2,
|
MinHeightCells: 2,
|
||||||
AllowStatusBarPlacement: false,
|
AllowStatusBarPlacement: false,
|
||||||
AllowDesktopPlacement: true),
|
AllowDesktopPlacement: true,
|
||||||
|
ResizeMode: DesktopComponentResizeMode.Free),
|
||||||
new DesktopComponentDefinition(
|
new DesktopComponentDefinition(
|
||||||
BuiltInComponentIds.Date,
|
BuiltInComponentIds.Date,
|
||||||
"Calendar",
|
"Calendar",
|
||||||
|
|||||||
@@ -8,4 +8,5 @@ public sealed record DesktopComponentDefinition(
|
|||||||
int MinWidthCells,
|
int MinWidthCells,
|
||||||
int MinHeightCells,
|
int MinHeightCells,
|
||||||
bool AllowStatusBarPlacement,
|
bool AllowStatusBarPlacement,
|
||||||
bool AllowDesktopPlacement);
|
bool AllowDesktopPlacement,
|
||||||
|
DesktopComponentResizeMode ResizeMode = DesktopComponentResizeMode.Proportional);
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace LanMontainDesktop.ComponentSystem;
|
||||||
|
|
||||||
|
public enum DesktopComponentResizeMode
|
||||||
|
{
|
||||||
|
Proportional = 0,
|
||||||
|
Free = 1
|
||||||
|
}
|
||||||
@@ -69,7 +69,7 @@ public sealed class TimeZoneService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string GetTimeZoneDisplayName(TimeZoneInfo timeZone)
|
public string GetTimeZoneDisplayName(TimeZoneInfo timeZone)
|
||||||
{
|
{
|
||||||
var offset = timeZone.BaseUtcOffset;
|
var offset = timeZone.GetUtcOffset(DateTime.UtcNow);
|
||||||
var sign = offset >= TimeSpan.Zero ? "+" : "-";
|
var sign = offset >= TimeSpan.Zero ? "+" : "-";
|
||||||
var hours = Math.Abs(offset.Hours);
|
var hours = Math.Abs(offset.Hours);
|
||||||
var minutes = Math.Abs(offset.Minutes);
|
var minutes = Math.Abs(offset.Minutes);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public sealed class WindowsStartMenuService
|
|||||||
nameOverride ?? Path.GetFileName(folderPath),
|
nameOverride ?? Path.GetFileName(folderPath),
|
||||||
relativePath);
|
relativePath);
|
||||||
|
|
||||||
foreach (var subFolderPath in Directory.EnumerateDirectories(folderPath))
|
foreach (var subFolderPath in EnumerateDirectoriesSafe(folderPath))
|
||||||
{
|
{
|
||||||
var folderName = Path.GetFileName(subFolderPath);
|
var folderName = Path.GetFileName(subFolderPath);
|
||||||
if (folderName.StartsWith(".", StringComparison.Ordinal))
|
if (folderName.StartsWith(".", StringComparison.Ordinal))
|
||||||
@@ -90,38 +90,76 @@ public sealed class WindowsStartMenuService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
folder.Folders.Add(ScanFolder(subFolderPath, rootPath));
|
try
|
||||||
|
{
|
||||||
|
folder.Folders.Add(ScanFolder(subFolderPath, rootPath));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Skip unreadable branches but continue scanning siblings.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var filePath in Directory.EnumerateFiles(folderPath))
|
foreach (var filePath in EnumerateFilesSafe(folderPath))
|
||||||
{
|
{
|
||||||
var extension = Path.GetExtension(filePath);
|
try
|
||||||
if (!SupportedEntryExtensions.Contains(extension))
|
|
||||||
{
|
{
|
||||||
continue;
|
var extension = Path.GetExtension(filePath);
|
||||||
}
|
if (!SupportedEntryExtensions.Contains(extension))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var fileName = Path.GetFileNameWithoutExtension(filePath);
|
var fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
if (string.IsNullOrWhiteSpace(fileName))
|
if (string.IsNullOrWhiteSpace(fileName))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var normalizedName = fileName.Replace('_', ' ').Trim();
|
var normalizedName = fileName.Replace('_', ' ').Trim();
|
||||||
folder.Apps.Add(new StartMenuAppEntry
|
folder.Apps.Add(new StartMenuAppEntry
|
||||||
|
{
|
||||||
|
DisplayName = normalizedName,
|
||||||
|
FilePath = filePath,
|
||||||
|
RelativePath = Path.GetRelativePath(rootPath, filePath),
|
||||||
|
IconPngBytes = OperatingSystem.IsWindows()
|
||||||
|
? WindowsIconService.TryGetIconPngBytes(filePath)
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
{
|
{
|
||||||
DisplayName = normalizedName,
|
// Skip unreadable or invalid entries and continue.
|
||||||
FilePath = filePath,
|
}
|
||||||
RelativePath = Path.GetRelativePath(rootPath, filePath),
|
|
||||||
IconPngBytes = OperatingSystem.IsWindows()
|
|
||||||
? WindowsIconService.TryGetIconPngBytes(filePath)
|
|
||||||
: null
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> EnumerateDirectoriesSafe(string folderPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Directory.EnumerateDirectories(folderPath);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Array.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> EnumerateFilesSafe(string folderPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Directory.EnumerateFiles(folderPath);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Array.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void MergeFolder(StartMenuFolderNode target, StartMenuFolderNode source)
|
private static void MergeFolder(StartMenuFolderNode target, StartMenuFolderNode source)
|
||||||
{
|
{
|
||||||
var appPathSet = new HashSet<string>(
|
var appPathSet = new HashSet<string>(
|
||||||
|
|||||||
@@ -45,16 +45,23 @@ public partial class AnalogClockWidget : UserControl, IDesktopComponentWidget, I
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
UpdateClock();
|
UpdateClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
InitializeDialIfNeeded();
|
InitializeDialIfNeeded();
|
||||||
|
|||||||
@@ -51,16 +51,23 @@ public partial class ClockWidget : UserControl, IDesktopComponentWidget, ITimeZo
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService != null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
UpdateClock();
|
UpdateClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateClock();
|
UpdateClock();
|
||||||
|
|||||||
@@ -109,16 +109,23 @@ public partial class DateWidget : UserControl, IDesktopComponentWidget, ITimeZon
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
UpdateDate();
|
UpdateDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateDate();
|
UpdateDate();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<Border Background="{DynamicResource AdaptiveBackgroundBrush}"
|
<Border Background="{DynamicResource AdaptiveBackgroundBrush}"
|
||||||
Padding="24">
|
Padding="24">
|
||||||
<StackPanel Spacing="16">
|
<StackPanel Spacing="16">
|
||||||
<TextBlock Text="日历组件设置"
|
<TextBlock Text="Date Widget Settings"
|
||||||
FontSize="20"
|
FontSize="20"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||||
|
|||||||
@@ -37,16 +37,23 @@ public partial class HolidayCalendarWidget : UserControl, IDesktopComponentWidge
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
TriggerContentRefresh();
|
TriggerContentRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
TriggerContentRefresh();
|
TriggerContentRefresh();
|
||||||
|
|||||||
@@ -195,15 +195,22 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget,
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
||||||
{
|
{
|
||||||
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ public interface IDesktopComponentWidget
|
|||||||
public interface ITimeZoneAwareComponentWidget
|
public interface ITimeZoneAwareComponentWidget
|
||||||
{
|
{
|
||||||
void SetTimeZoneService(TimeZoneService timeZoneService);
|
void SetTimeZoneService(TimeZoneService timeZoneService);
|
||||||
|
void ClearTimeZoneService();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IWeatherInfoAwareComponentWidget
|
public interface IWeatherInfoAwareComponentWidget
|
||||||
|
|||||||
@@ -99,16 +99,23 @@ public partial class LunarCalendarWidget : UserControl, IDesktopComponentWidget,
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
UpdateContent();
|
UpdateContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateContent();
|
UpdateContent();
|
||||||
|
|||||||
@@ -40,16 +40,23 @@ public partial class MonthCalendarWidget : UserControl, IDesktopComponentWidget,
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
UpdateCalendar();
|
UpdateCalendar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
UpdateCalendar();
|
UpdateCalendar();
|
||||||
|
|||||||
@@ -195,15 +195,22 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
||||||
{
|
{
|
||||||
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
||||||
|
|||||||
@@ -75,16 +75,23 @@ public partial class WeatherClockWidget : UserControl, IDesktopComponentWidget,
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
UpdateClockVisual();
|
UpdateClockVisual();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
||||||
{
|
{
|
||||||
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
||||||
|
|||||||
@@ -137,15 +137,22 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime
|
|||||||
|
|
||||||
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
public void SetTimeZoneService(TimeZoneService timeZoneService)
|
||||||
{
|
{
|
||||||
if (_timeZoneService is not null)
|
ClearTimeZoneService();
|
||||||
{
|
|
||||||
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeZoneService = timeZoneService;
|
_timeZoneService = timeZoneService;
|
||||||
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
_timeZoneService.TimeZoneChanged += OnTimeZoneChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearTimeZoneService()
|
||||||
|
{
|
||||||
|
if (_timeZoneService is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timeZoneService.TimeZoneChanged -= OnTimeZoneChanged;
|
||||||
|
_timeZoneService = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
public void SetWeatherInfoService(IWeatherInfoService weatherInfoService)
|
||||||
{
|
{
|
||||||
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
_weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService;
|
||||||
|
|||||||
@@ -400,6 +400,7 @@ public partial class MainWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComponentLibraryWindow.IsVisible = false;
|
ComponentLibraryWindow.IsVisible = false;
|
||||||
|
ClearComponentLibraryPreviewControls();
|
||||||
|
|
||||||
var shouldReopenSettings = reopenSettings && _reopenSettingsAfterComponentLibraryClose;
|
var shouldReopenSettings = reopenSettings && _reopenSettingsAfterComponentLibraryClose;
|
||||||
_reopenSettingsAfterComponentLibraryClose = false;
|
_reopenSettingsAfterComponentLibraryClose = false;
|
||||||
@@ -661,7 +662,8 @@ public partial class MainWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 娴犲海缍夐弽闂磋厬缁夊娅庣紒鍕
|
ClearTimeZoneServiceBindings(_selectedDesktopComponentHost);
|
||||||
|
|
||||||
if (_desktopPageComponentGrids.TryGetValue(placement.PageIndex, out var pageGrid))
|
if (_desktopPageComponentGrids.TryGetValue(placement.PageIndex, out var pageGrid))
|
||||||
{
|
{
|
||||||
pageGrid.Children.Remove(_selectedDesktopComponentHost);
|
pageGrid.Children.Remove(_selectedDesktopComponentHost);
|
||||||
@@ -748,7 +750,7 @@ public partial class MainWindow
|
|||||||
RebuildDesktopGrid();
|
RebuildDesktopGrid();
|
||||||
PersistSettings();
|
PersistSettings();
|
||||||
|
|
||||||
// 閺囧瓨鏌婇崝銊︹偓浣锋崲閸斺剝鐖弰鍓с仛
|
// Refresh taskbar actions after page count changes.
|
||||||
ApplyTaskbarActionVisibility(GetCurrentTaskbarContext());
|
ApplyTaskbarActionVisibility(GetCurrentTaskbarContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,6 +765,11 @@ public partial class MainWindow
|
|||||||
.Where(p => p.PageIndex == _currentDesktopSurfaceIndex)
|
.Where(p => p.PageIndex == _currentDesktopSurfaceIndex)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
if (_desktopPageComponentGrids.TryGetValue(_currentDesktopSurfaceIndex, out var pageGrid))
|
||||||
|
{
|
||||||
|
ClearTimeZoneServiceBindings(pageGrid.Children.OfType<Control>().ToList());
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var placement in placementsToRemove)
|
foreach (var placement in placementsToRemove)
|
||||||
{
|
{
|
||||||
_desktopComponentPlacements.Remove(placement);
|
_desktopComponentPlacements.Remove(placement);
|
||||||
@@ -770,7 +777,7 @@ public partial class MainWindow
|
|||||||
|
|
||||||
_desktopPageCount = Math.Clamp(_desktopPageCount - 1, MinDesktopPageCount, MaxDesktopPageCount);
|
_desktopPageCount = Math.Clamp(_desktopPageCount - 1, MinDesktopPageCount, MaxDesktopPageCount);
|
||||||
|
|
||||||
// 鐠嬪啯鏆hぐ鎾冲妞ょ敻娼扮槐銏犵穿
|
// Clamp current page index to valid range after deletion.
|
||||||
_currentDesktopSurfaceIndex = Math.Clamp(_currentDesktopSurfaceIndex, 0, _desktopPageCount - 1);
|
_currentDesktopSurfaceIndex = Math.Clamp(_currentDesktopSurfaceIndex, 0, _desktopPageCount - 1);
|
||||||
|
|
||||||
// Update remaining page indices after deletion.
|
// Update remaining page indices after deletion.
|
||||||
@@ -785,7 +792,7 @@ public partial class MainWindow
|
|||||||
RebuildDesktopGrid();
|
RebuildDesktopGrid();
|
||||||
PersistSettings();
|
PersistSettings();
|
||||||
|
|
||||||
// 閺囧瓨鏌婇崝銊︹偓浣锋崲閸斺剝鐖弰鍓с仛
|
// Refresh taskbar actions after page count changes.
|
||||||
ApplyTaskbarActionVisibility(GetCurrentTaskbarContext());
|
ApplyTaskbarActionVisibility(GetCurrentTaskbarContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,6 +849,7 @@ public partial class MainWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClearTimeZoneServiceBindings(pageGrid.Children.OfType<Control>().ToList());
|
||||||
pageGrid.Children.Clear();
|
pageGrid.Children.Clear();
|
||||||
|
|
||||||
var maxColumns = pageGrid.ColumnDefinitions.Count;
|
var maxColumns = pageGrid.ColumnDefinitions.Count;
|
||||||
@@ -1062,6 +1070,11 @@ public partial class MainWindow
|
|||||||
runtimeDescriptor.Definition,
|
runtimeDescriptor.Definition,
|
||||||
span.WidthCells,
|
span.WidthCells,
|
||||||
span.HeightCells);
|
span.HeightCells);
|
||||||
|
if (runtimeDescriptor.Definition.ResizeMode == DesktopComponentResizeMode.Free)
|
||||||
|
{
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
return NormalizeAspectRatioForComponent(componentId, normalized);
|
return NormalizeAspectRatioForComponent(componentId, normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1070,6 +1083,16 @@ public partial class MainWindow
|
|||||||
(Math.Max(1, span.WidthCells), Math.Max(1, span.HeightCells)));
|
(Math.Max(1, span.WidthCells), Math.Max(1, span.HeightCells)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DesktopComponentResizeMode GetComponentResizeMode(string componentId)
|
||||||
|
{
|
||||||
|
if (_componentRuntimeRegistry.TryGetDescriptor(componentId, out var runtimeDescriptor))
|
||||||
|
{
|
||||||
|
return runtimeDescriptor.Definition.ResizeMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DesktopComponentResizeMode.Proportional;
|
||||||
|
}
|
||||||
|
|
||||||
private static (int WidthCells, int HeightCells) NormalizeAspectRatioForComponent(
|
private static (int WidthCells, int HeightCells) NormalizeAspectRatioForComponent(
|
||||||
string componentId,
|
string componentId,
|
||||||
(int WidthCells, int HeightCells) span)
|
(int WidthCells, int HeightCells) span)
|
||||||
@@ -1196,6 +1219,30 @@ public partial class MainWindow
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ClearTimeZoneServiceBindings(IEnumerable<Control> roots)
|
||||||
|
{
|
||||||
|
foreach (var root in roots)
|
||||||
|
{
|
||||||
|
ClearTimeZoneServiceBindings(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ClearTimeZoneServiceBindings(Control root)
|
||||||
|
{
|
||||||
|
if (root is ITimeZoneAwareComponentWidget timeZoneAwareRoot)
|
||||||
|
{
|
||||||
|
timeZoneAwareRoot.ClearTimeZoneService();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var descendant in root.GetVisualDescendants())
|
||||||
|
{
|
||||||
|
if (descendant is ITimeZoneAwareComponentWidget timeZoneAwareChild)
|
||||||
|
{
|
||||||
|
timeZoneAwareChild.ClearTimeZoneService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Border? TryGetResizeHandle(Border host)
|
private static Border? TryGetResizeHandle(Border host)
|
||||||
{
|
{
|
||||||
if (host.Child is Grid hostChrome)
|
if (host.Child is Grid hostChrome)
|
||||||
@@ -1257,6 +1304,7 @@ public partial class MainWindow
|
|||||||
CancelDesktopComponentResize(restoreOriginalSpan: true);
|
CancelDesktopComponentResize(restoreOriginalSpan: true);
|
||||||
ClearDesktopComponentSelection();
|
ClearDesktopComponentSelection();
|
||||||
UpdateDesktopComponentHostEditState();
|
UpdateDesktopComponentHostEditState();
|
||||||
|
ClearComponentLibraryPreviewControls();
|
||||||
UpdateComponentLibraryLayout(_currentDesktopCellSize);
|
UpdateComponentLibraryLayout(_currentDesktopCellSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1615,36 +1663,52 @@ public partial class MainWindow
|
|||||||
|
|
||||||
var deltaX = pointerInViewport.X - _desktopComponentResize.StartPointerInViewport.X;
|
var deltaX = pointerInViewport.X - _desktopComponentResize.StartPointerInViewport.X;
|
||||||
var deltaY = pointerInViewport.Y - _desktopComponentResize.StartPointerInViewport.Y;
|
var deltaY = pointerInViewport.Y - _desktopComponentResize.StartPointerInViewport.Y;
|
||||||
var widthScale = (_desktopComponentResize.StartWidthCells + deltaX / pitch) / _desktopComponentResize.StartWidthCells;
|
int widthCells;
|
||||||
var heightScale = (_desktopComponentResize.StartHeightCells + deltaY / pitch) / _desktopComponentResize.StartHeightCells;
|
int heightCells;
|
||||||
|
if (GetComponentResizeMode(_desktopComponentResize.ComponentId) == DesktopComponentResizeMode.Free)
|
||||||
var proposedScale = Math.Max(widthScale, heightScale);
|
|
||||||
var minScale = Math.Max(
|
|
||||||
(double)_desktopComponentResize.MinWidthCells / _desktopComponentResize.StartWidthCells,
|
|
||||||
(double)_desktopComponentResize.MinHeightCells / _desktopComponentResize.StartHeightCells);
|
|
||||||
var maxScale = Math.Min(
|
|
||||||
(double)_desktopComponentResize.MaxWidthCells / _desktopComponentResize.StartWidthCells,
|
|
||||||
(double)_desktopComponentResize.MaxHeightCells / _desktopComponentResize.StartHeightCells);
|
|
||||||
|
|
||||||
if (double.IsNaN(proposedScale) || double.IsInfinity(proposedScale))
|
|
||||||
{
|
{
|
||||||
proposedScale = minScale;
|
widthCells = Math.Clamp(
|
||||||
|
(int)Math.Round(_desktopComponentResize.StartWidthCells + deltaX / pitch),
|
||||||
|
_desktopComponentResize.MinWidthCells,
|
||||||
|
_desktopComponentResize.MaxWidthCells);
|
||||||
|
heightCells = Math.Clamp(
|
||||||
|
(int)Math.Round(_desktopComponentResize.StartHeightCells + deltaY / pitch),
|
||||||
|
_desktopComponentResize.MinHeightCells,
|
||||||
|
_desktopComponentResize.MaxHeightCells);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (maxScale < minScale)
|
|
||||||
{
|
{
|
||||||
maxScale = minScale;
|
var widthScale = (_desktopComponentResize.StartWidthCells + deltaX / pitch) / _desktopComponentResize.StartWidthCells;
|
||||||
}
|
var heightScale = (_desktopComponentResize.StartHeightCells + deltaY / pitch) / _desktopComponentResize.StartHeightCells;
|
||||||
|
|
||||||
var scale = Math.Clamp(proposedScale, minScale, maxScale);
|
var proposedScale = Math.Max(widthScale, heightScale);
|
||||||
var widthCells = Math.Clamp(
|
var minScale = Math.Max(
|
||||||
(int)Math.Round(_desktopComponentResize.StartWidthCells * scale),
|
(double)_desktopComponentResize.MinWidthCells / _desktopComponentResize.StartWidthCells,
|
||||||
_desktopComponentResize.MinWidthCells,
|
(double)_desktopComponentResize.MinHeightCells / _desktopComponentResize.StartHeightCells);
|
||||||
_desktopComponentResize.MaxWidthCells);
|
var maxScale = Math.Min(
|
||||||
var heightCells = Math.Clamp(
|
(double)_desktopComponentResize.MaxWidthCells / _desktopComponentResize.StartWidthCells,
|
||||||
(int)Math.Round(_desktopComponentResize.StartHeightCells * scale),
|
(double)_desktopComponentResize.MaxHeightCells / _desktopComponentResize.StartHeightCells);
|
||||||
_desktopComponentResize.MinHeightCells,
|
|
||||||
_desktopComponentResize.MaxHeightCells);
|
if (double.IsNaN(proposedScale) || double.IsInfinity(proposedScale))
|
||||||
|
{
|
||||||
|
proposedScale = minScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxScale < minScale)
|
||||||
|
{
|
||||||
|
maxScale = minScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scale = Math.Clamp(proposedScale, minScale, maxScale);
|
||||||
|
widthCells = Math.Clamp(
|
||||||
|
(int)Math.Round(_desktopComponentResize.StartWidthCells * scale),
|
||||||
|
_desktopComponentResize.MinWidthCells,
|
||||||
|
_desktopComponentResize.MaxWidthCells);
|
||||||
|
heightCells = Math.Clamp(
|
||||||
|
(int)Math.Round(_desktopComponentResize.StartHeightCells * scale),
|
||||||
|
_desktopComponentResize.MinHeightCells,
|
||||||
|
_desktopComponentResize.MaxHeightCells);
|
||||||
|
}
|
||||||
|
|
||||||
var normalized = NormalizeComponentCellSpan(_desktopComponentResize.ComponentId, (widthCells, heightCells));
|
var normalized = NormalizeComponentCellSpan(_desktopComponentResize.ComponentId, (widthCells, heightCells));
|
||||||
widthCells = Math.Clamp(normalized.WidthCells, _desktopComponentResize.MinWidthCells, _desktopComponentResize.MaxWidthCells);
|
widthCells = Math.Clamp(normalized.WidthCells, _desktopComponentResize.MinWidthCells, _desktopComponentResize.MaxWidthCells);
|
||||||
@@ -2213,6 +2277,7 @@ public partial class MainWindow
|
|||||||
_componentLibraryActiveComponents = category.Components;
|
_componentLibraryActiveComponents = category.Components;
|
||||||
var componentCount = _componentLibraryActiveComponents.Count;
|
var componentCount = _componentLibraryActiveComponents.Count;
|
||||||
|
|
||||||
|
ClearTimeZoneServiceBindings(ComponentLibraryComponentPagesContainer.Children.OfType<Control>().ToList());
|
||||||
ComponentLibraryComponentPagesContainer.Children.Clear();
|
ComponentLibraryComponentPagesContainer.Children.Clear();
|
||||||
ComponentLibraryComponentPagesContainer.RowDefinitions.Clear();
|
ComponentLibraryComponentPagesContainer.RowDefinitions.Clear();
|
||||||
ComponentLibraryComponentPagesContainer.ColumnDefinitions.Clear();
|
ComponentLibraryComponentPagesContainer.ColumnDefinitions.Clear();
|
||||||
@@ -2374,6 +2439,19 @@ public partial class MainWindow
|
|||||||
UpdateComponentLibraryComponentNavigationButtons();
|
UpdateComponentLibraryComponentNavigationButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ClearComponentLibraryPreviewControls()
|
||||||
|
{
|
||||||
|
if (ComponentLibraryComponentPagesContainer is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearTimeZoneServiceBindings(ComponentLibraryComponentPagesContainer.Children.OfType<Control>().ToList());
|
||||||
|
ComponentLibraryComponentPagesContainer.Children.Clear();
|
||||||
|
ComponentLibraryComponentPagesContainer.RowDefinitions.Clear();
|
||||||
|
ComponentLibraryComponentPagesContainer.ColumnDefinitions.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
private string GetLocalizedComponentDisplayName(DesktopComponentRuntimeDescriptor descriptor)
|
private string GetLocalizedComponentDisplayName(DesktopComponentRuntimeDescriptor descriptor)
|
||||||
{
|
{
|
||||||
return L(descriptor.DisplayNameLocalizationKey, descriptor.Definition.DisplayName);
|
return L(descriptor.DisplayNameLocalizationKey, descriptor.Definition.DisplayName);
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ public partial class MainWindow
|
|||||||
DesktopPagesContainer.RowDefinitions.Clear();
|
DesktopPagesContainer.RowDefinitions.Clear();
|
||||||
DesktopPagesContainer.RowDefinitions.Add(new RowDefinition(new GridLength(pageHeight, GridUnitType.Pixel)));
|
DesktopPagesContainer.RowDefinitions.Add(new RowDefinition(new GridLength(pageHeight, GridUnitType.Pixel)));
|
||||||
DesktopPagesContainer.ColumnDefinitions.Clear();
|
DesktopPagesContainer.ColumnDefinitions.Clear();
|
||||||
|
ClearTimeZoneServiceBindings(DesktopPagesContainer.Children.OfType<Control>().ToList());
|
||||||
DesktopPagesContainer.Children.Clear();
|
DesktopPagesContainer.Children.Clear();
|
||||||
DesktopPagesContainer.Width = pageWidth * _desktopPageCount;
|
DesktopPagesContainer.Width = pageWidth * _desktopPageCount;
|
||||||
DesktopPagesContainer.Height = pageHeight;
|
DesktopPagesContainer.Height = pageHeight;
|
||||||
|
|||||||
@@ -86,20 +86,22 @@ public partial class MainWindow
|
|||||||
WallpaperPreviewBackButtonTextBlock.Text = L("button.back_to_windows", "Back to Windows");
|
WallpaperPreviewBackButtonTextBlock.Text = L("button.back_to_windows", "Back to Windows");
|
||||||
ToolTip.SetTip(BackToWindowsButton, L("tooltip.back_to_windows", "Back to Windows"));
|
ToolTip.SetTip(BackToWindowsButton, L("tooltip.back_to_windows", "Back to Windows"));
|
||||||
|
|
||||||
OpenComponentLibraryTextBlock.Text = L("button.component_library", "编辑桌面");
|
OpenComponentLibraryTextBlock.Text = L("button.component_library", "Edit Desktop");
|
||||||
WallpaperPreviewComponentLibraryTextBlock.Text = L("button.component_library", "编辑桌面");
|
WallpaperPreviewComponentLibraryTextBlock.Text = L("button.component_library", "Edit Desktop");
|
||||||
GridPreviewComponentLibraryTextBlock.Text = L("button.component_library", "编辑桌面");
|
GridPreviewComponentLibraryTextBlock.Text = L("button.component_library", "Edit Desktop");
|
||||||
ToolTip.SetTip(OpenComponentLibraryButton, L("tooltip.component_library", "编辑桌面"));
|
ToolTip.SetTip(OpenComponentLibraryButton, L("tooltip.component_library", "Edit Desktop"));
|
||||||
ComponentLibraryTitleTextBlock.Text = L("component_library.title", "小组件");
|
ComponentLibraryTitleTextBlock.Text = L("component_library.title", "Widgets");
|
||||||
ToolTip.SetTip(CloseComponentLibraryButton, L("common.close", "Close"));
|
ToolTip.SetTip(CloseComponentLibraryButton, L("common.close", "Close"));
|
||||||
ComponentLibraryEmptyTextBlock.Text = L(
|
ComponentLibraryEmptyTextBlock.Text = L(
|
||||||
"component_library.empty",
|
"component_library.empty",
|
||||||
"Swipe to pick a category, tap to open, then drag a widget onto the desktop.");
|
"Swipe to pick a category, tap to open, then drag a widget onto the desktop.");
|
||||||
|
|
||||||
LauncherTitleTextBlock.Text = L("launcher.title", "应用启动台");
|
LauncherTitleTextBlock.Text = L("launcher.title", "App Launcher");
|
||||||
LauncherSubtitleTextBlock.Text = L("launcher.subtitle", "按 Windows 开始菜单结构显示所有应用与文件夹");
|
LauncherSubtitleTextBlock.Text = L(
|
||||||
ToolTip.SetTip(LauncherFolderBackButton, L("common.back", "返回"));
|
"launcher.subtitle",
|
||||||
ToolTip.SetTip(LauncherFolderCloseButton, L("common.close", "关闭"));
|
"Displays all apps and folders based on the Windows Start menu structure.");
|
||||||
|
ToolTip.SetTip(LauncherFolderBackButton, L("common.back", "Back"));
|
||||||
|
ToolTip.SetTip(LauncherFolderCloseButton, L("common.close", "Close"));
|
||||||
|
|
||||||
SettingsNavHeaderTextBlock.Text = L("settings.nav_header", "Settings");
|
SettingsNavHeaderTextBlock.Text = L("settings.nav_header", "Settings");
|
||||||
SettingsNavWallpaperTextBlock.Text = L("settings.nav.wallpaper", "Wallpaper");
|
SettingsNavWallpaperTextBlock.Text = L("settings.nav.wallpaper", "Wallpaper");
|
||||||
@@ -109,11 +111,13 @@ public partial class MainWindow
|
|||||||
SettingsNavWeatherTextBlock.Text = L("settings.nav.weather", "Weather");
|
SettingsNavWeatherTextBlock.Text = L("settings.nav.weather", "Weather");
|
||||||
SettingsNavRegionTextBlock.Text = L("settings.nav.region", "Region");
|
SettingsNavRegionTextBlock.Text = L("settings.nav.region", "Region");
|
||||||
|
|
||||||
WallpaperPanelTitleTextBlock.Text = L("settings.wallpaper.title", "个性化我们的背景");
|
WallpaperPanelTitleTextBlock.Text = L("settings.wallpaper.title", "Personalize your wallpaper");
|
||||||
WallpaperPlacementSettingsExpander.Header = L("settings.wallpaper.placement_label", "选择契合度");
|
WallpaperPlacementSettingsExpander.Header = L("settings.wallpaper.placement_label", "Placement");
|
||||||
WallpaperPlacementSettingsExpander.Description = L("settings.wallpaper.placement_desc", "调整图像在桌面上的填充方式。");
|
WallpaperPlacementSettingsExpander.Description = L(
|
||||||
PickWallpaperButton.Content = L("settings.wallpaper.pick_button", "浏览照片");
|
"settings.wallpaper.placement_desc",
|
||||||
ClearWallpaperButton.Content = L("settings.wallpaper.clear_button", "重置");
|
"Adjust how the image fits on the desktop.");
|
||||||
|
PickWallpaperButton.Content = L("settings.wallpaper.pick_button", "Browse");
|
||||||
|
ClearWallpaperButton.Content = L("settings.wallpaper.clear_button", "Reset");
|
||||||
|
|
||||||
GridPanelTitleTextBlock.Text = L("settings.grid.title", "Grid Layout");
|
GridPanelTitleTextBlock.Text = L("settings.grid.title", "Grid Layout");
|
||||||
GridSpacingPresetLabelTextBlock.Text = L("settings.grid.spacing_label", "Grid Spacing");
|
GridSpacingPresetLabelTextBlock.Text = L("settings.grid.spacing_label", "Grid Spacing");
|
||||||
@@ -265,7 +269,7 @@ public partial class MainWindow
|
|||||||
|
|
||||||
private string GetLocalizedTimeZoneDisplayName(TimeZoneInfo timeZone)
|
private string GetLocalizedTimeZoneDisplayName(TimeZoneInfo timeZone)
|
||||||
{
|
{
|
||||||
var offset = timeZone.BaseUtcOffset;
|
var offset = timeZone.GetUtcOffset(DateTime.UtcNow);
|
||||||
var sign = offset >= TimeSpan.Zero ? "+" : "-";
|
var sign = offset >= TimeSpan.Zero ? "+" : "-";
|
||||||
var hours = Math.Abs(offset.Hours);
|
var hours = Math.Abs(offset.Hours);
|
||||||
var minutes = Math.Abs(offset.Minutes);
|
var minutes = Math.Abs(offset.Minutes);
|
||||||
|
|||||||
@@ -476,7 +476,7 @@
|
|||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||||
Margin="0,0,0,24"
|
Margin="0,0,0,24"
|
||||||
Text="涓€у寲鎮ㄧ殑鑳屾櫙" />
|
Text="Personalize Wallpaper" />
|
||||||
|
|
||||||
<!-- Left Column: Monitor Preview -->
|
<!-- Left Column: Monitor Preview -->
|
||||||
<Border x:Name="WallpaperPreviewHost"
|
<Border x:Name="WallpaperPreviewHost"
|
||||||
@@ -563,11 +563,11 @@
|
|||||||
FontWeight="Medium"
|
FontWeight="Medium"
|
||||||
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
Foreground="{DynamicResource AdaptiveTextPrimaryBrush}"
|
||||||
TextTrimming="CharacterEllipsis"
|
TextTrimming="CharacterEllipsis"
|
||||||
Text="鏈€夋嫨鏂囦欢" />
|
Text="No file selected" />
|
||||||
<TextBlock x:Name="WallpaperStatusTextBlock"
|
<TextBlock x:Name="WallpaperStatusTextBlock"
|
||||||
FontSize="12"
|
FontSize="12"
|
||||||
Foreground="{DynamicResource AdaptiveTextMutedBrush}"
|
Foreground="{DynamicResource AdaptiveTextMutedBrush}"
|
||||||
Text="灏辩华" />
|
Text="Ready" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Separator Background="{DynamicResource SurfaceStrokeColorDefaultBrush}" Height="1" Margin="0,8" />
|
<Separator Background="{DynamicResource SurfaceStrokeColorDefaultBrush}" Height="1" Margin="0,8" />
|
||||||
@@ -581,13 +581,13 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Padding="0,10"
|
Padding="0,10"
|
||||||
Click="OnPickWallpaperClick"
|
Click="OnPickWallpaperClick"
|
||||||
Content="娴忚鐓х墖" />
|
Content="Browse" />
|
||||||
<Button x:Name="ClearWallpaperButton"
|
<Button x:Name="ClearWallpaperButton"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Padding="0,10"
|
Padding="0,10"
|
||||||
Click="OnClearWallpaperClick"
|
Click="OnClearWallpaperClick"
|
||||||
Content="閲嶇疆" />
|
Content="Reset" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Border Classes="settings-expander-shell">
|
<Border Classes="settings-expander-shell">
|
||||||
@@ -695,7 +695,7 @@
|
|||||||
<StackPanel Grid.Row="1" Grid.Column="1"
|
<StackPanel Grid.Row="1" Grid.Column="1"
|
||||||
Margin="16,0,0,0"
|
Margin="16,0,0,0"
|
||||||
Spacing="16">
|
Spacing="16">
|
||||||
<TextBlock Text="绔栨帓鏍兼暟" FontSize="16" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
<TextBlock Text="Rows" FontSize="16" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||||
|
|
||||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="12">
|
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="12">
|
||||||
<Slider x:Name="GridSizeSlider"
|
<Slider x:Name="GridSizeSlider"
|
||||||
@@ -754,7 +754,7 @@
|
|||||||
|
|
||||||
<TextBlock x:Name="GridEdgeInsetComputedPxTextBlock"
|
<TextBlock x:Name="GridEdgeInsetComputedPxTextBlock"
|
||||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||||
Text="鈮?0 px" />
|
Text=">= 0 px" />
|
||||||
|
|
||||||
<Button x:Name="ApplyGridButton"
|
<Button x:Name="ApplyGridButton"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
@@ -1005,15 +1005,15 @@
|
|||||||
Unchecked="OnStatusBarClockUnchecked" />
|
Unchecked="OnStatusBarClockUnchecked" />
|
||||||
</ui:SettingsExpander.Footer>
|
</ui:SettingsExpander.Footer>
|
||||||
<StackPanel Margin="0,8,0,0" Spacing="12">
|
<StackPanel Margin="0,8,0,0" Spacing="12">
|
||||||
<TextBlock Text="鏄剧ず鏍煎紡" FontSize="14" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
<TextBlock Text="Display Format" FontSize="14" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
<RadioButton x:Name="ClockFormatHMSSRadio"
|
<RadioButton x:Name="ClockFormatHMSSRadio"
|
||||||
Content="鏃跺垎绉?(HH:mm:ss)"
|
Content="Time with seconds (HH:mm:ss)"
|
||||||
GroupName="ClockFormat"
|
GroupName="ClockFormat"
|
||||||
Checked="OnClockFormatChanged"
|
Checked="OnClockFormatChanged"
|
||||||
Tag="Hms" />
|
Tag="Hms" />
|
||||||
<RadioButton x:Name="ClockFormatHMRadio"
|
<RadioButton x:Name="ClockFormatHMRadio"
|
||||||
Content="鏃跺垎 (HH:mm)"
|
Content="Time (HH:mm)"
|
||||||
GroupName="ClockFormat"
|
GroupName="ClockFormat"
|
||||||
Checked="OnClockFormatChanged"
|
Checked="OnClockFormatChanged"
|
||||||
Tag="Hm" />
|
Tag="Hm" />
|
||||||
@@ -1070,7 +1070,7 @@
|
|||||||
|
|
||||||
<TextBlock x:Name="StatusBarSpacingComputedPxTextBlock"
|
<TextBlock x:Name="StatusBarSpacingComputedPxTextBlock"
|
||||||
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||||
Text="鈮?0 px" />
|
Text=">= 0 px" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ui:SettingsExpander>
|
</ui:SettingsExpander>
|
||||||
</Border>
|
</Border>
|
||||||
@@ -1274,19 +1274,19 @@
|
|||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel x:Name="AboutSettingsPanel" IsVisible="False" Spacing="20">
|
<StackPanel x:Name="AboutSettingsPanel" IsVisible="False" Spacing="20">
|
||||||
<TextBlock x:Name="AboutPanelTitleTextBlock" FontSize="24" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" Text="鍏充簬" />
|
<TextBlock x:Name="AboutPanelTitleTextBlock" FontSize="24" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" Text="About" />
|
||||||
<Border Background="{DynamicResource AdaptiveSurfaceRaisedBrush}" CornerRadius="{DynamicResource DesignCornerRadiusMd}" Padding="20">
|
<Border Background="{DynamicResource AdaptiveSurfaceRaisedBrush}" CornerRadius="{DynamicResource DesignCornerRadiusMd}" Padding="20">
|
||||||
<StackPanel Spacing="12">
|
<StackPanel Spacing="12">
|
||||||
<TextBlock Text="LanMontainDesktop" FontSize="20" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
<TextBlock Text="LanMontainDesktop" FontSize="20" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||||
<TextBlock Text="Modern desktop shell experience." FontSize="13" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
<TextBlock Text="Modern desktop shell experience." FontSize="13" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||||
<Separator Background="{DynamicResource AdaptiveButtonBorderBrush}" Margin="0,8" />
|
<Separator Background="{DynamicResource AdaptiveButtonBorderBrush}" Margin="0,8" />
|
||||||
<TextBlock x:Name="VersionTextBlock" Text="鐗堟湰鍙? 1.0.0" FontSize="13" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
<TextBlock x:Name="VersionTextBlock" Text="Version: 1.0.0" FontSize="13" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" />
|
||||||
<TextBlock x:Name="CodeNameTextBlock" Text="鐗堟湰浠e彿: Administrate" FontSize="13" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveAccentBrush}" />
|
<TextBlock x:Name="CodeNameTextBlock" Text="Code Name: Administrate" FontSize="13" FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveAccentBrush}" />
|
||||||
<TextBlock x:Name="FontInfoTextBlock" Text="字体: MiSans" FontSize="12" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
<TextBlock x:Name="FontInfoTextBlock" Text="Font: MiSans" FontSize="12" Foreground="{DynamicResource AdaptiveTextSecondaryBrush}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
@@ -1314,7 +1314,7 @@
|
|||||||
CornerRadius="36,36,0,0"
|
CornerRadius="36,36,0,0"
|
||||||
Padding="16,12">
|
Padding="16,12">
|
||||||
<Grid ColumnDefinitions="*,Auto">
|
<Grid ColumnDefinitions="*,Auto">
|
||||||
<TextBlock Text="缁勪欢璁剧疆"
|
<TextBlock Text="Component Settings"
|
||||||
FontSize="16"
|
FontSize="16"
|
||||||
FontWeight="SemiBold"
|
FontWeight="SemiBold"
|
||||||
Foreground="White"
|
Foreground="White"
|
||||||
|
|||||||
@@ -795,7 +795,7 @@ public partial class MainWindow : Window
|
|||||||
var spacingPx = Math.Max(0, cellSize) * (percent / 100d);
|
var spacingPx = Math.Max(0, cellSize) * (percent / 100d);
|
||||||
StatusBarSpacingComputedPxTextBlock.Text = Lf(
|
StatusBarSpacingComputedPxTextBlock.Text = Lf(
|
||||||
"settings.status_bar.spacing_custom_px_format",
|
"settings.status_bar.spacing_custom_px_format",
|
||||||
"鈮?{0:F1}px",
|
">= {0:F1}px",
|
||||||
spacingPx);
|
spacingPx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,13 +863,11 @@ public partial class MainWindow : Window
|
|||||||
var shortSidePx = Math.Max(1, Math.Min(hostWidth, hostHeight));
|
var shortSidePx = Math.Max(1, Math.Min(hostWidth, hostHeight));
|
||||||
var baseCell = shortSidePx / cells;
|
var baseCell = shortSidePx / cells;
|
||||||
|
|
||||||
// --- 姣斾緥鍖栫暀鐧?(Proportional Inset) ---
|
// Proportional inset based on user percentage selection.
|
||||||
// 鍏佽鐢ㄦ埛鐧惧垎姣旇皟鑺傦紝浣嗚瀹氭洿鍚堢悊鐨勫熀鍑嗗拰闄愬埗
|
|
||||||
var clampedPercent = Math.Clamp(insetPercent, MinEdgeInsetPercent, MaxEdgeInsetPercent);
|
var clampedPercent = Math.Clamp(insetPercent, MinEdgeInsetPercent, MaxEdgeInsetPercent);
|
||||||
var insetRatio = clampedPercent / 100d;
|
var insetRatio = clampedPercent / 100d;
|
||||||
|
|
||||||
// 纭繚鏈€灏忕暀鐧借兘瀹圭撼涓€瀹氱殑闃村奖鎵╁睍
|
// Keep inset within a practical visual range.
|
||||||
// 鍏佽 0 杈硅窛锛屾渶澶т笂闄愮淮鎸?80px
|
|
||||||
return Math.Clamp(baseCell * insetRatio, 0, 80);
|
return Math.Clamp(baseCell * insetRatio, 0, 80);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1282,7 +1280,7 @@ public partial class MainWindow : Window
|
|||||||
};
|
};
|
||||||
TimeZoneComboBox.Items.Add(item);
|
TimeZoneComboBox.Items.Add(item);
|
||||||
|
|
||||||
// 閫変腑褰撳墠鏃跺尯
|
// Select current time zone.
|
||||||
if (tz.Id == _timeZoneService.CurrentTimeZone.Id)
|
if (tz.Id == _timeZoneService.CurrentTimeZone.Id)
|
||||||
{
|
{
|
||||||
TimeZoneComboBox.SelectedItem = item;
|
TimeZoneComboBox.SelectedItem = item;
|
||||||
|
|||||||
Reference in New Issue
Block a user