diff --git a/LanMontainDesktop/ComponentSystem/ComponentRegistry.cs b/LanMontainDesktop/ComponentSystem/ComponentRegistry.cs index 3b0a37c..f829c1a 100644 --- a/LanMontainDesktop/ComponentSystem/ComponentRegistry.cs +++ b/LanMontainDesktop/ComponentSystem/ComponentRegistry.cs @@ -92,7 +92,8 @@ public sealed class ComponentRegistry MinWidthCells: 2, MinHeightCells: 4, AllowStatusBarPlacement: false, - AllowDesktopPlacement: true), + AllowDesktopPlacement: true, + ResizeMode: DesktopComponentResizeMode.Free), new DesktopComponentDefinition( BuiltInComponentIds.DesktopBlackboardLandscape, "Blackboard Landscape", @@ -101,7 +102,8 @@ public sealed class ComponentRegistry MinWidthCells: 4, MinHeightCells: 2, AllowStatusBarPlacement: false, - AllowDesktopPlacement: true), + AllowDesktopPlacement: true, + ResizeMode: DesktopComponentResizeMode.Free), new DesktopComponentDefinition( BuiltInComponentIds.Date, "Calendar", diff --git a/LanMontainDesktop/ComponentSystem/DesktopComponentDefinition.cs b/LanMontainDesktop/ComponentSystem/DesktopComponentDefinition.cs index 526f1fc..d2ca250 100644 --- a/LanMontainDesktop/ComponentSystem/DesktopComponentDefinition.cs +++ b/LanMontainDesktop/ComponentSystem/DesktopComponentDefinition.cs @@ -8,4 +8,5 @@ public sealed record DesktopComponentDefinition( int MinWidthCells, int MinHeightCells, bool AllowStatusBarPlacement, - bool AllowDesktopPlacement); + bool AllowDesktopPlacement, + DesktopComponentResizeMode ResizeMode = DesktopComponentResizeMode.Proportional); diff --git a/LanMontainDesktop/ComponentSystem/DesktopComponentResizeMode.cs b/LanMontainDesktop/ComponentSystem/DesktopComponentResizeMode.cs new file mode 100644 index 0000000..acfdfad --- /dev/null +++ b/LanMontainDesktop/ComponentSystem/DesktopComponentResizeMode.cs @@ -0,0 +1,7 @@ +namespace LanMontainDesktop.ComponentSystem; + +public enum DesktopComponentResizeMode +{ + Proportional = 0, + Free = 1 +} diff --git a/LanMontainDesktop/Services/TimeZoneService.cs b/LanMontainDesktop/Services/TimeZoneService.cs index 7afe2a3..df23a3e 100644 --- a/LanMontainDesktop/Services/TimeZoneService.cs +++ b/LanMontainDesktop/Services/TimeZoneService.cs @@ -69,7 +69,7 @@ public sealed class TimeZoneService /// public string GetTimeZoneDisplayName(TimeZoneInfo timeZone) { - var offset = timeZone.BaseUtcOffset; + var offset = timeZone.GetUtcOffset(DateTime.UtcNow); var sign = offset >= TimeSpan.Zero ? "+" : "-"; var hours = Math.Abs(offset.Hours); var minutes = Math.Abs(offset.Minutes); diff --git a/LanMontainDesktop/Services/WindowsStartMenuService.cs b/LanMontainDesktop/Services/WindowsStartMenuService.cs index 106b10f..b2e9b78 100644 --- a/LanMontainDesktop/Services/WindowsStartMenuService.cs +++ b/LanMontainDesktop/Services/WindowsStartMenuService.cs @@ -82,7 +82,7 @@ public sealed class WindowsStartMenuService nameOverride ?? Path.GetFileName(folderPath), relativePath); - foreach (var subFolderPath in Directory.EnumerateDirectories(folderPath)) + foreach (var subFolderPath in EnumerateDirectoriesSafe(folderPath)) { var folderName = Path.GetFileName(subFolderPath); if (folderName.StartsWith(".", StringComparison.Ordinal)) @@ -90,38 +90,76 @@ public sealed class WindowsStartMenuService 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); - if (!SupportedEntryExtensions.Contains(extension)) + try { - continue; - } + var extension = Path.GetExtension(filePath); + if (!SupportedEntryExtensions.Contains(extension)) + { + continue; + } - var fileName = Path.GetFileNameWithoutExtension(filePath); - if (string.IsNullOrWhiteSpace(fileName)) - { - continue; - } + var fileName = Path.GetFileNameWithoutExtension(filePath); + if (string.IsNullOrWhiteSpace(fileName)) + { + continue; + } - var normalizedName = fileName.Replace('_', ' ').Trim(); - folder.Apps.Add(new StartMenuAppEntry + var normalizedName = fileName.Replace('_', ' ').Trim(); + folder.Apps.Add(new StartMenuAppEntry + { + DisplayName = normalizedName, + FilePath = filePath, + RelativePath = Path.GetRelativePath(rootPath, filePath), + IconPngBytes = OperatingSystem.IsWindows() + ? WindowsIconService.TryGetIconPngBytes(filePath) + : null + }); + } + catch { - DisplayName = normalizedName, - FilePath = filePath, - RelativePath = Path.GetRelativePath(rootPath, filePath), - IconPngBytes = OperatingSystem.IsWindows() - ? WindowsIconService.TryGetIconPngBytes(filePath) - : null - }); + // Skip unreadable or invalid entries and continue. + } } return folder; } + private static IEnumerable EnumerateDirectoriesSafe(string folderPath) + { + try + { + return Directory.EnumerateDirectories(folderPath); + } + catch + { + return Array.Empty(); + } + } + + private static IEnumerable EnumerateFilesSafe(string folderPath) + { + try + { + return Directory.EnumerateFiles(folderPath); + } + catch + { + return Array.Empty(); + } + } + private static void MergeFolder(StartMenuFolderNode target, StartMenuFolderNode source) { var appPathSet = new HashSet( diff --git a/LanMontainDesktop/Views/Components/AnalogClockWidget.axaml.cs b/LanMontainDesktop/Views/Components/AnalogClockWidget.axaml.cs index 7718a6d..051135e 100644 --- a/LanMontainDesktop/Views/Components/AnalogClockWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/AnalogClockWidget.axaml.cs @@ -45,16 +45,23 @@ public partial class AnalogClockWidget : UserControl, IDesktopComponentWidget, I public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; UpdateClock(); } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { InitializeDialIfNeeded(); diff --git a/LanMontainDesktop/Views/Components/ClockWidget.axaml.cs b/LanMontainDesktop/Views/Components/ClockWidget.axaml.cs index d5294a4..cb45ebe 100644 --- a/LanMontainDesktop/Views/Components/ClockWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/ClockWidget.axaml.cs @@ -51,16 +51,23 @@ public partial class ClockWidget : UserControl, IDesktopComponentWidget, ITimeZo public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService != null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; UpdateClock(); } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { UpdateClock(); diff --git a/LanMontainDesktop/Views/Components/DateWidget.axaml.cs b/LanMontainDesktop/Views/Components/DateWidget.axaml.cs index 9bc7008..7075397 100644 --- a/LanMontainDesktop/Views/Components/DateWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/DateWidget.axaml.cs @@ -109,16 +109,23 @@ public partial class DateWidget : UserControl, IDesktopComponentWidget, ITimeZon public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; UpdateDate(); } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { UpdateDate(); diff --git a/LanMontainDesktop/Views/Components/DateWidgetSettingsWindow.axaml b/LanMontainDesktop/Views/Components/DateWidgetSettingsWindow.axaml index 56a2b7d..8c4b155 100644 --- a/LanMontainDesktop/Views/Components/DateWidgetSettingsWindow.axaml +++ b/LanMontainDesktop/Views/Components/DateWidgetSettingsWindow.axaml @@ -10,11 +10,11 @@ - - \ No newline at end of file + diff --git a/LanMontainDesktop/Views/Components/HolidayCalendarWidget.axaml.cs b/LanMontainDesktop/Views/Components/HolidayCalendarWidget.axaml.cs index d8eb035..e858f61 100644 --- a/LanMontainDesktop/Views/Components/HolidayCalendarWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/HolidayCalendarWidget.axaml.cs @@ -37,16 +37,23 @@ public partial class HolidayCalendarWidget : UserControl, IDesktopComponentWidge public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; TriggerContentRefresh(); } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { TriggerContentRefresh(); diff --git a/LanMontainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs b/LanMontainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs index 9332c95..97107c1 100644 --- a/LanMontainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs @@ -195,15 +195,22 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; diff --git a/LanMontainDesktop/Views/Components/IDesktopComponentWidget.cs b/LanMontainDesktop/Views/Components/IDesktopComponentWidget.cs index 72c5af8..446c305 100644 --- a/LanMontainDesktop/Views/Components/IDesktopComponentWidget.cs +++ b/LanMontainDesktop/Views/Components/IDesktopComponentWidget.cs @@ -10,6 +10,7 @@ public interface IDesktopComponentWidget public interface ITimeZoneAwareComponentWidget { void SetTimeZoneService(TimeZoneService timeZoneService); + void ClearTimeZoneService(); } public interface IWeatherInfoAwareComponentWidget diff --git a/LanMontainDesktop/Views/Components/LunarCalendarWidget.axaml.cs b/LanMontainDesktop/Views/Components/LunarCalendarWidget.axaml.cs index c099a40..3e70e4c 100644 --- a/LanMontainDesktop/Views/Components/LunarCalendarWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/LunarCalendarWidget.axaml.cs @@ -99,16 +99,23 @@ public partial class LunarCalendarWidget : UserControl, IDesktopComponentWidget, public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; UpdateContent(); } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { UpdateContent(); diff --git a/LanMontainDesktop/Views/Components/MonthCalendarWidget.axaml.cs b/LanMontainDesktop/Views/Components/MonthCalendarWidget.axaml.cs index 825b4df..8746d23 100644 --- a/LanMontainDesktop/Views/Components/MonthCalendarWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/MonthCalendarWidget.axaml.cs @@ -40,16 +40,23 @@ public partial class MonthCalendarWidget : UserControl, IDesktopComponentWidget, public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; UpdateCalendar(); } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) { UpdateCalendar(); diff --git a/LanMontainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs b/LanMontainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs index 82cf576..796ff96 100644 --- a/LanMontainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs @@ -195,15 +195,22 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; diff --git a/LanMontainDesktop/Views/Components/WeatherClockWidget.axaml.cs b/LanMontainDesktop/Views/Components/WeatherClockWidget.axaml.cs index d6a466f..3dbe71d 100644 --- a/LanMontainDesktop/Views/Components/WeatherClockWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/WeatherClockWidget.axaml.cs @@ -75,16 +75,23 @@ public partial class WeatherClockWidget : UserControl, IDesktopComponentWidget, public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; UpdateClockVisual(); } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; diff --git a/LanMontainDesktop/Views/Components/WeatherWidget.axaml.cs b/LanMontainDesktop/Views/Components/WeatherWidget.axaml.cs index a324dbf..d47cc53 100644 --- a/LanMontainDesktop/Views/Components/WeatherWidget.axaml.cs +++ b/LanMontainDesktop/Views/Components/WeatherWidget.axaml.cs @@ -137,15 +137,22 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, ITime public void SetTimeZoneService(TimeZoneService timeZoneService) { - if (_timeZoneService is not null) - { - _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; - } - + ClearTimeZoneService(); _timeZoneService = timeZoneService; _timeZoneService.TimeZoneChanged += OnTimeZoneChanged; } + public void ClearTimeZoneService() + { + if (_timeZoneService is null) + { + return; + } + + _timeZoneService.TimeZoneChanged -= OnTimeZoneChanged; + _timeZoneService = null; + } + public void SetWeatherInfoService(IWeatherInfoService weatherInfoService) { _weatherInfoService = weatherInfoService ?? DefaultWeatherInfoService; diff --git a/LanMontainDesktop/Views/MainWindow.ComponentSystem.cs b/LanMontainDesktop/Views/MainWindow.ComponentSystem.cs index c86e93f..6e8c61a 100644 --- a/LanMontainDesktop/Views/MainWindow.ComponentSystem.cs +++ b/LanMontainDesktop/Views/MainWindow.ComponentSystem.cs @@ -400,6 +400,7 @@ public partial class MainWindow } ComponentLibraryWindow.IsVisible = false; + ClearComponentLibraryPreviewControls(); var shouldReopenSettings = reopenSettings && _reopenSettingsAfterComponentLibraryClose; _reopenSettingsAfterComponentLibraryClose = false; @@ -661,7 +662,8 @@ public partial class MainWindow return; } - // 娴犲海缍夐弽闂磋厬缁夊娅庣紒鍕 + ClearTimeZoneServiceBindings(_selectedDesktopComponentHost); + if (_desktopPageComponentGrids.TryGetValue(placement.PageIndex, out var pageGrid)) { pageGrid.Children.Remove(_selectedDesktopComponentHost); @@ -748,7 +750,7 @@ public partial class MainWindow RebuildDesktopGrid(); PersistSettings(); - // 閺囧瓨鏌婇崝銊︹偓浣锋崲閸斺剝鐖弰鍓с仛 + // Refresh taskbar actions after page count changes. ApplyTaskbarActionVisibility(GetCurrentTaskbarContext()); } @@ -762,6 +764,11 @@ public partial class MainWindow var placementsToRemove = _desktopComponentPlacements .Where(p => p.PageIndex == _currentDesktopSurfaceIndex) .ToList(); + + if (_desktopPageComponentGrids.TryGetValue(_currentDesktopSurfaceIndex, out var pageGrid)) + { + ClearTimeZoneServiceBindings(pageGrid.Children.OfType().ToList()); + } foreach (var placement in placementsToRemove) { @@ -770,7 +777,7 @@ public partial class MainWindow _desktopPageCount = Math.Clamp(_desktopPageCount - 1, MinDesktopPageCount, MaxDesktopPageCount); - // 鐠嬪啯鏆hぐ鎾冲妞ょ敻娼扮槐銏犵穿 + // Clamp current page index to valid range after deletion. _currentDesktopSurfaceIndex = Math.Clamp(_currentDesktopSurfaceIndex, 0, _desktopPageCount - 1); // Update remaining page indices after deletion. @@ -785,7 +792,7 @@ public partial class MainWindow RebuildDesktopGrid(); PersistSettings(); - // 閺囧瓨鏌婇崝銊︹偓浣锋崲閸斺剝鐖弰鍓с仛 + // Refresh taskbar actions after page count changes. ApplyTaskbarActionVisibility(GetCurrentTaskbarContext()); } @@ -842,6 +849,7 @@ public partial class MainWindow return; } + ClearTimeZoneServiceBindings(pageGrid.Children.OfType().ToList()); pageGrid.Children.Clear(); var maxColumns = pageGrid.ColumnDefinitions.Count; @@ -1062,6 +1070,11 @@ public partial class MainWindow runtimeDescriptor.Definition, span.WidthCells, span.HeightCells); + if (runtimeDescriptor.Definition.ResizeMode == DesktopComponentResizeMode.Free) + { + return normalized; + } + return NormalizeAspectRatioForComponent(componentId, normalized); } @@ -1070,6 +1083,16 @@ public partial class MainWindow (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( string componentId, (int WidthCells, int HeightCells) span) @@ -1196,6 +1219,30 @@ public partial class MainWindow return null; } + private static void ClearTimeZoneServiceBindings(IEnumerable 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) { if (host.Child is Grid hostChrome) @@ -1257,6 +1304,7 @@ public partial class MainWindow CancelDesktopComponentResize(restoreOriginalSpan: true); ClearDesktopComponentSelection(); UpdateDesktopComponentHostEditState(); + ClearComponentLibraryPreviewControls(); UpdateComponentLibraryLayout(_currentDesktopCellSize); } @@ -1615,36 +1663,52 @@ public partial class MainWindow var deltaX = pointerInViewport.X - _desktopComponentResize.StartPointerInViewport.X; var deltaY = pointerInViewport.Y - _desktopComponentResize.StartPointerInViewport.Y; - var widthScale = (_desktopComponentResize.StartWidthCells + deltaX / pitch) / _desktopComponentResize.StartWidthCells; - var heightScale = (_desktopComponentResize.StartHeightCells + deltaY / pitch) / _desktopComponentResize.StartHeightCells; - - 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)) + int widthCells; + int heightCells; + if (GetComponentResizeMode(_desktopComponentResize.ComponentId) == DesktopComponentResizeMode.Free) { - 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); } - - if (maxScale < minScale) + else { - 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 widthCells = Math.Clamp( - (int)Math.Round(_desktopComponentResize.StartWidthCells * scale), - _desktopComponentResize.MinWidthCells, - _desktopComponentResize.MaxWidthCells); - var heightCells = Math.Clamp( - (int)Math.Round(_desktopComponentResize.StartHeightCells * scale), - _desktopComponentResize.MinHeightCells, - _desktopComponentResize.MaxHeightCells); + 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; + } + + 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)); widthCells = Math.Clamp(normalized.WidthCells, _desktopComponentResize.MinWidthCells, _desktopComponentResize.MaxWidthCells); @@ -2213,6 +2277,7 @@ public partial class MainWindow _componentLibraryActiveComponents = category.Components; var componentCount = _componentLibraryActiveComponents.Count; + ClearTimeZoneServiceBindings(ComponentLibraryComponentPagesContainer.Children.OfType().ToList()); ComponentLibraryComponentPagesContainer.Children.Clear(); ComponentLibraryComponentPagesContainer.RowDefinitions.Clear(); ComponentLibraryComponentPagesContainer.ColumnDefinitions.Clear(); @@ -2374,6 +2439,19 @@ public partial class MainWindow UpdateComponentLibraryComponentNavigationButtons(); } + private void ClearComponentLibraryPreviewControls() + { + if (ComponentLibraryComponentPagesContainer is null) + { + return; + } + + ClearTimeZoneServiceBindings(ComponentLibraryComponentPagesContainer.Children.OfType().ToList()); + ComponentLibraryComponentPagesContainer.Children.Clear(); + ComponentLibraryComponentPagesContainer.RowDefinitions.Clear(); + ComponentLibraryComponentPagesContainer.ColumnDefinitions.Clear(); + } + private string GetLocalizedComponentDisplayName(DesktopComponentRuntimeDescriptor descriptor) { return L(descriptor.DisplayNameLocalizationKey, descriptor.Definition.DisplayName); diff --git a/LanMontainDesktop/Views/MainWindow.DesktopPaging.cs b/LanMontainDesktop/Views/MainWindow.DesktopPaging.cs index 9ea81cd..76de8d7 100644 --- a/LanMontainDesktop/Views/MainWindow.DesktopPaging.cs +++ b/LanMontainDesktop/Views/MainWindow.DesktopPaging.cs @@ -127,6 +127,7 @@ public partial class MainWindow DesktopPagesContainer.RowDefinitions.Clear(); DesktopPagesContainer.RowDefinitions.Add(new RowDefinition(new GridLength(pageHeight, GridUnitType.Pixel))); DesktopPagesContainer.ColumnDefinitions.Clear(); + ClearTimeZoneServiceBindings(DesktopPagesContainer.Children.OfType().ToList()); DesktopPagesContainer.Children.Clear(); DesktopPagesContainer.Width = pageWidth * _desktopPageCount; DesktopPagesContainer.Height = pageHeight; diff --git a/LanMontainDesktop/Views/MainWindow.Localization.cs b/LanMontainDesktop/Views/MainWindow.Localization.cs index c62738c..9c6a4a3 100644 --- a/LanMontainDesktop/Views/MainWindow.Localization.cs +++ b/LanMontainDesktop/Views/MainWindow.Localization.cs @@ -86,20 +86,22 @@ 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", "编辑桌面"); - WallpaperPreviewComponentLibraryTextBlock.Text = L("button.component_library", "编辑桌面"); - GridPreviewComponentLibraryTextBlock.Text = L("button.component_library", "编辑桌面"); - ToolTip.SetTip(OpenComponentLibraryButton, L("tooltip.component_library", "编辑桌面")); - ComponentLibraryTitleTextBlock.Text = L("component_library.title", "小组件"); + 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", "Widgets"); ToolTip.SetTip(CloseComponentLibraryButton, L("common.close", "Close")); ComponentLibraryEmptyTextBlock.Text = L( "component_library.empty", "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 开始菜单结构显示所有应用与文件夹"); - ToolTip.SetTip(LauncherFolderBackButton, L("common.back", "返回")); - ToolTip.SetTip(LauncherFolderCloseButton, L("common.close", "关闭")); + LauncherTitleTextBlock.Text = L("launcher.title", "App Launcher"); + LauncherSubtitleTextBlock.Text = L( + "launcher.subtitle", + "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"); SettingsNavWallpaperTextBlock.Text = L("settings.nav.wallpaper", "Wallpaper"); @@ -109,11 +111,13 @@ public partial class MainWindow SettingsNavWeatherTextBlock.Text = L("settings.nav.weather", "Weather"); SettingsNavRegionTextBlock.Text = L("settings.nav.region", "Region"); - 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", "重置"); + WallpaperPanelTitleTextBlock.Text = L("settings.wallpaper.title", "Personalize your wallpaper"); + WallpaperPlacementSettingsExpander.Header = L("settings.wallpaper.placement_label", "Placement"); + WallpaperPlacementSettingsExpander.Description = L( + "settings.wallpaper.placement_desc", + "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"); GridSpacingPresetLabelTextBlock.Text = L("settings.grid.spacing_label", "Grid Spacing"); @@ -265,7 +269,7 @@ public partial class MainWindow private string GetLocalizedTimeZoneDisplayName(TimeZoneInfo timeZone) { - var offset = timeZone.BaseUtcOffset; + var offset = timeZone.GetUtcOffset(DateTime.UtcNow); var sign = offset >= TimeSpan.Zero ? "+" : "-"; var hours = Math.Abs(offset.Hours); var minutes = Math.Abs(offset.Minutes); diff --git a/LanMontainDesktop/Views/MainWindow.axaml b/LanMontainDesktop/Views/MainWindow.axaml index 30616ee..fc997a6 100644 --- a/LanMontainDesktop/Views/MainWindow.axaml +++ b/LanMontainDesktop/Views/MainWindow.axaml @@ -476,7 +476,7 @@ FontWeight="SemiBold" Foreground="{DynamicResource AdaptiveTextPrimaryBrush}" Margin="0,0,0,24" - Text="涓€у寲鎮ㄧ殑鑳屾櫙" /> + Text="Personalize Wallpaper" /> + Text="No file selected" /> + Text="Ready" /> @@ -581,13 +581,13 @@ HorizontalAlignment="Stretch" Padding="0,10" Click="OnPickWallpaperClick" - Content="娴忚鐓х墖" /> + Content="Browse" />