From 5d48a03f5772d823316966c60faf23da414026b9 Mon Sep 17 00:00:00 2001 From: lincube Date: Fri, 20 Mar 2026 14:12:40 +0800 Subject: [PATCH] Revert "0.7.0.1" This reverts commit ea8ce1f5ff17fade66e90821c43022e8320a1a36. --- .../Components/AnalogClockWidget.axaml.cs | 57 ++-- .../Components/BaiduHotSearchWidget.axaml.cs | 49 +--- .../BilibiliHotSearchWidget.axaml.cs | 77 +---- .../Views/Components/BrowserWidget.axaml.cs | 27 -- .../Components/ClassScheduleWidget.axaml.cs | 191 +++---------- .../Views/Components/ClockWidget.axaml.cs | 66 +---- .../Components/CnrDailyNewsWidget.axaml.cs | 64 +---- .../Components/DailyArtworkWidget.axaml.cs | 262 ++++++++++++++++-- .../Components/DailyPoetryWidget.axaml.cs | 129 ++++++--- .../ExchangeRateCalculatorWidget.axaml.cs | 102 ------- .../Components/ExtendedWeatherWidget.axaml.cs | 166 ++--------- .../Components/HourlyWeatherWidget.axaml.cs | 120 ++------ .../Views/Components/IfengNewsWidget.axaml.cs | 21 +- .../Components/MultiDayWeatherWidget.axaml.cs | 120 ++------ .../Components/MusicControlWidget.axaml.cs | 64 ----- .../OfficeRecentDocumentsWidget.axaml.cs | 77 +---- .../Views/Components/RecordingWidget.axaml.cs | 102 +++---- .../RemovableStorageWidget.axaml.cs | 71 +---- .../Components/Stcn24ForumWidget.axaml.cs | 28 +- .../StudyDeductionReasonsWidget.axaml.cs | 83 ------ .../StudyEnvironmentWidget.axaml.cs | 72 ----- .../StudyInterruptDensityWidget.axaml.cs | 87 ------ .../Components/StudyNoiseCurveWidget.axaml.cs | 45 --- .../StudyNoiseDistributionWidget.axaml.cs | 80 ------ .../StudyScoreOverviewWidget.axaml.cs | 87 ------ .../StudySessionControlWidget.axaml.cs | 35 --- .../StudySessionHistoryWidget.axaml.cs | 151 ++-------- .../Views/Components/TimerWidget.axaml.cs | 48 ---- .../Components/WeatherClockWidget.axaml.cs | 31 +-- .../Views/Components/WeatherWidget.axaml.cs | 90 +----- .../Components/WorldClockWidget.axaml.cs | 134 ++------- 31 files changed, 602 insertions(+), 2134 deletions(-) diff --git a/LanMountainDesktop/Views/Components/AnalogClockWidget.axaml.cs b/LanMountainDesktop/Views/Components/AnalogClockWidget.axaml.cs index dc41f3b..30e769b 100644 --- a/LanMountainDesktop/Views/Components/AnalogClockWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/AnalogClockWidget.axaml.cs @@ -7,7 +7,6 @@ using Avalonia.Controls.Shapes; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Models; using LanMountainDesktop.PluginSdk; @@ -66,7 +65,6 @@ public partial class AnalogClockWidget : UserControl, IDesktopComponentWidget, I private readonly LocalizationService _localizationService = new(); private TimeZoneService? _timeZoneService; private double _currentCellSize = 48; - private double _layoutScale = 1d; private bool _dialInitialized; private bool _handsInitialized; private bool? _isNightModeApplied; @@ -187,18 +185,17 @@ public partial class AnalogClockWidget : UserControl, IDesktopComponentWidget, I private void BuildTicks(bool isNightMode) { TickCanvas.Children.Clear(); - var scale = Math.Clamp(_layoutScale, 0.78d, 1.22d); var majorBrush = CreateBrush(isNightMode ? "#1A1A1A" : "#1E2430"); var minorBrush = CreateBrush(isNightMode ? "#D0D0D0" : "#D7DCE5"); - var majorThickness = (isNightMode ? 3.0 : 2.8) * scale; - var minorThickness = (isNightMode ? 1.4 : 1.2) * scale; + var majorThickness = isNightMode ? 3.0 : 2.8; + var minorThickness = isNightMode ? 1.4 : 1.2; for (var i = 0; i < 60; i++) { var angle = (i * 6 - 90) * Math.PI / 180d; var isHourTick = i % 5 == 0; - var outerRadius = Center - (7 * scale); - var innerRadius = outerRadius - (isHourTick ? 16 * scale : 8 * scale); + var outerRadius = Center - 7; + var innerRadius = outerRadius - (isHourTick ? 16 : 8); var x1 = Center + Math.Cos(angle) * innerRadius; var y1 = Center + Math.Sin(angle) * innerRadius; @@ -221,50 +218,34 @@ public partial class AnalogClockWidget : UserControl, IDesktopComponentWidget, I private void BuildNumbers(bool isNightMode) { NumberCanvas.Children.Clear(); - var scale = Math.Clamp(_layoutScale, 0.78d, 1.22d); var foreground = CreateBrush(isNightMode ? "#101010" : "#0F131A"); var fontWeight = isNightMode ? FontWeight.Bold : FontWeight.SemiBold; for (var number = 1; number <= 12; number++) { var angle = (number * 30 - 90) * Math.PI / 180d; - var radius = 88 * scale; + var radius = 88; var x = Center + Math.Cos(angle) * radius; var y = Center + Math.Sin(angle) * radius; var isDoubleDigit = number >= 10; - var glyphBox = ComponentTypographyLayoutService.ResolveGlyphBox( - isDoubleDigit ? 44 * scale : 36 * scale, - 34 * scale, - preferredSizeScale: isDoubleDigit ? 0.92d : 0.88d, - minSize: 18, - maxSize: isDoubleDigit ? 36 : 30, - insetScale: 0d); - var text = number.ToString(CultureInfo.InvariantCulture); - var fontSize = ComponentTypographyLayoutService.FitFontSize( - text, - glyphBox.Width, - glyphBox.Height, - maxLines: 1, - minFontSize: 12 * scale, - maxFontSize: 18 * scale, - weight: fontWeight, - lineHeightFactor: 1d); + var width = isDoubleDigit ? 44 : 28; + var height = 34; - var numberText = new TextBlock + var text = new TextBlock { - Text = text, - Width = glyphBox.Width, - Height = glyphBox.Height, + Text = number.ToString(CultureInfo.InvariantCulture), + Width = width, + Height = height, TextAlignment = TextAlignment.Center, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, - FontSize = fontSize, + FontSize = 18, FontWeight = fontWeight, Foreground = foreground }; - Canvas.SetLeft(numberText, x - glyphBox.Width / 2d); - Canvas.SetTop(numberText, y - glyphBox.Height / 2d); - NumberCanvas.Children.Add(numberText); + Canvas.SetLeft(text, x - width / 2d); + Canvas.SetTop(text, y - height / 2d); + NumberCanvas.Children.Add(text); } } @@ -344,14 +325,10 @@ public partial class AnalogClockWidget : UserControl, IDesktopComponentWidget, I { _currentCellSize = Math.Max(1, cellSize); var scale = ResolveScale(); - var chromeScale = ComponentChromeCornerRadiusHelper.ResolveScale(); - _layoutScale = Math.Clamp(scale * (0.9d + (chromeScale * 0.1d)), 0.58d, 2.0d); - RootBorder.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(42 * _layoutScale, 16, 56); - RootBorder.Padding = ComponentChromeCornerRadiusHelper.SafeThickness(14 * _layoutScale, 14 * _layoutScale, null, 0.55d); + RootBorder.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(42 * scale, 16, 56); + RootBorder.Padding = ComponentChromeCornerRadiusHelper.SafeThickness(14 * scale, 14 * scale, null, 0.55d); ApplyModeVisualIfNeeded(); - BuildTicks(_isNightModeApplied ?? ResolveIsNightMode()); - BuildNumbers(_isNightModeApplied ?? ResolveIsNightMode()); } private double ResolveScale() diff --git a/LanMountainDesktop/Views/Components/BaiduHotSearchWidget.axaml.cs b/LanMountainDesktop/Views/Components/BaiduHotSearchWidget.axaml.cs index f96e86a..d667c91 100644 --- a/LanMountainDesktop/Views/Components/BaiduHotSearchWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/BaiduHotSearchWidget.axaml.cs @@ -13,7 +13,6 @@ using Avalonia.Layout; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -433,61 +432,29 @@ public partial class BaiduHotSearchWidget : UserControl, IDesktopComponentWidget RefreshGlyphIcon.FontSize = Math.Clamp(refreshButtonSize * 0.46, 10, 20); var lineColumnGap = Math.Clamp(lineRowHeight * 0.34, 5, 12); - var indexBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - lineRowHeight, - lineRowHeight, - preferredSizeScale: 0.62d, - minSize: 16, - maxSize: 28); - var indexFont = ComponentTypographyLayoutService.FitFontSize( - "88", - indexBadge.Width, - indexBadge.Height, - 1, - minFontSize: 10, - maxFontSize: Math.Clamp(indexBadge.Height * 0.82d, 10, 18), - weight: FontWeight.Bold, - lineHeightFactor: 1.0d, - fontFamily: MiSansFontFamily); - var itemFontMin = Math.Clamp(lineRowHeight * 0.42, 11, 16); - var itemFontMax = Math.Clamp(lineRowHeight * 0.68, 12, 24); + var indexWidth = Math.Clamp(lineRowHeight * 1.02, 16, 28); + var indexFont = Math.Clamp(lineRowHeight * 0.50, 10, 16); + var itemFont = Math.Clamp(lineRowHeight * 0.62, 12, 24); var rowPadding = Math.Clamp(lineRowHeight * 0.08, 1, 4); - var itemTextWidth = Math.Max(56, innerWidth - indexBadge.Width - lineColumnGap); + var itemTextWidth = Math.Max(56, innerWidth - indexWidth - lineColumnGap); foreach (var visual in _hotItemVisuals) { visual.RowGrid.ColumnSpacing = lineColumnGap; if (visual.RowGrid.ColumnDefinitions.Count > 0) { - visual.RowGrid.ColumnDefinitions[0].Width = new GridLength(indexBadge.Width, GridUnitType.Pixel); + visual.RowGrid.ColumnDefinitions[0].Width = new GridLength(indexWidth, GridUnitType.Pixel); } visual.Host.Padding = new Thickness(0, rowPadding, 0, rowPadding); visual.IndexTextBlock.FontSize = indexFont; - visual.IndexTextBlock.MaxWidth = indexBadge.Width; - visual.IndexTextBlock.MinWidth = indexBadge.Width; - visual.IndexTextBlock.Margin = indexBadge.Margin; - - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - visual.TitleTextBlock.Text, - itemTextWidth, - lineRowHeight * 1.9d, - minLines: 1, - maxLines: ComponentTypographyLayoutService.CountTextDisplayUnits(visual.TitleTextBlock.Text) > 24 ? 2 : 1, - minFontSize: itemFontMin, - maxFontSize: itemFontMax, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Bold }, - lineHeightFactor: 1.08d, - fontFamily: MiSansFontFamily); - visual.TitleTextBlock.FontSize = titleLayout.FontSize; - visual.TitleTextBlock.LineHeight = titleLayout.LineHeight; - visual.TitleTextBlock.MaxLines = titleLayout.MaxLines; - visual.TitleTextBlock.FontWeight = titleLayout.Weight; + visual.IndexTextBlock.MaxWidth = indexWidth; + visual.TitleTextBlock.FontSize = itemFont; visual.TitleTextBlock.MaxWidth = itemTextWidth; visual.TitleTextBlock.TextAlignment = TextAlignment.Left; } - StatusTextBlock.FontSize = Math.Clamp(itemFontMax, 10, 20); + StatusTextBlock.FontSize = Math.Clamp(itemFont, 10, 20); ApplyNightModeVisual(); } diff --git a/LanMountainDesktop/Views/Components/BilibiliHotSearchWidget.axaml.cs b/LanMountainDesktop/Views/Components/BilibiliHotSearchWidget.axaml.cs index 1a9dd3b..1940596 100644 --- a/LanMountainDesktop/Views/Components/BilibiliHotSearchWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/BilibiliHotSearchWidget.axaml.cs @@ -11,7 +11,6 @@ using Avalonia.Input; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -438,93 +437,37 @@ public partial class BilibiliHotSearchWidget : UserControl, IDesktopComponentWid Math.Clamp(searchBoxHeight * 0.24, 5, 10), 0); SearchGlyphIcon.FontSize = Math.Clamp(searchBoxHeight * 0.45, 10, 20); - - var searchLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - SearchEntryTextBlock.Text, - Math.Max(54, SearchBoxBorder.Width - Math.Clamp(searchBoxHeight * 0.48, 8, 16)), - searchBoxHeight, - minLines: 1, - maxLines: 1, - minFontSize: 10, - maxFontSize: Math.Clamp(searchBoxHeight * 0.44, 10, 18), - weightCandidates: new[] { FontWeight.Medium, FontWeight.SemiBold }, - lineHeightFactor: 1.0d, - fontFamily: MiSansFontFamily); - SearchEntryTextBlock.FontSize = searchLayout.FontSize; - SearchEntryTextBlock.LineHeight = searchLayout.LineHeight; + SearchEntryTextBlock.FontSize = Math.Clamp(searchBoxHeight * 0.44, 10, 18); TopRightTitleTextBlock.MaxWidth = Math.Max(80, innerWidth - SearchBoxBorder.Width - HeaderGrid.ColumnSpacing); - var topRightLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TopRightTitleTextBlock.Text, - TopRightTitleTextBlock.MaxWidth, - topRowHeight, - minLines: 1, - maxLines: 1, - minFontSize: 11, - maxFontSize: Math.Clamp(topRowHeight * 0.46, 11, 22), - weightCandidates: new[] { FontWeight.Medium, FontWeight.SemiBold }, - lineHeightFactor: 1.0d, - fontFamily: MiSansFontFamily); - TopRightTitleTextBlock.FontSize = topRightLayout.FontSize; - TopRightTitleTextBlock.LineHeight = topRightLayout.LineHeight; + TopRightTitleTextBlock.FontSize = Math.Clamp(topRowHeight * 0.46, 11, 22); var lineColumnGap = Math.Clamp(lineRowHeight * 0.34, 5, 12); - var indexBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - lineRowHeight, - lineRowHeight, - preferredSizeScale: 0.62d, - minSize: 16, - maxSize: 28); - var indexFont = ComponentTypographyLayoutService.FitFontSize( - "88", - indexBadge.Width, - indexBadge.Height, - 1, - minFontSize: 10, - maxFontSize: Math.Clamp(indexBadge.Height * 0.82d, 10, 18), - weight: FontWeight.Bold, - lineHeightFactor: 1.0d, - fontFamily: MiSansFontFamily); - var itemFontMin = Math.Clamp(lineRowHeight * 0.42, 11, 16); - var itemFontMax = Math.Clamp(lineRowHeight * 0.68, 12, 24); + var indexWidth = Math.Clamp(lineRowHeight * 1.02, 16, 28); + var indexFont = Math.Clamp(lineRowHeight * 0.50, 10, 16); + var itemFont = Math.Clamp(lineRowHeight * 0.62, 12, 24); var rowPadding = Math.Clamp(lineRowHeight * 0.08, 1, 4); - var itemTextWidth = Math.Max(56, innerWidth - indexBadge.Width - lineColumnGap); + var itemTextWidth = Math.Max(56, innerWidth - indexWidth - lineColumnGap); foreach (var visual in _hotItemVisuals) { visual.RowGrid.ColumnSpacing = lineColumnGap; if (visual.RowGrid.ColumnDefinitions.Count > 0) { - visual.RowGrid.ColumnDefinitions[0].Width = new GridLength(indexBadge.Width, GridUnitType.Pixel); + visual.RowGrid.ColumnDefinitions[0].Width = new GridLength(indexWidth, GridUnitType.Pixel); } visual.Host.Padding = new Thickness(0, rowPadding, 0, rowPadding); visual.IndexTextBlock.FontSize = indexFont; - visual.IndexTextBlock.MaxWidth = indexBadge.Width; - visual.IndexTextBlock.MinWidth = indexBadge.Width; - visual.IndexTextBlock.Margin = indexBadge.Margin; + visual.IndexTextBlock.MaxWidth = indexWidth; visual.IndexTextBlock.HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Right; visual.IndexTextBlock.TextAlignment = TextAlignment.Right; - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - visual.TitleTextBlock.Text, - itemTextWidth, - lineRowHeight * 1.9d, - minLines: 1, - maxLines: ComponentTypographyLayoutService.CountTextDisplayUnits(visual.TitleTextBlock.Text) > 24 ? 2 : 1, - minFontSize: itemFontMin, - maxFontSize: itemFontMax, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Bold }, - lineHeightFactor: 1.08d, - fontFamily: MiSansFontFamily); - visual.TitleTextBlock.FontSize = titleLayout.FontSize; - visual.TitleTextBlock.LineHeight = titleLayout.LineHeight; - visual.TitleTextBlock.MaxLines = titleLayout.MaxLines; - visual.TitleTextBlock.FontWeight = titleLayout.Weight; + visual.TitleTextBlock.FontSize = itemFont; visual.TitleTextBlock.MaxWidth = itemTextWidth; visual.TitleTextBlock.TextAlignment = TextAlignment.Left; } - StatusTextBlock.FontSize = Math.Clamp(itemFontMax, 10, 20); + StatusTextBlock.FontSize = Math.Clamp(itemFont, 10, 20); ApplyNightModeVisual(); } diff --git a/LanMountainDesktop/Views/Components/BrowserWidget.axaml.cs b/LanMountainDesktop/Views/Components/BrowserWidget.axaml.cs index 1c51347..b552955 100644 --- a/LanMountainDesktop/Views/Components/BrowserWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/BrowserWidget.axaml.cs @@ -6,7 +6,6 @@ using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Styling; using AvaloniaWebView; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Services; using WebViewCore.Events; @@ -53,7 +52,6 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget, } AddressTextBox.Text = DefaultHomeUri.ToString(); - UpdateAddressTypography(); UpdateWebViewActiveState(); } @@ -118,7 +116,6 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget, AddressTextBox.FontSize = Math.Clamp(_currentCellSize * 0.30, 12, 15); AddressTextBox.Height = buttonSize; - UpdateAddressTypography(); } public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) @@ -286,7 +283,6 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget, { _lastKnownUri = uri; AddressTextBox.Text = uri.ToString(); - UpdateAddressTypography(); if (_isWebViewActive) { TryNavigate(uri, "NavigateTo"); @@ -302,7 +298,6 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget, _lastKnownUri = e.Url; AddressTextBox.Text = e.Url.ToString(); - UpdateAddressTypography(); } private void UpdateWebViewActiveState() @@ -412,7 +407,6 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget, GoButton.IsEnabled = false; AddressTextBox.IsEnabled = false; AddressTextBox.Text = _lastKnownUri.ToString(); - UpdateAddressTypography(); UnavailableMessageTextBlock.Text = _isWebViewFaulted ? "The browser component is temporarily unavailable. Restart the app to retry." @@ -457,25 +451,4 @@ public partial class BrowserWidget : UserControl, IDesktopComponentWidget, ? uri : null; } - - private void UpdateAddressTypography() - { - var maxWidth = AddressTextBox.Bounds.Width > 1 - ? AddressTextBox.Bounds.Width - : Math.Max(120, (Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 7) - 120); - var maxHeight = AddressTextBox.Bounds.Height > 1 - ? AddressTextBox.Bounds.Height - : Math.Max(20, AddressTextBox.Height); - - AddressTextBox.FontSize = ComponentTypographyLayoutService.FitFontSize( - AddressTextBox.Text, - maxWidth, - maxHeight, - maxLines: 1, - minFontSize: 12, - maxFontSize: 16, - weight: FontWeight.Normal, - lineHeightFactor: 1.06d, - fontFamily: AddressTextBox.FontFamily); - } } diff --git a/LanMountainDesktop/Views/Components/ClassScheduleWidget.axaml.cs b/LanMountainDesktop/Views/Components/ClassScheduleWidget.axaml.cs index 42f94a0..0108e4e 100644 --- a/LanMountainDesktop/Views/Components/ClassScheduleWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/ClassScheduleWidget.axaml.cs @@ -8,7 +8,6 @@ using Avalonia.Input; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Models; using LanMountainDesktop.PluginSdk; @@ -44,7 +43,6 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, private TimeZoneService? _timeZoneService; private double _currentCellSize = 48; - private double _layoutScale = 1d; private IReadOnlyList _courseItems = Array.Empty(); private bool _isNightVisual = true; private string _languageCode = "zh-CN"; @@ -495,20 +493,18 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, var useMonetColor = ComponentColorSchemeHelper.ShouldUseMonetColor( _componentColorScheme, ComponentColorSchemeHelper.GetCurrentGlobalThemeColorMode()); - var chromeScale = ComponentChromeCornerRadiusHelper.ResolveScale(); - _layoutScale = Math.Clamp(ResolveScale() * (0.9d + (chromeScale * 0.1d)), 0.52d, 2.2d); - var bulletSize = Math.Clamp(10 * _layoutScale, 5, 12); - var lineSpacing = Math.Clamp(4 * _layoutScale, 1.5, 8); + var scale = ResolveScale(); + var bulletSize = Math.Clamp(10 * scale, 5, 12); + var courseNameSize = Math.Clamp(42 * scale, 14, 42); + var secondarySize = Math.Clamp(29 * scale, 10, 28); + var lineSpacing = Math.Clamp(4 * scale, 1.5, 8); var itemPadding = new Thickness( - ComponentChromeCornerRadiusHelper.SafeValue(6 * _layoutScale, 3, 10), - ComponentChromeCornerRadiusHelper.SafeValue(4 * _layoutScale, 2, 8), - ComponentChromeCornerRadiusHelper.SafeValue(4 * _layoutScale, 2, 8), - ComponentChromeCornerRadiusHelper.SafeValue(4 * _layoutScale, 2, 8)); - var maxVisibleItems = ResolveMaxVisibleItems(_layoutScale); - var itemContentWidth = Math.Max(28, (Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 4) - itemPadding.Left - itemPadding.Right - bulletSize - Math.Clamp(10 * _layoutScale, 4, 14)); - var titleHeight = Math.Clamp(34 * _layoutScale, 16, 42); - var secondaryHeight = Math.Clamp(24 * _layoutScale, 12, 30); + ComponentChromeCornerRadiusHelper.SafeValue(6 * scale, 3, 10), + ComponentChromeCornerRadiusHelper.SafeValue(4 * scale, 2, 8), + ComponentChromeCornerRadiusHelper.SafeValue(4 * scale, 2, 8), + ComponentChromeCornerRadiusHelper.SafeValue(4 * scale, 2, 8)); + var maxVisibleItems = ResolveMaxVisibleItems(scale); var primaryBrush = CreateBrush(_isNightVisual ? "#F9FBFF" : "#151821"); var secondaryBrush = CreateBrush(_isNightVisual ? "#848B99" : "#667084"); @@ -529,32 +525,14 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, CornerRadius = new CornerRadius(bulletSize * 0.5), Background = bulletBrush, VerticalAlignment = Avalonia.Layout.VerticalAlignment.Top, - Margin = new Thickness(0, Math.Clamp(8 * _layoutScale, 2, 12), 0, 0) + Margin = new Thickness(0, Math.Clamp(8 * scale, 2, 12), 0, 0) }; var titleText = new TextBlock { Text = item.Name, - FontSize = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - item.Name, - itemContentWidth, - titleHeight, - minLines: 1, - maxLines: 2, - minFontSize: 14, - maxFontSize: Math.Clamp(42 * _layoutScale, 14, 42), - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 1.05d).FontSize, - FontWeight = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - item.Name, - itemContentWidth, - titleHeight, - minLines: 1, - maxLines: 2, - minFontSize: 14, - maxFontSize: Math.Clamp(42 * _layoutScale, 14, 42), - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 1.05d).Weight, + FontSize = courseNameSize, + FontWeight = ToVariableWeight(Lerp(620, 780, Math.Clamp((scale - 0.60) / 1.2, 0, 1))), Foreground = primaryBrush, TextTrimming = TextTrimming.CharacterEllipsis, TextWrapping = TextWrapping.NoWrap @@ -563,26 +541,8 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, var timeText = new TextBlock { Text = item.TimeRange, - FontSize = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - item.TimeRange, - itemContentWidth, - secondaryHeight, - minLines: 1, - maxLines: 1, - minFontSize: 10, - maxFontSize: Math.Clamp(28 * _layoutScale, 10, 28), - weightCandidates: new[] { FontWeight.Medium, FontWeight.Normal }, - lineHeightFactor: 1d).FontSize, - FontWeight = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - item.TimeRange, - itemContentWidth, - secondaryHeight, - minLines: 1, - maxLines: 1, - minFontSize: 10, - maxFontSize: Math.Clamp(28 * _layoutScale, 10, 28), - weightCandidates: new[] { FontWeight.Medium, FontWeight.Normal }, - lineHeightFactor: 1d).Weight, + FontSize = secondarySize, + FontWeight = ToVariableWeight(Lerp(520, 680, Math.Clamp((scale - 0.60) / 1.2, 0, 1))), Foreground = secondaryBrush, TextTrimming = TextTrimming.CharacterEllipsis, TextWrapping = TextWrapping.NoWrap @@ -591,26 +551,8 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, var detailText = new TextBlock { Text = item.Detail, - FontSize = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - item.Detail, - itemContentWidth, - secondaryHeight, - minLines: 1, - maxLines: 1, - minFontSize: 10, - maxFontSize: Math.Clamp(28 * _layoutScale, 10, 28), - weightCandidates: new[] { FontWeight.Normal, FontWeight.Medium }, - lineHeightFactor: 1d).FontSize, - FontWeight = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - item.Detail, - itemContentWidth, - secondaryHeight, - minLines: 1, - maxLines: 1, - minFontSize: 10, - maxFontSize: Math.Clamp(28 * _layoutScale, 10, 28), - weightCandidates: new[] { FontWeight.Normal, FontWeight.Medium }, - lineHeightFactor: 1d).Weight, + FontSize = secondarySize, + FontWeight = ToVariableWeight(Lerp(500, 640, Math.Clamp((scale - 0.60) / 1.2, 0, 1))), Foreground = secondaryBrush, TextTrimming = TextTrimming.CharacterEllipsis, TextWrapping = TextWrapping.NoWrap @@ -625,7 +567,7 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, var itemGrid = new Grid { ColumnDefinitions = new ColumnDefinitions("Auto,*"), - ColumnSpacing = Math.Clamp(10 * _layoutScale, 4, 14) + ColumnSpacing = Math.Clamp(10 * scale, 4, 14) }; itemGrid.Children.Add(bullet); itemGrid.Children.Add(textStack); @@ -661,8 +603,6 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, } var scale = ResolveScale(); - var chromeScale = ComponentChromeCornerRadiusHelper.ResolveScale(); - _layoutScale = Math.Clamp(scale * (0.9d + (chromeScale * 0.1d)), 0.52d, 2.2d); _isNightVisual = ResolveNightMode(); var useMonetColor = ComponentColorSchemeHelper.ShouldUseMonetColor( @@ -672,66 +612,6 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, var slashBrush = useMonetColor ? CreateBrush("#FF4FC3F7") : CreateBrush("#FF3250"); - var sampleNow = _timeZoneService?.GetCurrentTime() ?? DateTime.Now; - var headerWidth = Math.Max(42, Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 4); - var headerHeight = Math.Max(42, Bounds.Height > 1 ? Bounds.Height : _currentCellSize * 4); - var headerPrimaryWidth = Math.Clamp(headerWidth * 0.34, 28, 92); - var headerSecondaryWidth = Math.Clamp(headerWidth * 0.52, 40, 148); - var dateHeight = Math.Clamp(headerHeight * 0.30, 26, 96); - var secondaryHeaderHeight = Math.Clamp(headerHeight * 0.12, 16, 42); - var weekdayLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - FormatWeekday(sampleNow.DayOfWeek), - headerSecondaryWidth, - secondaryHeaderHeight, - minLines: 1, - maxLines: 1, - minFontSize: 13, - maxFontSize: 32, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 1.02d); - var classCountLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - FormatClassCount(_courseItems.Count), - headerSecondaryWidth, - secondaryHeaderHeight, - minLines: 1, - maxLines: 1, - minFontSize: 14, - maxFontSize: 36, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 1.02d); - var statusText = string.IsNullOrWhiteSpace(StatusTextBlock.Text) - ? L("schedule.widget.no_class_today", "浠婂ぉ娌℃湁璇剧▼") - : StatusTextBlock.Text; - var statusLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - statusText, - headerSecondaryWidth, - secondaryHeaderHeight, - minLines: 1, - maxLines: 1, - minFontSize: 12, - maxFontSize: 30, - weightCandidates: new[] { FontWeight.Medium, FontWeight.Normal }, - lineHeightFactor: 1.02d); - var monthLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - sampleNow.Month.ToString(CultureInfo.InvariantCulture), - headerPrimaryWidth, - dateHeight, - minLines: 1, - maxLines: 1, - minFontSize: 26, - maxFontSize: 82, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 1d); - var dayLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - sampleNow.Day.ToString(CultureInfo.InvariantCulture), - headerPrimaryWidth, - dateHeight, - minLines: 1, - maxLines: 1, - minFontSize: 26, - maxFontSize: 82, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 1d); RootBorder.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(_currentCellSize * 0.45, 24, 44); RootBorder.Background = _isNightVisual @@ -740,21 +620,21 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, RootBorder.BorderBrush = CreateBrush(_isNightVisual ? "#24FFFFFF" : "#15000000"); var rootPadding = new Thickness( - ComponentChromeCornerRadiusHelper.SafeValue(16 * _layoutScale, 10, 24), - ComponentChromeCornerRadiusHelper.SafeValue(14 * _layoutScale, 9, 20), - ComponentChromeCornerRadiusHelper.SafeValue(16 * _layoutScale, 10, 24), - ComponentChromeCornerRadiusHelper.SafeValue(14 * _layoutScale, 8, 20)); + ComponentChromeCornerRadiusHelper.SafeValue(16 * scale, 10, 24), + ComponentChromeCornerRadiusHelper.SafeValue(14 * scale, 9, 20), + ComponentChromeCornerRadiusHelper.SafeValue(16 * scale, 10, 24), + ComponentChromeCornerRadiusHelper.SafeValue(14 * scale, 8, 20)); RootBorder.Padding = rootPadding; - LayoutGrid.RowSpacing = Math.Clamp(14 * _layoutScale, 6, 20); - HeaderGrid.ColumnSpacing = Math.Clamp(10 * _layoutScale, 4, 16); - DateGroup.Spacing = Math.Clamp(1.5 * _layoutScale, 0.5, 3); - MetaStack.Spacing = Math.Clamp(6 * _layoutScale, 3, 10); - CourseListPanel.Spacing = Math.Clamp(6 * _layoutScale, 3, 10); + LayoutGrid.RowSpacing = Math.Clamp(14 * scale, 6, 20); + HeaderGrid.ColumnSpacing = Math.Clamp(10 * scale, 4, 16); + DateGroup.Spacing = Math.Clamp(1.5 * scale, 0.5, 3); + MetaStack.Spacing = Math.Clamp(6 * scale, 3, 10); + CourseListPanel.Spacing = Math.Clamp(6 * scale, 3, 10); - var dateFont = Math.Clamp(66 * _layoutScale, 26, 82); - MonthTextBlock.FontSize = monthLayout.FontSize; - DayTextBlock.FontSize = dayLayout.FontSize; + var dateFont = Math.Clamp(66 * scale, 26, 82); + MonthTextBlock.FontSize = dateFont; + DayTextBlock.FontSize = dateFont; SlashTextBlock.FontSize = dateFont; MonthTextBlock.Foreground = CreateBrush(_isNightVisual ? "#F8FAFF" : "#131722"); @@ -764,13 +644,12 @@ public partial class ClassScheduleWidget : UserControl, IDesktopComponentWidget, ClassCountTextBlock.Foreground = CreateBrush(_isNightVisual ? "#8D95A4" : "#738095"); StatusTextBlock.Foreground = CreateBrush(_isNightVisual ? "#9AA2B1" : "#4B5565"); - WeekdayTextBlock.FontSize = weekdayLayout.FontSize; - ClassCountTextBlock.FontSize = classCountLayout.FontSize; - StatusTextBlock.FontSize = statusLayout.FontSize; + WeekdayTextBlock.FontSize = Math.Clamp(34 * scale, 13, 32); + ClassCountTextBlock.FontSize = Math.Clamp(40 * scale, 14, 36); + StatusTextBlock.FontSize = Math.Clamp(30 * scale, 12, 30); - WeekdayTextBlock.FontWeight = weekdayLayout.Weight; - ClassCountTextBlock.FontWeight = classCountLayout.Weight; - StatusTextBlock.FontWeight = statusLayout.Weight; + WeekdayTextBlock.FontWeight = ToVariableWeight(Lerp(560, 700, Math.Clamp((scale - 0.60) / 1.2, 0, 1))); + ClassCountTextBlock.FontWeight = ToVariableWeight(Lerp(560, 680, Math.Clamp((scale - 0.60) / 1.2, 0, 1))); } private static string FormatTime(TimeSpan time) diff --git a/LanMountainDesktop/Views/Components/ClockWidget.axaml.cs b/LanMountainDesktop/Views/Components/ClockWidget.axaml.cs index 678fa67..bbfb2e1 100644 --- a/LanMountainDesktop/Views/Components/ClockWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/ClockWidget.axaml.cs @@ -4,7 +4,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Services; namespace LanMountainDesktop.Views.Components; @@ -121,13 +120,11 @@ public partial class ClockWidget : UserControl, IDesktopComponentWidget, ITimeZo SecondsTextBlock.Text = now.ToString("ss", CultureInfo.CurrentCulture); SecondsTextBlock.IsVisible = _displayFormat == ClockDisplayFormat.HourMinuteSecond; - ApplyTypographyLayout(); } public void ApplyCellSize(double cellSize) { _lastAppliedCellSize = cellSize; - var layoutScale = Math.Clamp((cellSize / 44d) * (0.9d + (ComponentChromeCornerRadiusHelper.ResolveScale() * 0.1d)), 0.65d, 1.95d); // --- Class Island “满盈”风格算法 --- @@ -141,7 +138,7 @@ public partial class ClockWidget : UserControl, IDesktopComponentWidget, ITimeZo // 3. 核心:满盈字阶 (Filled Typography) // 使主时间文字占据容器高度的 ~68%,产生饱满的视觉张力 - var mainFontSize = targetHeight * 0.68 * layoutScale; + var mainFontSize = targetHeight * 0.68; MainTimeTextBlock.FontSize = mainFontSize; MainTimeTextBlock.FontWeight = FontWeight.SemiBold; @@ -155,74 +152,19 @@ public partial class ClockWidget : UserControl, IDesktopComponentWidget, ITimeZo // 6. 间距微调 if (MainTimeTextBlock.Parent is StackPanel panel) { - panel.Spacing = Math.Clamp(cellSize * 0.06 * layoutScale, 2, 8); + panel.Spacing = Math.Clamp(cellSize * 0.06, 2, 8); } if (_transparentBackground) { RootBorder.MinWidth = 0; - RootBorder.Padding = new Thickness(Math.Clamp(cellSize * 0.06 * layoutScale, 4, 10), 0); + RootBorder.Padding = new Thickness(Math.Clamp(cellSize * 0.06, 4, 10), 0); return; } // 确保清除可能存在的固定 Padding,由代码控制“紧密感” RootBorder.MinWidth = cellSize * 2.2; - RootBorder.Padding = new Thickness(Math.Clamp(cellSize * 0.15 * layoutScale, 12, 24), 0); - ApplyTypographyLayout(); - } - - private void ApplyTypographyLayout() - { - var layoutScale = Math.Clamp((_lastAppliedCellSize / 44d) * (0.9d + (ComponentChromeCornerRadiusHelper.ResolveScale() * 0.1d)), 0.65d, 1.95d); - var availableWidth = Math.Max(1, RootBorder.Bounds.Width > 1 ? RootBorder.Bounds.Width : Math.Max(1, _lastAppliedCellSize * 2.2)); - var availableHeight = Math.Max(1, RootBorder.Bounds.Height > 1 ? RootBorder.Bounds.Height : Math.Clamp(_lastAppliedCellSize * 0.74, 34, 74)); - var contentWidth = Math.Max(1, availableWidth - RootBorder.Padding.Left - RootBorder.Padding.Right); - var contentHeight = Math.Max(1, availableHeight - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - - var mainLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - MainTimeTextBlock.Text, - contentWidth * (SecondsTextBlock.IsVisible ? 0.78d : 0.84d), - contentHeight * 0.80d, - minLines: 1, - maxLines: 1, - minFontSize: Math.Clamp(18 * layoutScale, 16, 28), - maxFontSize: Math.Clamp(44 * layoutScale, 28, 64), - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 0.96d); - MainTimeTextBlock.FontSize = mainLayout.FontSize; - MainTimeTextBlock.FontWeight = mainLayout.Weight; - - if (SecondsTextBlock.IsVisible) - { - var secondsLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - SecondsTextBlock.Text, - contentWidth * 0.28d, - contentHeight * 0.46d, - minLines: 1, - maxLines: 1, - minFontSize: Math.Clamp(11 * layoutScale, 9, 18), - maxFontSize: Math.Clamp(28 * layoutScale, 14, 34), - weightCandidates: new[] { FontWeight.Medium, FontWeight.Normal }, - lineHeightFactor: 0.96d); - SecondsTextBlock.FontSize = secondsLayout.FontSize; - SecondsTextBlock.FontWeight = secondsLayout.Weight; - SecondsTextBlock.Opacity = 0.55; - } - - if (MainTimeTextBlock.Parent is StackPanel panel) - { - panel.Spacing = Math.Clamp(contentHeight * 0.06 * layoutScale, 2, 8); - } - - if (_transparentBackground) - { - RootBorder.MinWidth = 0; - RootBorder.Padding = new Thickness(Math.Clamp(_lastAppliedCellSize * 0.06 * layoutScale, 4, 10), 0); - return; - } - - RootBorder.MinWidth = _lastAppliedCellSize * 2.2; - RootBorder.Padding = new Thickness(Math.Clamp(_lastAppliedCellSize * 0.15 * layoutScale, 12, 24), 0); + RootBorder.Padding = new Thickness(Math.Clamp(cellSize * 0.15, 12, 24), 0); } private void ApplyChrome() diff --git a/LanMountainDesktop/Views/Components/CnrDailyNewsWidget.axaml.cs b/LanMountainDesktop/Views/Components/CnrDailyNewsWidget.axaml.cs index 6c3bf49..678cc54 100644 --- a/LanMountainDesktop/Views/Components/CnrDailyNewsWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/CnrDailyNewsWidget.axaml.cs @@ -16,7 +16,6 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -600,40 +599,17 @@ public partial class CnrDailyNewsWidget : UserControl, IDesktopComponentWidget, News2TitleTextBlock.MaxWidth = availableTextWidth; var newsFont = Math.Clamp(21 * scale, 10.5, 28); - var newsHeightBudget = Math.Max(28, imageHeight + columnGap * 2d); - var news1Layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - News1TitleTextBlock.Text, - availableTextWidth, - newsHeightBudget, - minLines: 1, - maxLines: ComponentTypographyLayoutService.CountTextDisplayUnits(News1TitleTextBlock.Text) > 30 ? 2 : 1, - minFontSize: Math.Clamp(newsFont * 0.72, 10.5, 18), - maxFontSize: newsFont, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Bold }, - lineHeightFactor: 1.14d, - fontFamily: MiSansFontFamily); - var news2Layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - News2TitleTextBlock.Text, - availableTextWidth, - newsHeightBudget, - minLines: 1, - maxLines: ComponentTypographyLayoutService.CountTextDisplayUnits(News2TitleTextBlock.Text) > 30 ? 2 : 1, - minFontSize: Math.Clamp(newsFont * 0.72, 10.5, 18), - maxFontSize: newsFont, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Bold }, - lineHeightFactor: 1.14d, - fontFamily: MiSansFontFamily); - News1TitleTextBlock.FontSize = news1Layout.FontSize; - News1TitleTextBlock.LineHeight = news1Layout.LineHeight; - News1TitleTextBlock.MinHeight = news1Layout.LineHeight * news1Layout.MaxLines; - News1TitleTextBlock.MaxLines = news1Layout.MaxLines; - News1TitleTextBlock.FontWeight = news1Layout.Weight; - News2TitleTextBlock.FontSize = news2Layout.FontSize; - News2TitleTextBlock.LineHeight = news2Layout.LineHeight; - News2TitleTextBlock.MinHeight = news2Layout.LineHeight * news2Layout.MaxLines; - News2TitleTextBlock.MaxLines = news2Layout.MaxLines; - News2TitleTextBlock.FontWeight = news2Layout.Weight; + News1TitleTextBlock.FontSize = newsFont; + News2TitleTextBlock.FontSize = newsFont; + var mainNewsLineHeight = newsFont * 1.14; + News1TitleTextBlock.LineHeight = mainNewsLineHeight; + News2TitleTextBlock.LineHeight = mainNewsLineHeight; + var mainNewsMinHeight = mainNewsLineHeight * 2; + News1TitleTextBlock.MinHeight = mainNewsMinHeight; + News2TitleTextBlock.MinHeight = mainNewsMinHeight; StatusTextBlock.FontSize = Math.Clamp(16 * scale, 9, 24); + News1TitleTextBlock.MaxLines = 2; + News2TitleTextBlock.MaxLines = 2; foreach (var row in _extraNewsRows) { @@ -647,23 +623,11 @@ public partial class CnrDailyNewsWidget : UserControl, IDesktopComponentWidget, row.ImageHost.Height = imageHeight; row.ImageHost.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(16 * scale, 8, 22); - var rowTitleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - row.TitleTextBlock.Text, - availableTextWidth, - Math.Max(32, imageHeight + columnGap), - minLines: 1, - maxLines: ComponentTypographyLayoutService.CountTextDisplayUnits(row.TitleTextBlock.Text) > 28 ? 2 : 1, - minFontSize: Math.Clamp(19 * scale, 10, 16), - maxFontSize: Math.Clamp(19 * scale, 10, 25), - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Bold }, - lineHeightFactor: 1.12d, - fontFamily: MiSansFontFamily); row.TitleTextBlock.MaxWidth = availableTextWidth; - row.TitleTextBlock.FontSize = rowTitleLayout.FontSize; - row.TitleTextBlock.LineHeight = rowTitleLayout.LineHeight; - row.TitleTextBlock.MinHeight = rowTitleLayout.LineHeight * rowTitleLayout.MaxLines; - row.TitleTextBlock.MaxLines = rowTitleLayout.MaxLines; - row.TitleTextBlock.FontWeight = rowTitleLayout.Weight; + row.TitleTextBlock.FontSize = Math.Clamp(19 * scale, 10, 25); + row.TitleTextBlock.LineHeight = row.TitleTextBlock.FontSize * 1.12; + row.TitleTextBlock.MinHeight = row.TitleTextBlock.LineHeight * 2; + row.TitleTextBlock.MaxLines = 2; } ExtraNewsItemsPanel.Spacing = Math.Clamp(6 * scale, 3, 10); diff --git a/LanMountainDesktop/Views/Components/DailyArtworkWidget.axaml.cs b/LanMountainDesktop/Views/Components/DailyArtworkWidget.axaml.cs index 0447a8a..8e59121 100644 --- a/LanMountainDesktop/Views/Components/DailyArtworkWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/DailyArtworkWidget.axaml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -13,7 +13,6 @@ using Avalonia.Input; using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Models; using LanMountainDesktop.PluginSdk; @@ -27,13 +26,13 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, private static readonly IReadOnlyDictionary ZhWeekdays = new Dictionary { - [DayOfWeek.Monday] = "һ", - [DayOfWeek.Tuesday] = "ڶ", - [DayOfWeek.Wednesday] = "", - [DayOfWeek.Thursday] = "", - [DayOfWeek.Friday] = "", - [DayOfWeek.Saturday] = "", - [DayOfWeek.Sunday] = "" + [DayOfWeek.Monday] = "星期一", + [DayOfWeek.Tuesday] = "星期二", + [DayOfWeek.Wednesday] = "星期三", + [DayOfWeek.Thursday] = "星期四", + [DayOfWeek.Friday] = "星期五", + [DayOfWeek.Saturday] = "星期六", + [DayOfWeek.Sunday] = "星期日" }; private static readonly Regex MultiWhitespaceRegex = new(@"\s+", RegexOptions.Compiled); @@ -450,7 +449,7 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, var leftSingleLineHeight = Math.Max(12, (leftContentHeight - dateStackSpacing) / 2d); var dateBase = Math.Clamp(44 * scale, 16, 62); - DateTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( + DateTextBlock.FontSize = FitFontSize( DateTextBlock.Text, leftContentWidth, leftSingleLineHeight, @@ -458,11 +457,10 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, minFontSize: Math.Max(12, dateBase * 0.68), maxFontSize: dateBase, weight: FontWeight.Bold, - lineHeightFactor: 1.10, - fontFamily: MiSansFontFamily); + lineHeightFactor: 1.10); DateTextBlock.LineHeight = DateTextBlock.FontSize * 1.10; - WeekdayTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( + WeekdayTextBlock.FontSize = FitFontSize( WeekdayTextBlock.Text, leftContentWidth, leftSingleLineHeight, @@ -470,8 +468,7 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, minFontSize: Math.Max(12, dateBase * 0.68), maxFontSize: dateBase, weight: FontWeight.Bold, - lineHeightFactor: 1.10, - fontFamily: MiSansFontFamily); + lineHeightFactor: 1.10); WeekdayTextBlock.LineHeight = WeekdayTextBlock.FontSize * 1.10; var rightContentHeight = Math.Max(42, totalHeight - rootPadding.Top - rootPadding.Bottom - InfoPanel.Padding.Top - InfoPanel.Padding.Bottom); @@ -519,7 +516,7 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, yearHeightBudget = minYearHeight + extraHeight * (yearWeight / weightSum); } - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( + var titleLayout = FitAdaptiveTextLayout( PaintingTitleTextBlock.Text, rightContentWidth, titleHeightBudget, @@ -528,8 +525,7 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, minFontSize: titleMin, maxFontSize: titleBase, weightCandidates: TitleWeightCandidates, - lineHeightFactor: 1.10, - fontFamily: MiSansFontFamily); + lineHeightFactor: 1.10); PaintingTitleTextBlock.MaxWidth = rightContentWidth; PaintingTitleTextBlock.Margin = new Thickness(0, 0, 0, titleBottomMargin); PaintingTitleTextBlock.MaxLines = titleLayout.MaxLines; @@ -542,7 +538,7 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, artistInfoStack.Spacing = bottomStackSpacing; } - var artistLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( + var artistLayout = FitAdaptiveTextLayout( ArtistTextBlock.Text, rightContentWidth, artistHeightBudget, @@ -551,15 +547,14 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, minFontSize: artistMin, maxFontSize: artistBase, weightCandidates: ArtistWeightCandidates, - lineHeightFactor: 1.14, - fontFamily: MiSansFontFamily); + lineHeightFactor: 1.14); ArtistTextBlock.MaxWidth = rightContentWidth; ArtistTextBlock.MaxLines = artistLayout.MaxLines; ArtistTextBlock.FontWeight = artistLayout.Weight; ArtistTextBlock.FontSize = artistLayout.FontSize; ArtistTextBlock.LineHeight = artistLayout.LineHeight; - var yearLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( + var yearLayout = FitAdaptiveTextLayout( YearTextBlock.Text, rightContentWidth, yearHeightBudget, @@ -568,8 +563,7 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, minFontSize: yearMin, maxFontSize: yearBase, weightCandidates: SecondaryWeightCandidates, - lineHeightFactor: 1.08, - fontFamily: MiSansFontFamily); + lineHeightFactor: 1.08); YearTextBlock.MaxWidth = rightContentWidth; YearTextBlock.MaxLines = yearLayout.MaxLines; YearTextBlock.FontWeight = yearLayout.Weight; @@ -723,7 +717,7 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, normalized = "Untitled"; } - return $"{normalized}"; + return $"“{normalized}”"; } private void CancelRefreshRequest() @@ -777,4 +771,222 @@ public partial class DailyArtworkWidget : UserControl, IDesktopComponentWidget, return MultiWhitespaceRegex.Replace(text.Trim(), " "); } + private static double FitFontSize( + string? text, + double maxWidth, + double maxHeight, + int maxLines, + double minFontSize, + double maxFontSize, + FontWeight weight, + double lineHeightFactor) + { + var content = string.IsNullOrWhiteSpace(text) ? " " : text.Trim(); + var min = Math.Max(6, minFontSize); + var max = Math.Max(min, maxFontSize); + var low = min; + var high = max; + var best = min; + + for (var i = 0; i < 18; i++) + { + var candidate = (low + high) / 2d; + var lineHeight = candidate * lineHeightFactor; + var size = MeasureTextSize(content, candidate, weight, Math.Max(1, maxWidth), lineHeight); + var lineCount = Math.Max(1, (int)Math.Ceiling(size.Height / Math.Max(1, lineHeight))); + var fits = size.Height <= maxHeight + 0.6 && lineCount <= Math.Max(1, maxLines); + + if (fits) + { + best = candidate; + low = candidate; + } + else + { + high = candidate; + } + } + + return best; + } + + private static AdaptiveTextLayout FitAdaptiveTextLayout( + string? text, + double maxWidth, + double maxHeight, + int minLines, + int maxLines, + double minFontSize, + double maxFontSize, + FontWeight[] weightCandidates, + double lineHeightFactor) + { + var content = string.IsNullOrWhiteSpace(text) ? " " : text.Trim(); + var safeMinLines = Math.Max(1, minLines); + var safeMaxLines = Math.Max(safeMinLines, maxLines); + var linesByHeight = ResolveMaxLinesByHeight(maxHeight, minFontSize, lineHeightFactor, safeMinLines, safeMaxLines); + + var candidates = weightCandidates is { Length: > 0 } + ? weightCandidates + : new[] { FontWeight.Normal }; + + AdaptiveTextLayout? best = null; + foreach (var weight in candidates) + { + for (var lineLimit = linesByHeight; lineLimit >= safeMinLines; lineLimit--) + { + var fontSize = FitFontSize( + content, + maxWidth, + maxHeight, + lineLimit, + minFontSize, + maxFontSize, + weight, + lineHeightFactor); + var lineHeight = fontSize * lineHeightFactor; + var measuredSize = MeasureTextSize(content, fontSize, weight, Math.Max(1, maxWidth), lineHeight); + var measuredLineCount = ResolveLineCount(measuredSize.Height, lineHeight); + var overflowLines = Math.Max(0, measuredLineCount - lineLimit); + var overflowHeight = Math.Max(0, measuredSize.Height - maxHeight); + var overflowScore = overflowLines * 1000d + overflowHeight; + var fitsCompletely = overflowLines == 0 && overflowHeight <= 0.6; + var candidate = new AdaptiveTextLayout(fontSize, weight, lineLimit, lineHeight, overflowScore, fitsCompletely); + + if (best is null || IsBetterAdaptiveTextCandidate(candidate, best.Value)) + { + best = candidate; + } + } + } + + if (best is not null) + { + return best.Value; + } + + var fallbackFontSize = Math.Max(6, minFontSize); + return new AdaptiveTextLayout( + fallbackFontSize, + FontWeight.Normal, + safeMinLines, + fallbackFontSize * lineHeightFactor, + double.MaxValue, + fitsCompletely: false); + } + + private static bool IsBetterAdaptiveTextCandidate(AdaptiveTextLayout candidate, AdaptiveTextLayout best) + { + if (candidate.FitsCompletely && !best.FitsCompletely) + { + return true; + } + + if (!candidate.FitsCompletely && best.FitsCompletely) + { + return false; + } + + if (candidate.FitsCompletely && best.FitsCompletely) + { + if (candidate.FontSize > best.FontSize + 0.12) + { + return true; + } + + if (Math.Abs(candidate.FontSize - best.FontSize) <= 0.12 && candidate.MaxLines < best.MaxLines) + { + return true; + } + + return false; + } + + if (candidate.OverflowScore < best.OverflowScore - 0.2) + { + return true; + } + + if (Math.Abs(candidate.OverflowScore - best.OverflowScore) <= 0.2 && + candidate.FontSize > best.FontSize + 0.12) + { + return true; + } + + if (Math.Abs(candidate.OverflowScore - best.OverflowScore) <= 0.2 && + Math.Abs(candidate.FontSize - best.FontSize) <= 0.12 && + candidate.MaxLines > best.MaxLines) + { + return true; + } + + return false; + } + + private static int ResolveMaxLinesByHeight( + double maxHeight, + double minFontSize, + double lineHeightFactor, + int minLines, + int maxLines) + { + var safeMinLines = Math.Max(1, minLines); + var safeMaxLines = Math.Max(safeMinLines, maxLines); + var lineHeight = Math.Max(1, Math.Max(6, minFontSize) * lineHeightFactor); + var maxHeightWithTolerance = Math.Max(1, maxHeight + 0.6); + var linesByHeight = (int)Math.Floor(maxHeightWithTolerance / lineHeight); + return Math.Clamp(linesByHeight, safeMinLines, safeMaxLines); + } + + private static int ResolveLineCount(double measuredHeight, double lineHeight) + { + return Math.Max(1, (int)Math.Ceiling(measuredHeight / Math.Max(1, lineHeight))); + } + + private readonly struct AdaptiveTextLayout + { + public AdaptiveTextLayout( + double fontSize, + FontWeight weight, + int maxLines, + double lineHeight, + double overflowScore, + bool fitsCompletely) + { + FontSize = fontSize; + Weight = weight; + MaxLines = Math.Max(1, maxLines); + LineHeight = lineHeight; + OverflowScore = overflowScore; + FitsCompletely = fitsCompletely; + } + + public double FontSize { get; } + + public FontWeight Weight { get; } + + public int MaxLines { get; } + + public double LineHeight { get; } + + public double OverflowScore { get; } + + public bool FitsCompletely { get; } + } + + private static Size MeasureTextSize(string text, double fontSize, FontWeight weight, double maxWidth, double lineHeight) + { + var probe = new TextBlock + { + Text = text, + FontFamily = MiSansFontFamily, + FontSize = fontSize, + FontWeight = weight, + TextWrapping = TextWrapping.Wrap, + LineHeight = lineHeight + }; + + probe.Measure(new Size(Math.Max(1, maxWidth), double.PositiveInfinity)); + return probe.DesiredSize; + } } diff --git a/LanMountainDesktop/Views/Components/DailyPoetryWidget.axaml.cs b/LanMountainDesktop/Views/Components/DailyPoetryWidget.axaml.cs index 2a410be..8537497 100644 --- a/LanMountainDesktop/Views/Components/DailyPoetryWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/DailyPoetryWidget.axaml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,7 +11,6 @@ using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -49,6 +48,8 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I private const double MinPoetryFontSize = 8; private const double MinAuthorFontSize = 7; + private readonly record struct TextFitResult(double FontSize, FontWeight FontWeight, double LineHeight); + private readonly DispatcherTimer _refreshTimer = new() { Interval = TimeSpan.FromHours(6) @@ -267,7 +268,7 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I { if (!string.IsNullOrWhiteSpace(snapshot.Origin)) { - return $"{snapshot.Origin.Trim()} · {snapshot.Author.Trim()}"; + return $"{snapshot.Origin.Trim()} \u00B7 {snapshot.Author.Trim()}"; } return snapshot.Author.Trim(); @@ -296,7 +297,7 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I private void ApplyLoadingState() { _poetryRawText = L("poetry.widget.loading_content", "Loading..."); - _authorRawText = L("poetry.widget.loading_author", "·"); + _authorRawText = L("poetry.widget.loading_author", "..."); StatusTextBlock.IsVisible = false; ApplyModeVisualIfNeeded(force: true); } @@ -483,29 +484,23 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I minFontWeight: ToVariableWeight(poemMinWeight), lineHeightFactor: 1.12); - var poemFit = ComponentTypographyLayoutService.FitAdaptiveTextLayout( + var poemFit = FitTextStable( poemPrepared, poemWidth, availablePoemHeight, minFontSize: poemMinFontSize, maxFontSize: Math.Clamp(poemPreferredFontSize * 1.20, poemMinFontSize, 62), - minLines: poemMaxLines, maxLines: poemMaxLines, - weightCandidates: new[] - { - ToVariableWeight(poemMinWeight), - ToVariableWeight((poemMinWeight + poemMaxWeight) / 2d), - ToVariableWeight(poemMaxWeight) - }, lineHeightFactor: 1.12, - fontFamily: MiSansFontFamily); + minWeight: poemMinWeight, + maxWeight: poemMaxWeight); PoetryContentTextBlock.Text = poemPrepared; PoetryContentTextBlock.MaxWidth = poemWidth; PoetryContentTextBlock.MaxLines = poemMaxLines; PoetryContentTextBlock.FontSize = poemFit.FontSize; PoetryContentTextBlock.LineHeight = poemFit.LineHeight; - PoetryContentTextBlock.FontWeight = poemFit.Weight; + PoetryContentTextBlock.FontWeight = poemFit.FontWeight; var authorWidth = Math.Max(72, Math.Min(innerWidth * (isNightMode ? 0.5 : 0.56), innerWidth - 8)); var authorUnitsTarget = 20; @@ -525,22 +520,16 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I minFontWeight: ToVariableWeight(authorMinWeight), lineHeightFactor: 1.12); - var authorFit = ComponentTypographyLayoutService.FitAdaptiveTextLayout( + var authorFit = FitTextStable( authorPrepared, authorWidth, AuthorAccent.Height, minFontSize: authorMinFontSize, maxFontSize: Math.Clamp(authorPreferredFontSize * 1.15, authorMinFontSize, 42), - minLines: 1, maxLines: 1, - weightCandidates: new[] - { - ToVariableWeight(authorMinWeight), - ToVariableWeight((authorMinWeight + authorMaxWeight) / 2d), - ToVariableWeight(authorMaxWeight) - }, lineHeightFactor: 1.12, - fontFamily: MiSansFontFamily); + minWeight: authorMinWeight, + maxWeight: authorMaxWeight); AuthorTextBlock.Text = authorPrepared; AuthorTextBlock.TextWrapping = TextWrapping.NoWrap; @@ -548,7 +537,7 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I AuthorTextBlock.MaxWidth = authorWidth; AuthorTextBlock.FontSize = authorFit.FontSize; AuthorTextBlock.LineHeight = authorFit.LineHeight; - AuthorTextBlock.FontWeight = authorFit.Weight; + AuthorTextBlock.FontWeight = authorFit.FontWeight; } private void UpdateRefreshButtonState() @@ -702,7 +691,7 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I if (current.Length == 0) { - if (ComponentTypographyLayoutService.CountTextDisplayUnits(remain) <= target || lines.Count == lineLimit - 1) + if (EstimateDisplayUnits(remain) <= target || lines.Count == lineLimit - 1) { current.Append(remain); remain = string.Empty; @@ -725,7 +714,7 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I } var merged = current + remain; - if (ComponentTypographyLayoutService.CountTextDisplayUnits(merged) <= target || lines.Count == lineLimit - 1) + if (EstimateDisplayUnits(merged) <= target || lines.Count == lineLimit - 1) { current.Append(remain); remain = string.Empty; @@ -859,13 +848,7 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I } var lineHeight = fontSize * lineHeightFactor; - var measured = ComponentTypographyLayoutService.MeasureTextSize( - text, - fontSize, - fontWeight, - maxWidth, - lineHeight, - MiSansFontFamily); + var measured = MeasureTextSize(text, fontSize, fontWeight, maxWidth, lineHeight); var lineCount = Math.Max(1, (int)Math.Ceiling(measured.Height / Math.Max(1, lineHeight))); return measured.Height <= maxHeight + 0.6 && lineCount <= Math.Max(1, maxLines); } @@ -908,6 +891,86 @@ public partial class DailyPoetryWidget : UserControl, IDesktopComponentWidget, I return text.Length; } + private static double EstimateDisplayUnits(string text) + { + var units = 0d; + foreach (var ch in text) + { + units += ch <= 127 ? 0.56 : 1d; + } + + return units; + } + + private static TextFitResult FitTextStable( + string? text, + double maxWidth, + double maxHeight, + double minFontSize, + double maxFontSize, + int maxLines, + double lineHeightFactor, + double minWeight, + double maxWeight) + { + var normalizedText = string.IsNullOrWhiteSpace(text) ? " " : text.Trim(); + var min = Math.Max(6, minFontSize); + var max = Math.Max(min, maxFontSize); + var low = min; + var high = max; + + var bestSize = min; + var bestWeight = ToVariableWeight(minWeight); + + for (var i = 0; i < 22; i++) + { + var candidate = (low + high) / 2d; + var progress = max <= min + ? 0 + : Math.Clamp((candidate - min) / (max - min), 0, 1); + var candidateWeight = ToVariableWeight(Lerp(minWeight, maxWeight, progress)); + var lineHeight = candidate * lineHeightFactor; + + var measured = MeasureTextSize(normalizedText, candidate, candidateWeight, Math.Max(1, maxWidth), lineHeight); + var lineCount = Math.Max(1, (int)Math.Ceiling(measured.Height / Math.Max(1, lineHeight))); + var fits = measured.Height <= maxHeight + 0.6 && lineCount <= Math.Max(1, maxLines); + + if (fits) + { + bestSize = candidate; + bestWeight = candidateWeight; + low = candidate; + } + else + { + high = candidate; + } + } + + var lineHeightResult = bestSize * lineHeightFactor; + return new TextFitResult(bestSize, bestWeight, lineHeightResult); + } + + private static Size MeasureTextSize( + string text, + double fontSize, + FontWeight fontWeight, + double maxWidth, + double lineHeight) + { + var probe = new TextBlock + { + Text = text, + FontFamily = MiSansFontFamily, + FontSize = fontSize, + FontWeight = fontWeight, + TextWrapping = TextWrapping.Wrap, + LineHeight = lineHeight + }; + + probe.Measure(new Size(Math.Max(1, maxWidth), double.PositiveInfinity)); + return probe.DesiredSize; + } private static FontWeight ToVariableWeight(double weight) { diff --git a/LanMountainDesktop/Views/Components/ExchangeRateCalculatorWidget.axaml.cs b/LanMountainDesktop/Views/Components/ExchangeRateCalculatorWidget.axaml.cs index 0d1187a..1ebad06 100644 --- a/LanMountainDesktop/Views/Components/ExchangeRateCalculatorWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/ExchangeRateCalculatorWidget.axaml.cs @@ -9,7 +9,6 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Services; namespace LanMountainDesktop.Views.Components; @@ -75,7 +74,6 @@ public partial class ExchangeRateCalculatorWidget : UserControl, IDesktopCompone UpdateCurrencyLabels(); UpdateAmounts(); ApplyLoadingState(); - UpdateTypography(); } public void ApplyCellSize(double cellSize) @@ -84,7 +82,6 @@ public partial class ExchangeRateCalculatorWidget : UserControl, IDesktopCompone var scale = ResolveScale(); RootBorder.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(34 * scale, 14, 48); RootBorder.Padding = ComponentChromeCornerRadiusHelper.SafeThickness(12 * scale, 12 * scale, null, 0.55d); - UpdateTypography(); } public void SetRecommendationInfoService(IRecommendationInfoService recommendationInfoService) @@ -246,7 +243,6 @@ public partial class ExchangeRateCalculatorWidget : UserControl, IDesktopCompone FromCurrencyNameTextBlock.Text = IsZh() ? from.ZhName : from.EnName; ToCurrencyCodeTextBlock.Text = to.Code; ToCurrencyNameTextBlock.Text = IsZh() ? to.ZhName : to.EnName; - UpdateTypography(); } private void UpdateAmounts() @@ -262,7 +258,6 @@ public partial class ExchangeRateCalculatorWidget : UserControl, IDesktopCompone _fromCurrency, _calculatorDataService.FormatAmount(_currentRate, maxFractionDigits: 6), _toCurrency); - UpdateTypography(); } private void ApplyLoadingState() @@ -338,103 +333,6 @@ public partial class ExchangeRateCalculatorWidget : UserControl, IDesktopCompone return Math.Clamp(Math.Min(cellScale, Math.Min(widthScale, heightScale)), 0.72, 1.95); } - private void UpdateTypography() - { - var layoutWidth = LayoutRoot.Width > 1 ? LayoutRoot.Width : 304d; - var layoutHeight = LayoutRoot.Height > 1 ? LayoutRoot.Height : 304d; - - var fromStackWidth = Math.Max(72, (layoutWidth - 86) * 0.36); - var amountWidth = Math.Max(116, (layoutWidth - 86) * 0.50); - var rateWidth = Math.Max(120, layoutWidth - 24); - var statusWidth = Math.Max(120, layoutWidth - 24); - - FromCurrencyCodeTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - FromCurrencyCodeTextBlock.Text, - fromStackWidth, - 26, - 1, - 11, - 20, - FontWeight.SemiBold, - 1.06d, - MiSansFontFamily); - FromCurrencyNameTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - FromCurrencyNameTextBlock.Text, - fromStackWidth, - 18, - 1, - 9, - 14, - FontWeight.Normal, - 1.06d, - MiSansFontFamily); - ToCurrencyCodeTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - ToCurrencyCodeTextBlock.Text, - fromStackWidth, - 26, - 1, - 11, - 20, - FontWeight.SemiBold, - 1.06d, - MiSansFontFamily); - ToCurrencyNameTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - ToCurrencyNameTextBlock.Text, - fromStackWidth, - 18, - 1, - 9, - 14, - FontWeight.Normal, - 1.06d, - MiSansFontFamily); - - InputAmountTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - InputAmountTextBlock.Text, - amountWidth, - Math.Max(42, layoutHeight * 0.16), - 1, - 20, - 42, - FontWeight.Bold, - 1.02d, - MiSansFontFamily); - ConvertedAmountTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - ConvertedAmountTextBlock.Text, - amountWidth, - Math.Max(42, layoutHeight * 0.16), - 1, - 20, - 42, - FontWeight.Bold, - 1.02d, - MiSansFontFamily); - RateTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - RateTextBlock.Text, - rateWidth, - 20, - 1, - 10, - 15, - FontWeight.Normal, - 1.06d, - MiSansFontFamily); - - if (StatusTextBlock.IsVisible) - { - StatusTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - StatusTextBlock.Text, - statusWidth, - 22, - 1, - 10, - 16, - FontWeight.Normal, - 1.06d, - MiSansFontFamily); - } - } - private void CancelRefreshRequest() { var cts = Interlocked.Exchange(ref _refreshCts, null); diff --git a/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs index 1ceef5b..4a6e358 100644 --- a/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/ExtendedWeatherWidget.axaml.cs @@ -9,7 +9,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Host.Abstractions; using LanMountainDesktop.Models; @@ -545,91 +544,34 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge var temperatureSample = string.IsNullOrWhiteSpace(TemperatureTextBlock.Text) ? "00°" : TemperatureTextBlock.Text.Trim(); + var temperatureGlyphCount = Math.Clamp(temperatureSample.Length, 3, 6); var temperatureMaxWidth = Math.Max(30, innerWidth - iconSize - SummaryGrid.ColumnSpacing - 6); var rawTemperatureSize = Math.Clamp(Lerp(72, 102, iconGrowth) * topScale, 14, 340); - var temperatureLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TemperatureTextBlock.Text, - temperatureMaxWidth, - Math.Max(18, summaryHeight * 0.84), - 1, - 1, - Math.Max(10, rawTemperatureSize * 0.42), - rawTemperatureSize, - [ToVariableWeight(Lerp(300, 380, emphasis))], - 1.02); - TemperatureTextBlock.FontSize = temperatureLayout.FontSize; - TemperatureTextBlock.FontWeight = temperatureLayout.Weight; + var fitTemperatureSize = temperatureMaxWidth / (temperatureGlyphCount * 0.62); + TemperatureTextBlock.FontSize = Math.Clamp(Math.Min(rawTemperatureSize, fitTemperatureSize), 10, 340); + TemperatureTextBlock.FontWeight = ToVariableWeight(Lerp(300, 380, emphasis)); TemperatureTextBlock.MaxWidth = Math.Clamp(temperatureMaxWidth, 30, Math.Max(300, innerWidth * 0.66)); TemperatureTextBlock.Margin = new Thickness(0, Math.Clamp(-2.2 * topScale, -12, 0), 0, 0); - var cityBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - innerWidth * 0.36, - Math.Max(16, summaryHeight * 0.34), - preferredSizeScale: 0.28d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - CityInfoBadge.Padding = cityBadge.Padding; - CityInfoBadge.CornerRadius = new CornerRadius(cityBadge.Size / 2d); - CityInfoBadge.MaxWidth = Math.Clamp(innerWidth * 0.36, 34, 420); - var cityLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - CityTextBlock.Text, - Math.Max(24, CityInfoBadge.MaxWidth - cityBadge.Padding.Left - cityBadge.Padding.Right), - Math.Max(12, summaryHeight * 0.36), - 1, - 1, - 6, - Math.Max(6, 18.5 * topScale), - [ToVariableWeight(Lerp(530, 620, emphasis))], - 1.08); - CityTextBlock.FontSize = cityLayout.FontSize; - CityTextBlock.FontWeight = cityLayout.Weight; - CityTextBlock.LineHeight = cityLayout.LineHeight; - CityTextBlock.MaxWidth = CityInfoBadge.MaxWidth; - - var conditionBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - innerWidth * 0.25, - Math.Max(16, summaryHeight * 0.34), - preferredSizeScale: 0.26d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - ConditionInfoBadge.Padding = conditionBadge.Padding; - ConditionInfoBadge.CornerRadius = new CornerRadius(conditionBadge.Size / 2d); - ConditionInfoBadge.MaxWidth = Math.Clamp(innerWidth * 0.25, 26, 340); - var conditionLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ConditionTextBlock.Text, - Math.Max(24, ConditionInfoBadge.MaxWidth - conditionBadge.Padding.Left - conditionBadge.Padding.Right), - Math.Max(12, summaryHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, 20 * topScale), - [ToVariableWeight(Lerp(580, 660, emphasis))], - 1.06); - var rangeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - RangeTextBlock.Text, - Math.Max(24, ConditionInfoBadge.MaxWidth - conditionBadge.Padding.Left - conditionBadge.Padding.Right), - Math.Max(12, summaryHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, 20 * topScale), - [ToVariableWeight(Lerp(600, 680, emphasis))], - 1.06); - ConditionTextBlock.FontSize = conditionLayout.FontSize; - ConditionTextBlock.FontWeight = conditionLayout.Weight; - ConditionTextBlock.LineHeight = conditionLayout.LineHeight; - RangeTextBlock.FontSize = rangeLayout.FontSize; - RangeTextBlock.FontWeight = rangeLayout.Weight; - RangeTextBlock.LineHeight = rangeLayout.LineHeight; - CityTextBlock.MaxWidth = CityInfoBadge.MaxWidth; - ConditionTextBlock.MaxWidth = ConditionInfoBadge.MaxWidth; - RangeTextBlock.MaxWidth = ConditionInfoBadge.MaxWidth; + var cityFontSize = Math.Clamp(18.5 * topScale, 7, 86); + var conditionFontSize = Math.Clamp(20 * topScale, 7, 90); + var rangeFontSize = Math.Clamp(20 * topScale, 7, 90); + CityTextBlock.FontSize = cityFontSize; + ConditionTextBlock.FontSize = conditionFontSize; + RangeTextBlock.FontSize = rangeFontSize; + CityTextBlock.FontWeight = ToVariableWeight(Lerp(530, 620, emphasis)); + ConditionTextBlock.FontWeight = ToVariableWeight(Lerp(580, 660, emphasis)); + RangeTextBlock.FontWeight = ToVariableWeight(Lerp(600, 680, emphasis)); + CityTextBlock.LineHeight = cityFontSize * 1.08; + ConditionTextBlock.LineHeight = conditionFontSize * 1.06; + RangeTextBlock.LineHeight = rangeFontSize * 1.06; WeatherIconImage.Width = iconSize; WeatherIconImage.Height = iconSize; WeatherIconImage.Margin = new Thickness(0, Math.Clamp(-2.4 * topScale, -12, 0), 0, 0); + ConditionTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.25, 28, 340); + RangeTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.31, 34, 380); + CityTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.36, 34, 420); HourlyPanelBorder.Padding = new Thickness(0); HourlyPanelBorder.CornerRadius = new CornerRadius(0); @@ -648,30 +590,10 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge var hourlyStackSpacing = Math.Clamp(2 * hourlyCellScale, 0.2, 10); for (var i = 0; i < _hourlyTempBlocks.Length; i++) { - var hourlyTempLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _hourlyTempBlocks[i].Text, - Math.Clamp(hourlyCellWidth, 12, 260), - Math.Max(10, hourlyHeight * 0.42), - 1, - 1, - 6, - hourlyTempSize, - [ToVariableWeight(Lerp(540, 650, emphasis))], - 1.02); - var hourlyTimeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _hourlyTimeBlocks[i].Text, - Math.Clamp(hourlyCellWidth, 12, 260), - Math.Max(10, hourlyHeight * 0.34), - 1, - 1, - 6, - hourlyTimeSize, - [ToVariableWeight(Lerp(450, 560, emphasis))], - 1.02); - _hourlyTempBlocks[i].FontSize = hourlyTempLayout.FontSize; - _hourlyTimeBlocks[i].FontSize = hourlyTimeLayout.FontSize; - _hourlyTempBlocks[i].FontWeight = hourlyTempLayout.Weight; - _hourlyTimeBlocks[i].FontWeight = hourlyTimeLayout.Weight; + _hourlyTempBlocks[i].FontSize = hourlyTempSize; + _hourlyTimeBlocks[i].FontSize = hourlyTimeSize; + _hourlyTempBlocks[i].FontWeight = ToVariableWeight(Lerp(540, 650, emphasis)); + _hourlyTimeBlocks[i].FontWeight = ToVariableWeight(Lerp(450, 560, emphasis)); _hourlyTempBlocks[i].MaxWidth = Math.Clamp(hourlyCellWidth, 12, 260); _hourlyTimeBlocks[i].MaxWidth = Math.Clamp(hourlyCellWidth, 12, 260); _hourlyIconBlocks[i].Width = hourlyIconSize; @@ -698,42 +620,12 @@ public partial class ExtendedWeatherWidget : UserControl, IDesktopComponentWidge var dailyHighRightGap = Math.Clamp(innerWidth * 0.018, 1, 28); for (var i = 0; i < _dailyLabelBlocks.Length; i++) { - var dailyLabelLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _dailyLabelBlocks[i].Text, - dailyLabelMaxWidth, - Math.Max(10, dailyRowHeight * 0.50), - 1, - 1, - 6, - dailyLabelSize, - [ToVariableWeight(Lerp(520, 620, emphasis))], - 1.04); - var dailyHighLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _dailyHighBlocks[i].Text, - dailyHighWidth, - Math.Max(10, dailyRowHeight * 0.42), - 1, - 1, - 6, - dailyTempSize, - [ToVariableWeight(Lerp(560, 680, emphasis))], - 1.02); - var dailyLowLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _dailyLowBlocks[i].Text, - dailyLowWidth, - Math.Max(10, dailyRowHeight * 0.42), - 1, - 1, - 6, - dailyTempSize, - [ToVariableWeight(Lerp(470, 590, emphasis))], - 1.02); - _dailyLabelBlocks[i].FontSize = dailyLabelLayout.FontSize; - _dailyHighBlocks[i].FontSize = dailyHighLayout.FontSize; - _dailyLowBlocks[i].FontSize = dailyLowLayout.FontSize; - _dailyLabelBlocks[i].FontWeight = dailyLabelLayout.Weight; - _dailyHighBlocks[i].FontWeight = dailyHighLayout.Weight; - _dailyLowBlocks[i].FontWeight = dailyLowLayout.Weight; + _dailyLabelBlocks[i].FontSize = dailyLabelSize; + _dailyHighBlocks[i].FontSize = dailyTempSize; + _dailyLowBlocks[i].FontSize = dailyTempSize; + _dailyLabelBlocks[i].FontWeight = ToVariableWeight(Lerp(520, 620, emphasis)); + _dailyHighBlocks[i].FontWeight = ToVariableWeight(Lerp(560, 680, emphasis)); + _dailyLowBlocks[i].FontWeight = ToVariableWeight(Lerp(470, 590, emphasis)); _dailyLabelBlocks[i].MaxWidth = dailyLabelMaxWidth; _dailyHighBlocks[i].Width = dailyHighWidth; _dailyLowBlocks[i].Width = dailyLowWidth; diff --git a/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs index 16e7070..2873a8b 100644 --- a/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/HourlyWeatherWidget.axaml.cs @@ -11,7 +11,6 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Platform; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Host.Abstractions; using LanMountainDesktop.Models; @@ -1272,88 +1271,31 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, var temperatureSample = string.IsNullOrWhiteSpace(TemperatureTextBlock.Text) ? "00°" : TemperatureTextBlock.Text.Trim(); + var temperatureGlyphCount = Math.Clamp(temperatureSample.Length, 3, 6); var temperatureMaxWidth = Math.Max(28, innerWidth - iconSize - TopRowGrid.ColumnSpacing - 4); var rawTemperatureSize = Math.Clamp(Lerp(64, 92, iconGrowth) * topScale, 12, 320); - var temperatureLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TemperatureTextBlock.Text, - temperatureMaxWidth, - Math.Max(18, topZoneHeight * 0.84), - 1, - 1, - Math.Max(9, rawTemperatureSize * 0.42), - rawTemperatureSize, - [ToVariableWeight(Lerp(300, 360, emphasis))], - 1.02); - TemperatureTextBlock.FontSize = temperatureLayout.FontSize; - TemperatureTextBlock.FontWeight = temperatureLayout.Weight; + var fitTemperatureSize = temperatureMaxWidth / (temperatureGlyphCount * 0.62); + TemperatureTextBlock.FontSize = Math.Clamp(Math.Min(rawTemperatureSize, fitTemperatureSize), 9, 320); + TemperatureTextBlock.FontWeight = ToVariableWeight(Lerp(300, 360, emphasis)); TemperatureTextBlock.Margin = new Thickness(0, Math.Clamp(-2.0 * topScale, -10, 0), 0, 0); TemperatureTextBlock.MaxWidth = Math.Clamp(temperatureMaxWidth, 28, Math.Max(280, innerWidth * 0.68)); - var cityBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - innerWidth * 0.37, - Math.Max(16, topZoneHeight * 0.34), - preferredSizeScale: 0.28d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - CityInfoBadge.Padding = cityBadge.Padding; - CityInfoBadge.CornerRadius = new CornerRadius(cityBadge.Size / 2d); - CityInfoBadge.MaxWidth = Math.Clamp(innerWidth * 0.37, 34, 460); + CityInfoBadge.Padding = new Thickness(0); + CityInfoBadge.CornerRadius = new CornerRadius(0); LocationIcon.FontSize = Math.Clamp(13 * topScale, 6, 52); - var cityLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - CityTextBlock.Text, - Math.Max(24, CityInfoBadge.MaxWidth - cityBadge.Padding.Left - cityBadge.Padding.Right), - Math.Max(12, topZoneHeight * 0.36), - 1, - 1, - 6, - Math.Max(6, 18.5 * topScale), - [ToVariableWeight(Lerp(530, 620, emphasis))], - 1.08); - CityTextBlock.FontSize = cityLayout.FontSize; - CityTextBlock.FontWeight = cityLayout.Weight; - CityTextBlock.LineHeight = cityLayout.LineHeight; - CityTextBlock.MaxWidth = CityInfoBadge.MaxWidth; + CityTextBlock.FontSize = Math.Clamp(18.5 * topScale, 7, 88); + CityTextBlock.FontWeight = ToVariableWeight(Lerp(530, 620, emphasis)); + CityTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.37, 34, 460); - var conditionBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - innerWidth * 0.24, - Math.Max(16, bottomZoneHeight * 0.34), - preferredSizeScale: 0.26d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - ConditionInfoBadge.Padding = conditionBadge.Padding; - ConditionInfoBadge.CornerRadius = new CornerRadius(conditionBadge.Size / 2d); - ConditionInfoBadge.MaxWidth = Math.Clamp(innerWidth * 0.24, 26, 320); + ConditionInfoBadge.Padding = new Thickness(0); + ConditionInfoBadge.CornerRadius = new CornerRadius(0); ConditionRangeStack.Spacing = Math.Clamp(8.5 * topScale, 1, 24); - var conditionLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ConditionTextBlock.Text, - Math.Max(24, ConditionInfoBadge.MaxWidth - conditionBadge.Padding.Left - conditionBadge.Padding.Right), - Math.Max(12, bottomZoneHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, 19 * topScale), - [ToVariableWeight(Lerp(580, 660, emphasis))], - 1.10); - var rangeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - RangeTextBlock.Text, - Math.Max(24, ConditionInfoBadge.MaxWidth - conditionBadge.Padding.Left - conditionBadge.Padding.Right), - Math.Max(12, bottomZoneHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, 21 * topScale), - [ToVariableWeight(Lerp(600, 680, emphasis))], - 1.10); - ConditionTextBlock.FontSize = conditionLayout.FontSize; - ConditionTextBlock.FontWeight = conditionLayout.Weight; - ConditionTextBlock.LineHeight = conditionLayout.LineHeight; - RangeTextBlock.FontSize = rangeLayout.FontSize; - RangeTextBlock.FontWeight = rangeLayout.Weight; - RangeTextBlock.LineHeight = rangeLayout.LineHeight; - ConditionTextBlock.MaxWidth = ConditionInfoBadge.MaxWidth; - RangeTextBlock.MaxWidth = ConditionInfoBadge.MaxWidth; + ConditionTextBlock.FontSize = Math.Clamp(19 * topScale, 7, 78); + RangeTextBlock.FontSize = Math.Clamp(21 * topScale, 7, 84); + ConditionTextBlock.FontWeight = ToVariableWeight(Lerp(580, 660, emphasis)); + RangeTextBlock.FontWeight = ToVariableWeight(Lerp(600, 680, emphasis)); + ConditionTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.24, 26, 320); + RangeTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.31, 32, 360); BottomInfoStack.Spacing = Math.Clamp(2.0 * topScale, 0.4, 14); WeatherIconImage.Width = iconSize; @@ -1383,34 +1325,14 @@ public partial class HourlyWeatherWidget : UserControl, IDesktopComponentWidget, for (var i = 0; i < _hourlyTimeBlocks.Length; i++) { - var hourlyTempLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _hourlyTempBlocks[i].Text, - Math.Clamp(hourlyCellWidth, 12, 240), - Math.Max(10, hourlyCellScale * 28), - 1, - 1, - 6, - hourlyTempSize, - [ToVariableWeight(Lerp(580, 690, emphasis))], - 1.02); - var hourlyTimeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _hourlyTimeBlocks[i].Text, - Math.Clamp(hourlyCellWidth, 12, 240), - Math.Max(10, hourlyCellScale * 24), - 1, - 1, - 6, - hourlyTimeSize, - [ToVariableWeight(Lerp(500, 600, emphasis))], - 1.02); - _hourlyTempBlocks[i].FontSize = hourlyTempLayout.FontSize; - _hourlyTimeBlocks[i].FontSize = hourlyTimeLayout.FontSize; + _hourlyTempBlocks[i].FontSize = hourlyTempSize; + _hourlyTimeBlocks[i].FontSize = hourlyTimeSize; _hourlyIconBlocks[i].Width = hourlyIconSize; _hourlyIconBlocks[i].Height = hourlyIconSize; _hourlyTimeBlocks[i].MaxWidth = Math.Clamp(hourlyCellWidth, 12, 240); _hourlyTempBlocks[i].MaxWidth = Math.Clamp(hourlyCellWidth, 12, 240); - _hourlyTimeBlocks[i].FontWeight = hourlyTimeLayout.Weight; - _hourlyTempBlocks[i].FontWeight = hourlyTempLayout.Weight; + _hourlyTimeBlocks[i].FontWeight = ToVariableWeight(Lerp(500, 600, emphasis)); + _hourlyTempBlocks[i].FontWeight = ToVariableWeight(Lerp(580, 690, emphasis)); if (_hourlyTimeBlocks[i].Parent is StackPanel hourlyStack) { hourlyStack.Spacing = stackSpacing; diff --git a/LanMountainDesktop/Views/Components/IfengNewsWidget.axaml.cs b/LanMountainDesktop/Views/Components/IfengNewsWidget.axaml.cs index 7f874ba..6836490 100644 --- a/LanMountainDesktop/Views/Components/IfengNewsWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/IfengNewsWidget.axaml.cs @@ -15,7 +15,6 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -463,23 +462,11 @@ public partial class IfengNewsWidget : UserControl, IDesktopComponentWidget, IRe visual.ImageHost.Height = imageHeight; visual.ImageHost.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(imageHeight * 0.15, 8, 16); - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - visual.TitleTextBlock.Text, - textWidth, - itemHeight, - minLines: 1, - maxLines: ComponentTypographyLayoutService.CountTextDisplayUnits(visual.TitleTextBlock.Text) > 28 ? 2 : 1, - minFontSize: Math.Clamp(titleFont * 0.72, 10, 16), - maxFontSize: titleFont, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Bold }, - lineHeightFactor: 1.12d, - fontFamily: MiSansFontFamily); visual.TitleTextBlock.MaxWidth = textWidth; - visual.TitleTextBlock.FontSize = titleLayout.FontSize; - visual.TitleTextBlock.LineHeight = titleLayout.LineHeight; - visual.TitleTextBlock.MinHeight = titleLayout.LineHeight * titleLayout.MaxLines; - visual.TitleTextBlock.MaxLines = titleLayout.MaxLines; - visual.TitleTextBlock.FontWeight = titleLayout.Weight; + visual.TitleTextBlock.FontSize = titleFont; + visual.TitleTextBlock.LineHeight = titleFont * 1.12; + visual.TitleTextBlock.MinHeight = visual.TitleTextBlock.LineHeight * 2; + visual.TitleTextBlock.MaxLines = 2; } StatusTextBlock.FontSize = Math.Clamp(titleFont, 10, 20); diff --git a/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs index 0e72031..d8e8476 100644 --- a/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/MultiDayWeatherWidget.axaml.cs @@ -9,7 +9,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Host.Abstractions; using LanMountainDesktop.Models; @@ -1121,88 +1120,31 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge var temperatureSample = string.IsNullOrWhiteSpace(TemperatureTextBlock.Text) ? "00°" : TemperatureTextBlock.Text.Trim(); + var temperatureGlyphCount = Math.Clamp(temperatureSample.Length, 3, 6); var temperatureMaxWidth = Math.Max(28, innerWidth - iconSize - TopRowGrid.ColumnSpacing - 4); var rawTemperatureSize = Math.Clamp(Lerp(64, 92, iconGrowth) * topScale, 12, 320); - var temperatureLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TemperatureTextBlock.Text, - temperatureMaxWidth, - Math.Max(18, topZoneHeight * 0.84), - 1, - 1, - Math.Max(9, rawTemperatureSize * 0.42), - rawTemperatureSize, - [ToVariableWeight(Lerp(300, 360, emphasis))], - 1.02); - TemperatureTextBlock.FontSize = temperatureLayout.FontSize; - TemperatureTextBlock.FontWeight = temperatureLayout.Weight; + var fitTemperatureSize = temperatureMaxWidth / (temperatureGlyphCount * 0.62); + TemperatureTextBlock.FontSize = Math.Clamp(Math.Min(rawTemperatureSize, fitTemperatureSize), 9, 320); + TemperatureTextBlock.FontWeight = ToVariableWeight(Lerp(300, 360, emphasis)); TemperatureTextBlock.Margin = new Thickness(0, Math.Clamp(-2.0 * topScale, -10, 0), 0, 0); TemperatureTextBlock.MaxWidth = Math.Clamp(temperatureMaxWidth, 28, Math.Max(280, innerWidth * 0.68)); - var cityBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - innerWidth * 0.37, - Math.Max(16, topZoneHeight * 0.34), - preferredSizeScale: 0.28d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - CityInfoBadge.Padding = cityBadge.Padding; - CityInfoBadge.CornerRadius = new CornerRadius(cityBadge.Size / 2d); - CityInfoBadge.MaxWidth = Math.Clamp(innerWidth * 0.37, 34, 460); + CityInfoBadge.Padding = new Thickness(0); + CityInfoBadge.CornerRadius = new CornerRadius(0); LocationIcon.FontSize = Math.Clamp(13 * topScale, 6, 52); - var cityLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - CityTextBlock.Text, - Math.Max(24, CityInfoBadge.MaxWidth - cityBadge.Padding.Left - cityBadge.Padding.Right), - Math.Max(12, topZoneHeight * 0.36), - 1, - 1, - 6, - Math.Max(6, 18.5 * topScale), - [ToVariableWeight(Lerp(530, 620, emphasis))], - 1.08); - CityTextBlock.FontSize = cityLayout.FontSize; - CityTextBlock.FontWeight = cityLayout.Weight; - CityTextBlock.LineHeight = cityLayout.LineHeight; - CityTextBlock.MaxWidth = CityInfoBadge.MaxWidth; + CityTextBlock.FontSize = Math.Clamp(18.5 * topScale, 7, 88); + CityTextBlock.FontWeight = ToVariableWeight(Lerp(530, 620, emphasis)); + CityTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.37, 34, 460); - var conditionBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - innerWidth * 0.24, - Math.Max(16, topZoneHeight * 0.34), - preferredSizeScale: 0.26d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - ConditionInfoBadge.Padding = conditionBadge.Padding; - ConditionInfoBadge.CornerRadius = new CornerRadius(conditionBadge.Size / 2d); - ConditionInfoBadge.MaxWidth = Math.Clamp(innerWidth * 0.24, 26, 320); + ConditionInfoBadge.Padding = new Thickness(0); + ConditionInfoBadge.CornerRadius = new CornerRadius(0); ConditionIconStack.Spacing = Math.Clamp(8.5 * topScale, 1, 24); - var conditionLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ConditionTextBlock.Text, - Math.Max(24, ConditionInfoBadge.MaxWidth - conditionBadge.Padding.Left - conditionBadge.Padding.Right), - Math.Max(12, topZoneHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, 19 * topScale), - [ToVariableWeight(Lerp(580, 660, emphasis))], - 1.06); - var rangeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - RangeTextBlock.Text, - Math.Max(24, ConditionInfoBadge.MaxWidth - conditionBadge.Padding.Left - conditionBadge.Padding.Right), - Math.Max(12, topZoneHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, 21 * topScale), - [ToVariableWeight(Lerp(600, 680, emphasis))], - 1.06); - ConditionTextBlock.FontSize = conditionLayout.FontSize; - ConditionTextBlock.FontWeight = conditionLayout.Weight; - ConditionTextBlock.LineHeight = conditionLayout.LineHeight; - RangeTextBlock.FontSize = rangeLayout.FontSize; - RangeTextBlock.FontWeight = rangeLayout.Weight; - RangeTextBlock.LineHeight = rangeLayout.LineHeight; - ConditionTextBlock.MaxWidth = ConditionInfoBadge.MaxWidth; - RangeTextBlock.MaxWidth = ConditionInfoBadge.MaxWidth; + ConditionTextBlock.FontSize = Math.Clamp(19 * topScale, 7, 78); + RangeTextBlock.FontSize = Math.Clamp(21 * topScale, 7, 84); + ConditionTextBlock.FontWeight = ToVariableWeight(Lerp(580, 660, emphasis)); + RangeTextBlock.FontWeight = ToVariableWeight(Lerp(600, 680, emphasis)); + ConditionTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.24, 26, 320); + RangeTextBlock.MaxWidth = Math.Clamp(innerWidth * 0.31, 32, 360); BottomInfoStack.Spacing = Math.Clamp(2.0 * topScale, 0.4, 14); WeatherIconImage.Width = iconSize; @@ -1231,34 +1173,14 @@ public partial class MultiDayWeatherWidget : UserControl, IDesktopComponentWidge for (var i = 0; i < _hourlyTimeBlocks.Length; i++) { - var hourlyTimeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _hourlyTimeBlocks[i].Text, - Math.Clamp(hourlyCellWidth, 12, 260), - Math.Max(10, bottomZoneHeight * 0.34), - 1, - 1, - 6, - forecastLabelSize, - [ToVariableWeight(Lerp(500, 600, emphasis))], - 1.02); - var hourlyTempLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - _hourlyTempBlocks[i].Text, - Math.Clamp(hourlyCellWidth, 12, 260), - Math.Max(10, bottomZoneHeight * 0.42), - 1, - 1, - 6, - forecastRangeSize, - [ToVariableWeight(Lerp(580, 690, emphasis))], - 1.02); - _hourlyTimeBlocks[i].FontSize = hourlyTimeLayout.FontSize; - _hourlyTempBlocks[i].FontSize = hourlyTempLayout.FontSize; + _hourlyTimeBlocks[i].FontSize = forecastLabelSize; + _hourlyTempBlocks[i].FontSize = forecastRangeSize; _hourlyIconBlocks[i].Width = forecastIconSize; _hourlyIconBlocks[i].Height = forecastIconSize; _hourlyTimeBlocks[i].MaxWidth = Math.Clamp(hourlyCellWidth, 12, 260); _hourlyTempBlocks[i].MaxWidth = Math.Clamp(hourlyCellWidth, 12, 260); - _hourlyTimeBlocks[i].FontWeight = hourlyTimeLayout.Weight; - _hourlyTempBlocks[i].FontWeight = hourlyTempLayout.Weight; + _hourlyTimeBlocks[i].FontWeight = ToVariableWeight(Lerp(500, 600, emphasis)); + _hourlyTempBlocks[i].FontWeight = ToVariableWeight(Lerp(580, 690, emphasis)); _hourlyTimeBlocks[i].TextAlignment = TextAlignment.Center; _hourlyTempBlocks[i].TextAlignment = TextAlignment.Center; if (_hourlyTimeBlocks[i].Parent is StackPanel hourlyStack) diff --git a/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs b/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs index 8e65b29..896ebe7 100644 --- a/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/MusicControlWidget.axaml.cs @@ -12,7 +12,6 @@ using Avalonia.Media.Imaging; using Avalonia.Styling; using Avalonia.Threading; using FluentIcons.Common; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -124,7 +123,6 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget, NextIcon.FontSize = Math.Clamp(18 * scale, 13, 24); FavoriteIcon.FontSize = Math.Clamp(16 * scale, 11, 21); - UpdateTypography(); UpdateProgressVisual(_progressRatio, _isProgressIndeterminate); } @@ -420,7 +418,6 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget, SetCoverImage(state.ThumbnailBytes); ApplyActionButtonState(state); - UpdateTypography(); UpdateSourceAppButtonTooltip(); } @@ -555,67 +552,6 @@ public partial class MusicControlWidget : UserControl, IDesktopComponentWidget, }; } - private void UpdateTypography() - { - var scale = ResolveScale(); - var rootWidth = Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 10.5; - var rootHeight = Bounds.Height > 1 ? Bounds.Height : _currentCellSize * 4.2; - var headerWidth = Math.Max(120, rootWidth - Math.Max(84, SourceAppButton.MinWidth) - 86); - var titleWidth = Math.Max(96, headerWidth); - var metaWidth = Math.Max(96, headerWidth); - var timelineWidth = Math.Max(52, rootWidth * 0.18); - var statusWidth = Math.Max(72, Math.Min(headerWidth, rootWidth * 0.26)); - - TitleTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - TitleTextBlock.Text, - titleWidth, - Math.Max(24, rootHeight * 0.12), - 1, - 12, - Math.Clamp(20 * scale, 12, 28), - FontWeight.SemiBold, - 1.06d); - - var artistMaxLines = ArtistTextBlock.MaxLines <= 0 ? 1 : ArtistTextBlock.MaxLines; - ArtistTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - ArtistTextBlock.Text, - metaWidth, - artistMaxLines > 1 ? Math.Max(32, rootHeight * 0.12) : Math.Max(20, rootHeight * 0.08), - artistMaxLines, - 9, - Math.Clamp(14 * scale, 9, 18), - FontWeight.SemiBold, - 1.06d); - - PositionTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - PositionTextBlock.Text, - timelineWidth, - 18, - 1, - 8, - Math.Clamp(13 * scale, 8, 15), - FontWeight.SemiBold, - 1.05d); - DurationTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - DurationTextBlock.Text, - timelineWidth, - 18, - 1, - 8, - Math.Clamp(13 * scale, 8, 15), - FontWeight.SemiBold, - 1.05d); - StatusTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - StatusTextBlock.Text, - statusWidth, - 18, - 1, - 8, - Math.Clamp(13 * scale, 8, 15), - FontWeight.Medium, - 1.05d); - } - private string L(string key, string fallback) { return _localizationService.GetString(_languageCode, key, fallback); diff --git a/LanMountainDesktop/Views/Components/OfficeRecentDocumentsWidget.axaml.cs b/LanMountainDesktop/Views/Components/OfficeRecentDocumentsWidget.axaml.cs index 4e8db7a..ba1782a 100644 --- a/LanMountainDesktop/Views/Components/OfficeRecentDocumentsWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/OfficeRecentDocumentsWidget.axaml.cs @@ -5,8 +5,6 @@ using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; using Avalonia.Input; -using Avalonia.Media; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -75,6 +73,8 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen Resources["OfficeRecentDocumentsAccentSize"] = accentSize; Resources["OfficeRecentDocumentsAccentCornerRadius"] = new CornerRadius(accentSize / 2d); + Resources["OfficeRecentDocumentsHeaderFontSize"] = Math.Clamp(18 * scale, 12, 24); + Resources["OfficeRecentDocumentsStatusFontSize"] = Math.Clamp(14 * scale, 10, 18); Resources["OfficeRecentDocumentsDocumentSpacing"] = ComponentChromeCornerRadiusHelper.SafeValue(8 * scale, 4, 12, null, 0.40d); var cardWidth = Math.Clamp(130 * scale, 96, 180); @@ -83,7 +83,8 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen Resources["OfficeRecentDocumentsDocumentCardHeight"] = cardHeight; Resources["OfficeRecentDocumentsCardCornerRadius"] = ComponentChromeCornerRadiusHelper.Scale(16 * scale, 10, 24); Resources["OfficeRecentDocumentsCardPadding"] = new Thickness(ComponentChromeCornerRadiusHelper.SafeValue(10 * scale, 6, 16, null, 0.50d)); - UpdateTypographyResources(); + Resources["OfficeRecentDocumentsDocumentTitleFontSize"] = Math.Clamp(12 * scale, 10, 18); + Resources["OfficeRecentDocumentsDocumentTimeFontSize"] = Math.Clamp(10 * scale, 8, 14); } public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) @@ -127,19 +128,16 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen { StatusTextBlock.Text = "\u6682\u65e0\u6700\u8fd1\u6587\u6863"; StatusTextBlock.IsVisible = true; - UpdateTypographyResources(); return; } UpdateDisplay(); - UpdateTypographyResources(); } catch (Exception ex) { AppLogger.Warn("OfficeRecentDocsWidget", "Failed to load recent Office documents.", ex); StatusTextBlock.Text = "\u52a0\u8f7d\u5931\u8d25"; StatusTextBlock.IsVisible = true; - UpdateTypographyResources(); } finally { @@ -165,7 +163,6 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen }).ToList(); DocumentsItemsControl.ItemsSource = displayItems; - UpdateTypographyResources(); } private static string GetTimeAgo(DateTime dateTime) @@ -218,70 +215,4 @@ public partial class OfficeRecentDocumentsWidget : UserControl, IDesktopComponen } } } - - private void UpdateTypographyResources() - { - var width = Bounds.Width > 1 ? Bounds.Width : 640d; - var cardWidth = (double?)Resources["OfficeRecentDocumentsDocumentCardWidth"] ?? 130d; - var cardHeight = (double?)Resources["OfficeRecentDocumentsDocumentCardHeight"] ?? 90d; - var cardPadding = (Thickness?)Resources["OfficeRecentDocumentsCardPadding"] ?? new Thickness(10); - var rootPadding = (Thickness?)Resources["OfficeRecentDocumentsRootPadding"] ?? new Thickness(12, 10, 12, 10); - var contentMargin = (Thickness?)Resources["OfficeRecentDocumentsContentMargin"] ?? new Thickness(16, 14, 16, 14); - - var innerWidth = Math.Max(180, width - rootPadding.Left - rootPadding.Right - contentMargin.Left - contentMargin.Right); - var headerWidth = Math.Max(120, innerWidth * 0.48); - var statusWidth = Math.Max(120, innerWidth * 0.40); - - Resources["OfficeRecentDocumentsHeaderFontSize"] = ComponentTypographyLayoutService.FitFontSize( - HeaderTextBlock.Text, - headerWidth, - 24, - 1, - 12, - 24, - FontWeight.SemiBold, - 1.05d); - - Resources["OfficeRecentDocumentsStatusFontSize"] = ComponentTypographyLayoutService.FitFontSize( - StatusTextBlock.Text, - statusWidth, - 22, - 1, - 10, - 18, - FontWeight.Normal, - 1.06d); - - var documentTexts = _documents.Count == 0 - ? new[] { "Sample Office Document" } - : _documents.Select(item => item.FileName).Where(text => !string.IsNullOrWhiteSpace(text)).ToArray(); - var longestDocumentText = documentTexts.Length == 0 - ? "Sample Office Document" - : documentTexts.OrderByDescending(ComponentTypographyLayoutService.CountTextDisplayUnits).First(); - var titleWidth = Math.Max(72, cardWidth - cardPadding.Left - cardPadding.Right); - var titleHeight = Math.Max(28, cardHeight - cardPadding.Top - cardPadding.Bottom - 18); - Resources["OfficeRecentDocumentsDocumentTitleFontSize"] = ComponentTypographyLayoutService.FitFontSize( - longestDocumentText, - titleWidth, - titleHeight, - 2, - 10, - 18, - FontWeight.Medium, - 1.08d); - - var timeSamples = _documents.Count == 0 - ? new[] { "00/00" } - : _documents.Select(item => GetTimeAgo(item.LastModifiedTime)).ToArray(); - var longestTimeText = timeSamples.OrderByDescending(ComponentTypographyLayoutService.CountTextDisplayUnits).First(); - Resources["OfficeRecentDocumentsDocumentTimeFontSize"] = ComponentTypographyLayoutService.FitFontSize( - longestTimeText, - Math.Max(56, titleWidth * 0.72), - 18, - 1, - 8, - 14, - FontWeight.Normal, - 1.06d); - } } diff --git a/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs b/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs index bb297d9..879bc6c 100644 --- a/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/RecordingWidget.axaml.cs @@ -10,7 +10,6 @@ using Avalonia.Media; using Avalonia.Platform.Storage; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -109,8 +108,10 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget, IDe HintTextBlock.Margin = new Thickness(0, Math.Clamp(8 * contentScale, 4, 10), 0, 0); WaveformBarsPanel.Spacing = Math.Clamp(3 * contentScale, 1.6, 3.4); + TitleTextBlock.FontSize = Math.Clamp(19 * contentScale, 12, 20); + TimerTextBlock.FontSize = Math.Clamp(66 * contentScale, 34, 66); + HintTextBlock.FontSize = Math.Clamp(13 * contentScale, 9, 13); - UpdateTypography(); UpdateWaveformVisual(); } @@ -378,43 +379,49 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget, IDe PauseGlyphIcon.IsVisible = snapshot.State == AudioRecorderRuntimeState.Recording; PlayGlyphIcon.IsVisible = snapshot.State == AudioRecorderRuntimeState.Paused; - string hintText; if (!isSupported) { - hintText = L("recording.widget.hint.unsupported", "Microphone is unavailable"); + HintTextBlock.Text = L("recording.widget.hint.unsupported", "Microphone is unavailable"); + return; } - else if (snapshot.State == AudioRecorderRuntimeState.Recording) + + if (snapshot.State == AudioRecorderRuntimeState.Recording) { - hintText = L("recording.widget.hint.recording", "Recording"); + HintTextBlock.Text = L("recording.widget.hint.recording", "Recording"); + return; } - else if (snapshot.State == AudioRecorderRuntimeState.Paused) + + if (snapshot.State == AudioRecorderRuntimeState.Paused) { - hintText = L("recording.widget.hint.paused", "Paused"); + HintTextBlock.Text = L("recording.widget.hint.paused", "Paused"); + return; } - else if (snapshot.State == AudioRecorderRuntimeState.Error) + + if (snapshot.State == AudioRecorderRuntimeState.Error) { - hintText = string.IsNullOrWhiteSpace(snapshot.LastError) + HintTextBlock.Text = string.IsNullOrWhiteSpace(snapshot.LastError) ? L("recording.widget.hint.error", "Recording failed") : snapshot.LastError; + return; } - else + + if (!string.IsNullOrWhiteSpace(snapshot.LastSavedFilePath) && + !string.Equals(snapshot.LastSavedFilePath, _lastSavedFilePath, StringComparison.OrdinalIgnoreCase)) { - if (!string.IsNullOrWhiteSpace(snapshot.LastSavedFilePath) && - !string.Equals(snapshot.LastSavedFilePath, _lastSavedFilePath, StringComparison.OrdinalIgnoreCase)) - { - _lastSavedFilePath = snapshot.LastSavedFilePath; - } - - hintText = !string.IsNullOrWhiteSpace(_lastSavedFilePath) - ? string.Format( - CultureInfo.InvariantCulture, - L("recording.widget.hint.saved_format", "Saved {0}"), - Path.GetFileName(_lastSavedFilePath)) - : L("recording.widget.hint.ready", "Tap red button to record"); + _lastSavedFilePath = snapshot.LastSavedFilePath; } - HintTextBlock.Text = hintText; - UpdateTypography(); + if (!string.IsNullOrWhiteSpace(_lastSavedFilePath)) + { + var fileName = Path.GetFileName(_lastSavedFilePath); + HintTextBlock.Text = string.Format( + CultureInfo.InvariantCulture, + L("recording.widget.hint.saved_format", "Saved {0}"), + fileName); + return; + } + + HintTextBlock.Text = L("recording.widget.hint.ready", "Tap red button to record"); } private bool TryStartRecordingWithMonitoringHandoff() @@ -567,51 +574,6 @@ public partial class RecordingWidget : UserControl, IDesktopComponentWidget, IDe return duration.ToString(@"mm\:ss", CultureInfo.InvariantCulture); } - private void UpdateTypography() - { - var contentWidth = RecorderContentGrid.Bounds.Width > 1 ? RecorderContentGrid.Bounds.Width : 252d; - var contentHeight = RecorderContentGrid.Bounds.Height > 1 ? RecorderContentGrid.Bounds.Height : 240d; - var timerWidth = Math.Max(88, contentWidth * 0.84); - var timerHeight = Math.Max(34, contentHeight * 0.24); - var hintWidth = Math.Max(120, contentWidth * 0.86); - var hintHeight = Math.Max(24, contentHeight * 0.12); - - TitleTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - TitleTextBlock.Text, - Math.Max(96, contentWidth * 0.62), - 20, - 1, - 12, - 20, - FontWeight.SemiBold, - 1.05d); - - TimerTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - TimerTextBlock.Text, - timerWidth, - timerHeight, - 1, - 34, - 66, - FontWeight.SemiBold, - 1.0d); - - var hintLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - HintTextBlock.Text, - hintWidth, - hintHeight, - 1, - 2, - 9, - 13, - [FontWeight.Medium, FontWeight.Normal], - 1.10d); - HintTextBlock.FontSize = hintLayout.FontSize; - HintTextBlock.FontWeight = hintLayout.Weight; - HintTextBlock.MaxLines = hintLayout.MaxLines; - HintTextBlock.TextWrapping = hintLayout.MaxLines > 1 ? TextWrapping.Wrap : TextWrapping.NoWrap; - } - private static IBrush CreateBrush(string colorHex) { return new SolidColorBrush(Color.Parse(colorHex)); diff --git a/LanMountainDesktop/Views/Components/RemovableStorageWidget.axaml.cs b/LanMountainDesktop/Views/Components/RemovableStorageWidget.axaml.cs index e7bdc56..3660e17 100644 --- a/LanMountainDesktop/Views/Components/RemovableStorageWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/RemovableStorageWidget.axaml.cs @@ -9,7 +9,6 @@ using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; using FluentIcons.Avalonia; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Models; using LanMountainDesktop.PluginSdk; @@ -365,6 +364,11 @@ public partial class RemovableStorageWidget : UserControl, IDesktopComponentWidg IconBadge.CornerRadius = new CornerRadius(badgeSize * 0.5); DriveIcon.FontSize = Math.Clamp(24 * scale, 20, 32); + DriveNameTextBlock.FontSize = Math.Clamp(16 * scale, 13, 24); + DriveDetailTextBlock.FontSize = Math.Clamp(11.5 * scale, 10, 16); + StatusTextBlock.FontSize = Math.Clamp(12 * scale, 10, 17); + StatusTextBlock.MaxWidth = Math.Max(96, width - (RootBorder.Padding.Left + RootBorder.Padding.Right)); + var buttonHeight = Math.Clamp(42 * scale, 38, 54); var buttonPadding = Math.Clamp(14 * scale, 10, 20); var buttonCornerRadius = Math.Clamp(buttonHeight * 0.5, 18, 999); @@ -379,14 +383,14 @@ public partial class RemovableStorageWidget : UserControl, IDesktopComponentWidg OpenButtonIcon.FontSize = Math.Clamp(16 * scale, 14, 20); EjectButtonIcon.FontSize = Math.Clamp(16 * scale, 14, 20); + OpenButtonTextBlock.FontSize = Math.Clamp(13 * scale, 11.5, 18); + EjectButtonTextBlock.FontSize = Math.Clamp(13 * scale, 11.5, 18); AccentOrb.Width = Math.Clamp(width * 0.44, 96, 176); AccentOrb.Height = AccentOrb.Width; AccentOrb.CornerRadius = new CornerRadius(AccentOrb.Width * 0.5); AccentGlow.Height = Math.Clamp(76 * scale, 52, 110); AccentGlow.CornerRadius = new CornerRadius(AccentGlow.Height * 0.5); - - UpdateTypography(); } private RemovableStorageDrive? GetSelectedDrive() @@ -518,67 +522,6 @@ public partial class RemovableStorageWidget : UserControl, IDesktopComponentWidg return Math.Clamp(Math.Min(cellScale, Math.Min(widthScale, heightScale)), 0.72, 2.2); } - private void UpdateTypography() - { - var scale = ResolveScale(); - var width = Bounds.Width > 1 ? Bounds.Width : 220d; - var rootPadding = RootBorder.Padding; - var headerWidth = Math.Max(96, width - rootPadding.Left - rootPadding.Right - Math.Max(44, IconBadge.Width) - HeaderGrid.ColumnSpacing); - var statusWidth = Math.Max(120, width - rootPadding.Left - rootPadding.Right); - var buttonWidth = Math.Max(88, width - rootPadding.Left - rootPadding.Right); - - DriveNameTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - DriveNameTextBlock.Text, - headerWidth, - 22, - 1, - 13, - 24, - FontWeight.SemiBold, - 1.05d); - DriveDetailTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - DriveDetailTextBlock.Text, - headerWidth, - 18, - 1, - 10, - 16, - FontWeight.Normal, - 1.05d); - StatusTextBlock.FontSize = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - StatusTextBlock.Text, - statusWidth, - Math.Max(28, 40 * scale), - 1, - 3, - 10, - 17, - [FontWeight.Medium, FontWeight.Normal], - 1.10d).FontSize; - StatusTextBlock.MaxWidth = statusWidth; - StatusTextBlock.MaxLines = 3; - StatusTextBlock.TextWrapping = TextWrapping.Wrap; - - OpenButtonTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - OpenButtonTextBlock.Text, - buttonWidth - 32, - Math.Max(18, OpenButton.Height - 8), - 1, - 11, - 18, - FontWeight.SemiBold, - 1.04d); - EjectButtonTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - EjectButtonTextBlock.Text, - buttonWidth - 32, - Math.Max(18, EjectButton.Height - 8), - 1, - 11, - 18, - FontWeight.SemiBold, - 1.04d); - } - private string L(string key, string fallback) { return _localizationService.GetString(_languageCode, key, fallback); diff --git a/LanMountainDesktop/Views/Components/Stcn24ForumWidget.axaml.cs b/LanMountainDesktop/Views/Components/Stcn24ForumWidget.axaml.cs index 0596178..585f3ef 100644 --- a/LanMountainDesktop/Views/Components/Stcn24ForumWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/Stcn24ForumWidget.axaml.cs @@ -15,7 +15,6 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -676,32 +675,9 @@ public partial class Stcn24ForumWidget : UserControl, IDesktopComponentWidget, I visual.AvatarHost.Height = avatarSize; visual.AvatarHost.CornerRadius = new CornerRadius(avatarSize / 2d); - var avatarGlyphBox = ComponentTypographyLayoutService.ResolveGlyphBox( - avatarSize, - avatarSize, - preferredSizeScale: 0.60d, - minSize: 12, - maxSize: 18); - visual.AvatarFallbackText.Margin = avatarGlyphBox.Margin; - visual.AvatarFallbackText.FontSize = Math.Min(avatarFont, Math.Max(avatarGlyphBox.Width * 0.55d, 10)); - visual.AvatarFallbackText.MaxWidth = avatarGlyphBox.Width; - - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - visual.TitleTextBlock.Text, - titleMaxWidth, - Math.Max(avatarSize, rowPaddingVertical * 2d + 18), - minLines: 1, - maxLines: ComponentTypographyLayoutService.CountTextDisplayUnits(visual.TitleTextBlock.Text) > 24 ? 2 : 1, - minFontSize: Math.Clamp(titleFont * 0.72, 10, 14), - maxFontSize: titleFont, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Bold }, - lineHeightFactor: 1.08d, - fontFamily: MiSansFontFamily); - visual.TitleTextBlock.FontSize = titleLayout.FontSize; - visual.TitleTextBlock.LineHeight = titleLayout.LineHeight; + visual.AvatarFallbackText.FontSize = avatarFont; + visual.TitleTextBlock.FontSize = titleFont; visual.TitleTextBlock.MaxWidth = titleMaxWidth; - visual.TitleTextBlock.MaxLines = titleLayout.MaxLines; - visual.TitleTextBlock.FontWeight = titleLayout.Weight; } StatusTextBlock.FontSize = Math.Clamp(14 * softScale, 10, 18); diff --git a/LanMountainDesktop/Views/Components/StudyDeductionReasonsWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudyDeductionReasonsWidget.axaml.cs index 04a9959..d034f24 100644 --- a/LanMountainDesktop/Views/Components/StudyDeductionReasonsWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudyDeductionReasonsWidget.axaml.cs @@ -6,7 +6,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -285,88 +284,6 @@ public partial class StudyDeductionReasonsWidget : UserControl, IDesktopComponen ApplyVariableWeights(scale); ApplyLocalizedLabels(); - - var contentWidth = Math.Max(120, (Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 8) - RootBorder.Padding.Left - RootBorder.Padding.Right); - var contentHeight = Math.Max(78, (Bounds.Height > 1 ? Bounds.Height : _currentCellSize * 3) - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TitleTextBlock.Text, - Math.Max(120, contentWidth * 0.44), - Math.Max(18, contentHeight * 0.22), - 1, - 1, - 9, - Math.Clamp(20 * scale, 9, 20), - [TitleTextBlock.FontWeight], - 1.05); - TitleTextBlock.FontSize = titleLayout.FontSize; - TitleTextBlock.FontWeight = titleLayout.Weight; - TitleTextBlock.MaxLines = 1; - TitleTextBlock.TextWrapping = TextWrapping.NoWrap; - TitleTextBlock.LineHeight = titleLayout.LineHeight; - - var modeBadgeBox = ComponentTypographyLayoutService.ResolveBadgeBox( - Math.Max(64, contentWidth * 0.24), - Math.Max(20, contentHeight * 0.14), - preferredSizeScale: 0.48d, - minSize: 18, - maxSize: 42, - insetScale: 0.18d); - ModeBadgeBorder.Padding = modeBadgeBox.Padding; - ModeBadgeBorder.CornerRadius = new CornerRadius(Math.Clamp(modeBadgeBox.Size * 0.36, 5, 12)); - var modeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ModeTextBlock.Text, - Math.Max(54, modeBadgeBox.Width), - Math.Max(18, modeBadgeBox.Height), - 1, - 1, - 8, - Math.Clamp(16 * scale, 8, 16), - [ModeTextBlock.FontWeight], - 1.02); - ModeTextBlock.FontSize = modeLayout.FontSize; - ModeTextBlock.FontWeight = modeLayout.Weight; - ModeTextBlock.MaxLines = 1; - ModeTextBlock.TextWrapping = TextWrapping.NoWrap; - ModeTextBlock.LineHeight = modeLayout.LineHeight; - - foreach (var block in new[] { SustainedReasonTextBlock, TimeReasonTextBlock, SegmentReasonTextBlock }) - { - var layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - block.Text, - Math.Max(84, contentWidth * 0.34), - Math.Max(18, contentHeight * 0.14), - 1, - _isUltraCompactMode ? 1 : 2, - 9, - Math.Clamp(18 * scale, 9, 18), - [block.FontWeight], - 1.05); - block.FontSize = layout.FontSize; - block.FontWeight = layout.Weight; - block.MaxLines = layout.MaxLines; - block.TextWrapping = layout.MaxLines > 1 ? TextWrapping.Wrap : TextWrapping.NoWrap; - block.LineHeight = layout.LineHeight; - } - - foreach (var block in new[] { SustainedMetricTextBlock, TimeMetricTextBlock, SegmentMetricTextBlock, TotalLossTextBlock, ScoreTextBlock }) - { - var layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - block.Text, - Math.Max(72, contentWidth * 0.22), - Math.Max(16, contentHeight * 0.10), - 1, - 1, - 8, - Math.Clamp(16 * scale, 8, 16), - [block.FontWeight], - 1.02); - block.FontSize = layout.FontSize; - block.FontWeight = layout.Weight; - block.MaxLines = 1; - block.TextWrapping = TextWrapping.NoWrap; - block.LineHeight = layout.LineHeight; - } } private void ApplyTypographyByBackground(Color panelColor) diff --git a/LanMountainDesktop/Views/Components/StudyEnvironmentWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudyEnvironmentWidget.axaml.cs index 062f9cf..26dee40 100644 --- a/LanMountainDesktop/Views/Components/StudyEnvironmentWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudyEnvironmentWidget.axaml.cs @@ -5,7 +5,6 @@ using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; using LanMountainDesktop.ComponentSystem; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; @@ -252,77 +251,6 @@ public partial class StudyEnvironmentWidget : UserControl, IDesktopComponentWidg LayoutGrid.ColumnSpacing = hideStatusLabel ? Math.Clamp(6 * scale, 4, 10) : Math.Clamp(10 * scale, 7, 14); - - var availableWidth = Math.Max(72, (width > 0 ? width : _currentCellSize * 4) - RootBorder.Padding.Left - RootBorder.Padding.Right); - var availableHeight = Math.Max(34, (height > 0 ? height : _currentCellSize * 2) - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - var statusTitleWidth = Math.Max(50, availableWidth * 0.32); - var statusValueWidth = Math.Max(78, availableWidth - statusTitleWidth - Math.Clamp(6 * scale, 3, 8)); - var valueHeight = Math.Max(18, availableHeight * 0.44); - - var statusTitleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - StatusTitleTextBlock.Text, - statusTitleWidth, - valueHeight, - 1, - 1, - 9, - Math.Clamp(18 * scale, 9, 18), - [StatusTitleTextBlock.FontWeight], - 1.04); - StatusTitleTextBlock.FontSize = statusTitleLayout.FontSize; - StatusTitleTextBlock.FontWeight = statusTitleLayout.Weight; - StatusTitleTextBlock.MaxLines = 1; - StatusTitleTextBlock.TextWrapping = TextWrapping.NoWrap; - StatusTitleTextBlock.LineHeight = statusTitleLayout.LineHeight; - - var statusValueLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - StatusValueTextBlock.Text, - statusValueWidth, - valueHeight, - 1, - 1, - 12, - Math.Clamp(34 * scale, 12, 34), - [StatusValueTextBlock.FontWeight], - 1.04); - StatusValueTextBlock.FontSize = statusValueLayout.FontSize; - StatusValueTextBlock.FontWeight = statusValueLayout.Weight; - StatusValueTextBlock.MaxLines = 1; - StatusValueTextBlock.TextWrapping = TextWrapping.NoWrap; - StatusValueTextBlock.LineHeight = statusValueLayout.LineHeight; - - var noiseValueLines = _showDisplayDb && _showDbfs ? 2 : 1; - var noiseValueLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - NoiseValueTextBlock.Text, - Math.Max(92, availableWidth * 0.48), - Math.Max(22, availableHeight * 0.56), - 1, - noiseValueLines, - 12, - Math.Clamp(38 * scale, 12, 38), - [NoiseValueTextBlock.FontWeight], - 1.06); - NoiseValueTextBlock.FontSize = noiseValueLayout.FontSize; - NoiseValueTextBlock.FontWeight = noiseValueLayout.Weight; - NoiseValueTextBlock.MaxLines = noiseValueLayout.MaxLines; - NoiseValueTextBlock.TextWrapping = noiseValueLayout.MaxLines > 1 ? TextWrapping.Wrap : TextWrapping.NoWrap; - NoiseValueTextBlock.LineHeight = noiseValueLayout.LineHeight; - - var noiseSubValueLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - NoiseSubValueTextBlock.Text, - Math.Max(72, availableWidth * 0.34), - Math.Max(18, availableHeight * 0.24), - 1, - 1, - 9, - Math.Clamp(18 * scale, 9, 18), - [NoiseSubValueTextBlock.FontWeight], - 1.04); - NoiseSubValueTextBlock.FontSize = noiseSubValueLayout.FontSize; - NoiseSubValueTextBlock.FontWeight = noiseSubValueLayout.Weight; - NoiseSubValueTextBlock.MaxLines = 1; - NoiseSubValueTextBlock.TextWrapping = TextWrapping.NoWrap; - NoiseSubValueTextBlock.LineHeight = noiseSubValueLayout.LineHeight; } private string ResolveStatusText(StudyAnalyticsSnapshot snapshot) diff --git a/LanMountainDesktop/Views/Components/StudyInterruptDensityWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudyInterruptDensityWidget.axaml.cs index 6a02b8d..d2f885c 100644 --- a/LanMountainDesktop/Views/Components/StudyInterruptDensityWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudyInterruptDensityWidget.axaml.cs @@ -5,7 +5,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -311,92 +310,6 @@ public partial class StudyInterruptDensityWidget : UserControl, IDesktopComponen ApplyVariableWeights(scale); ApplyLocalizedLabels(); - - var contentWidth = Math.Max(120, (Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 8) - RootBorder.Padding.Left - RootBorder.Padding.Right); - var contentHeight = Math.Max(78, (Bounds.Height > 1 ? Bounds.Height : _currentCellSize * 3) - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TitleTextBlock.Text, - Math.Max(120, contentWidth * 0.38), - Math.Max(18, contentHeight * 0.18), - 1, - 1, - 9, - Math.Clamp(20 * scale, 9, 20), - [TitleTextBlock.FontWeight], - 1.05); - TitleTextBlock.FontSize = titleLayout.FontSize; - TitleTextBlock.FontWeight = titleLayout.Weight; - TitleTextBlock.MaxLines = 1; - TitleTextBlock.TextWrapping = TextWrapping.NoWrap; - TitleTextBlock.LineHeight = titleLayout.LineHeight; - - var modeBadgeBox = ComponentTypographyLayoutService.ResolveBadgeBox( - Math.Max(64, contentWidth * 0.22), - Math.Max(20, contentHeight * 0.14), - preferredSizeScale: 0.46d, - minSize: 18, - maxSize: 42, - insetScale: 0.18d); - ModeBadgeBorder.Padding = modeBadgeBox.Padding; - ModeBadgeBorder.CornerRadius = new CornerRadius(Math.Clamp(modeBadgeBox.Size * 0.36, 4, 12)); - var modeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ModeTextBlock.Text, - Math.Max(52, modeBadgeBox.Width), - Math.Max(18, modeBadgeBox.Height), - 1, - 1, - 8, - Math.Clamp(16 * scale, 8, 16), - [ModeTextBlock.FontWeight], - 1.02); - ModeTextBlock.FontSize = modeLayout.FontSize; - ModeTextBlock.FontWeight = modeLayout.Weight; - ModeTextBlock.MaxLines = 1; - ModeTextBlock.TextWrapping = TextWrapping.NoWrap; - ModeTextBlock.LineHeight = modeLayout.LineHeight; - - foreach (var block in new[] { DensityValueTextBlock, CountValueTextBlock, DurationValueTextBlock }) - { - var minFont = block == DensityValueTextBlock ? 18 : 10; - var maxFont = block == DensityValueTextBlock ? Math.Clamp(94 * scale, 18, 94) : Math.Clamp(36 * scale, 10, 36); - var maxWidth = block == DensityValueTextBlock ? Math.Max(86, contentWidth * 0.24) : Math.Max(64, contentWidth * 0.18); - var maxHeight = block == DensityValueTextBlock ? Math.Max(24, contentHeight * 0.26) : Math.Max(18, contentHeight * 0.18); - var layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - block.Text, - maxWidth, - maxHeight, - 1, - 1, - minFont, - maxFont, - [block.FontWeight], - 1.02); - block.FontSize = layout.FontSize; - block.FontWeight = layout.Weight; - block.MaxLines = 1; - block.TextWrapping = TextWrapping.NoWrap; - block.LineHeight = layout.LineHeight; - } - - foreach (var block in new[] { DensityUnitTextBlock, DensityLevelTextBlock, CountLabelTextBlock, DurationLabelTextBlock, ThresholdTextBlock }) - { - var layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - block.Text, - Math.Max(64, contentWidth * 0.18), - Math.Max(16, contentHeight * 0.14), - 1, - 1, - 8, - Math.Clamp(18 * scale, 8, 18), - [block.FontWeight], - 1.02); - block.FontSize = layout.FontSize; - block.FontWeight = layout.Weight; - block.MaxLines = 1; - block.TextWrapping = TextWrapping.NoWrap; - block.LineHeight = layout.LineHeight; - } } private void ApplyTypographyByBackground(Color panelColor) diff --git a/LanMountainDesktop/Views/Components/StudyNoiseCurveWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudyNoiseCurveWidget.axaml.cs index 53651b3..c6cb04f 100644 --- a/LanMountainDesktop/Views/Components/StudyNoiseCurveWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudyNoiseCurveWidget.axaml.cs @@ -5,7 +5,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -129,50 +128,6 @@ public partial class StudyNoiseCurveWidget : UserControl, IDesktopComponentWidge XLeftTextBlock.FontSize = axisFontSize; XCenterTextBlock.FontSize = axisFontSize; XRightTextBlock.FontSize = axisFontSize; - - var contentWidth = Math.Max(110, (_currentCellSize * 4) - RootBorder.Padding.Left - RootBorder.Padding.Right); - var contentHeight = Math.Max(72, (_currentCellSize * 2) - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - var statusLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - StatusTextBlock.Text, - Math.Max(72, contentWidth * 0.34), - Math.Max(18, contentHeight * 0.18), - 1, - 1, - 12, - Math.Clamp(30 * scale, 12, 30), - [StatusTextBlock.FontWeight], - 1.03); - StatusTextBlock.FontSize = statusLayout.FontSize; - StatusTextBlock.FontWeight = statusLayout.Weight; - StatusTextBlock.MaxLines = 1; - StatusTextBlock.TextWrapping = TextWrapping.NoWrap; - StatusTextBlock.LineHeight = statusLayout.LineHeight; - - var realtimeValueLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - RealtimeValueTextBlock.Text, - Math.Max(82, contentWidth * 0.40), - Math.Max(20, contentHeight * 0.22), - 1, - 1, - 12, - Math.Clamp(34 * scale, 12, 34), - [RealtimeValueTextBlock.FontWeight], - 1.03); - RealtimeValueTextBlock.FontSize = realtimeValueLayout.FontSize; - RealtimeValueTextBlock.FontWeight = realtimeValueLayout.Weight; - RealtimeValueTextBlock.MaxLines = 1; - RealtimeValueTextBlock.TextWrapping = TextWrapping.NoWrap; - RealtimeValueTextBlock.LineHeight = realtimeValueLayout.LineHeight; - - var badgeBox = ComponentTypographyLayoutService.ResolveBadgeBox( - Math.Max(64, contentWidth * 0.20), - Math.Max(20, contentHeight * 0.12), - preferredSizeScale: 0.46d, - minSize: 18, - maxSize: 40, - insetScale: 0.18d); - StatusBadgeBorder.Padding = badgeBox.Padding; - StatusBadgeBorder.CornerRadius = new CornerRadius(Math.Clamp(badgeBox.Size * 0.36, 5, 12)); } public void SetDesktopPageContext(bool isOnActivePage, bool isEditMode) diff --git a/LanMountainDesktop/Views/Components/StudyNoiseDistributionWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudyNoiseDistributionWidget.axaml.cs index eda01ad..fad3dd9 100644 --- a/LanMountainDesktop/Views/Components/StudyNoiseDistributionWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudyNoiseDistributionWidget.axaml.cs @@ -6,7 +6,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -359,85 +358,6 @@ public partial class StudyNoiseDistributionWidget : UserControl, IDesktopCompone SummaryTextBlock.IsVisible = true; ApplyVariableWeights(scale); - - var contentWidth = Math.Max(120, (Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 8) - RootBorder.Padding.Left - RootBorder.Padding.Right); - var contentHeight = Math.Max(78, (Bounds.Height > 1 ? Bounds.Height : _currentCellSize * 3) - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TitleTextBlock.Text, - Math.Max(120, contentWidth * 0.38), - Math.Max(18, contentHeight * 0.18), - 1, - 1, - 9, - Math.Clamp(22 * scale, 9, 22), - [TitleTextBlock.FontWeight], - 1.05); - TitleTextBlock.FontSize = titleLayout.FontSize; - TitleTextBlock.FontWeight = titleLayout.Weight; - TitleTextBlock.MaxLines = 1; - TitleTextBlock.TextWrapping = TextWrapping.NoWrap; - TitleTextBlock.LineHeight = titleLayout.LineHeight; - - var summaryLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - SummaryTextBlock.Text, - Math.Max(104, contentWidth * 0.44), - Math.Max(18, contentHeight * 0.16), - 1, - _isUltraCompactMode ? 1 : 2, - 8, - Math.Clamp(20 * scale, 8, 20), - [SummaryTextBlock.FontWeight], - 1.06); - SummaryTextBlock.FontSize = summaryLayout.FontSize; - SummaryTextBlock.FontWeight = summaryLayout.Weight; - SummaryTextBlock.MaxLines = summaryLayout.MaxLines; - SummaryTextBlock.TextWrapping = summaryLayout.MaxLines > 1 ? TextWrapping.Wrap : TextWrapping.NoWrap; - SummaryTextBlock.LineHeight = summaryLayout.LineHeight; - - var modeBadgeBox = ComponentTypographyLayoutService.ResolveBadgeBox( - Math.Max(64, contentWidth * 0.22), - Math.Max(20, contentHeight * 0.14), - preferredSizeScale: 0.46d, - minSize: 18, - maxSize: 42, - insetScale: 0.18d); - ModeBadgeBorder.Padding = modeBadgeBox.Padding; - ModeBadgeBorder.CornerRadius = new CornerRadius(Math.Clamp(modeBadgeBox.Size * 0.36, 4, 12)); - var modeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ModeTextBlock.Text, - Math.Max(52, modeBadgeBox.Width), - Math.Max(18, modeBadgeBox.Height), - 1, - 1, - 8, - Math.Clamp(18 * scale, 8, 18), - [ModeTextBlock.FontWeight], - 1.02); - ModeTextBlock.FontSize = modeLayout.FontSize; - ModeTextBlock.FontWeight = modeLayout.Weight; - ModeTextBlock.MaxLines = 1; - ModeTextBlock.TextWrapping = TextWrapping.NoWrap; - ModeTextBlock.LineHeight = modeLayout.LineHeight; - - foreach (var block in new[] { YExtremeTextBlock, YNoisyTextBlock, YNormalTextBlock, YQuietTextBlock, XLeftTextBlock, XCenterTextBlock, XRightTextBlock }) - { - var layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - block.Text, - Math.Max(36, contentWidth * 0.12), - Math.Max(14, contentHeight * 0.08), - 1, - 1, - 8, - Math.Clamp(16 * scale, 8, 16), - [block.FontWeight], - 1.02); - block.FontSize = layout.FontSize; - block.FontWeight = layout.Weight; - block.MaxLines = 1; - block.TextWrapping = TextWrapping.NoWrap; - block.LineHeight = layout.LineHeight; - } } private void ApplyTypographyByBackground(Color panelColor) diff --git a/LanMountainDesktop/Views/Components/StudyScoreOverviewWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudyScoreOverviewWidget.axaml.cs index fcbf154..8c894ee 100644 --- a/LanMountainDesktop/Views/Components/StudyScoreOverviewWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudyScoreOverviewWidget.axaml.cs @@ -6,7 +6,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -337,92 +336,6 @@ public partial class StudyScoreOverviewWidget : UserControl, IDesktopComponentWi ApplyVariableWeights(scale); ApplyLocalizedLabels(); - - var contentWidth = Math.Max(140, (Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 8) - RootBorder.Padding.Left - RootBorder.Padding.Right); - var contentHeight = Math.Max(96, (Bounds.Height > 1 ? Bounds.Height : _currentCellSize * 4) - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TitleTextBlock.Text, - Math.Max(120, contentWidth * 0.42), - Math.Max(18, contentHeight * 0.14), - 1, - 1, - 9, - Math.Clamp(30 * scale * labelFactor, 9, 30), - [TitleTextBlock.FontWeight], - 1.05); - TitleTextBlock.FontSize = titleLayout.FontSize; - TitleTextBlock.FontWeight = titleLayout.Weight; - TitleTextBlock.MaxLines = 1; - TitleTextBlock.TextWrapping = TextWrapping.NoWrap; - TitleTextBlock.LineHeight = titleLayout.LineHeight; - - var modeBadgeBox = ComponentTypographyLayoutService.ResolveBadgeBox( - Math.Max(64, contentWidth * 0.22), - Math.Max(20, contentHeight * 0.12), - preferredSizeScale: 0.46d, - minSize: 18, - maxSize: 42, - insetScale: 0.18d); - ModeBadgeBorder.Padding = modeBadgeBox.Padding; - ModeBadgeBorder.CornerRadius = new CornerRadius(Math.Clamp(modeBadgeBox.Size * 0.36, 5, 14)); - var modeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ModeTextBlock.Text, - Math.Max(52, modeBadgeBox.Width), - Math.Max(18, modeBadgeBox.Height), - 1, - 1, - 8, - Math.Clamp(22 * scale * labelFactor, 8, 22), - [ModeTextBlock.FontWeight], - 1.02); - ModeTextBlock.FontSize = modeLayout.FontSize; - ModeTextBlock.FontWeight = modeLayout.Weight; - ModeTextBlock.MaxLines = 1; - ModeTextBlock.TextWrapping = TextWrapping.NoWrap; - ModeTextBlock.LineHeight = modeLayout.LineHeight; - - foreach (var block in new[] { CurrentLabelTextBlock, AverageLabelTextBlock, MinimumLabelTextBlock, MaximumLabelTextBlock }) - { - var layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - block.Text, - Math.Max(64, contentWidth * 0.16), - Math.Max(14, contentHeight * 0.10), - 1, - 1, - 8, - Math.Clamp(22 * scale * labelFactor, 8, 22), - [block.FontWeight], - 1.02); - block.FontSize = layout.FontSize; - block.FontWeight = layout.Weight; - block.MaxLines = 1; - block.TextWrapping = TextWrapping.NoWrap; - block.LineHeight = layout.LineHeight; - } - - foreach (var block in new[] { CurrentScoreTextBlock, AverageValueTextBlock, MinimumValueTextBlock, MaximumValueTextBlock }) - { - var minFont = block == CurrentScoreTextBlock ? 22 : 11; - var maxFont = block == CurrentScoreTextBlock ? Math.Clamp(190 * scale * headlineFactor, 22, 190) : Math.Clamp(64 * scale * statFactor, 11, 64); - var maxWidth = block == CurrentScoreTextBlock ? Math.Max(96, contentWidth * 0.30) : Math.Max(72, contentWidth * 0.18); - var maxHeight = block == CurrentScoreTextBlock ? Math.Max(30, contentHeight * 0.24) : Math.Max(20, contentHeight * 0.14); - var layout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - block.Text, - maxWidth, - maxHeight, - 1, - 1, - minFont, - maxFont, - [block.FontWeight], - 1.02); - block.FontSize = layout.FontSize; - block.FontWeight = layout.Weight; - block.MaxLines = 1; - block.TextWrapping = TextWrapping.NoWrap; - block.LineHeight = layout.LineHeight; - } } private void PushRealtimeScore(double score, DateTimeOffset now) diff --git a/LanMountainDesktop/Views/Components/StudySessionControlWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudySessionControlWidget.axaml.cs index c479103..af204dd 100644 --- a/LanMountainDesktop/Views/Components/StudySessionControlWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudySessionControlWidget.axaml.cs @@ -4,7 +4,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Media; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -294,40 +293,6 @@ public partial class StudySessionControlWidget : UserControl, IDesktopComponentW ActionIcon.Height = Math.Clamp(buttonSize * 0.44, 14, 30); SecondaryTextBlock.IsVisible = !_isUltraCompactMode; - - var contentWidth = Math.Max(96, (Bounds.Width > 1 ? Bounds.Width : _currentCellSize * 4) - RootBorder.Padding.Left - RootBorder.Padding.Right); - var contentHeight = Math.Max(44, (Bounds.Height > 1 ? Bounds.Height : _currentCellSize * 2) - RootBorder.Padding.Top - RootBorder.Padding.Bottom); - var primaryLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - PrimaryTextBlock.Text, - Math.Max(72, contentWidth * 0.58), - Math.Max(18, contentHeight * 0.28), - 1, - 1, - 10, - Math.Clamp(30 * scale, 10, 30), - [PrimaryTextBlock.FontWeight], - 1.04); - PrimaryTextBlock.FontSize = primaryLayout.FontSize; - PrimaryTextBlock.FontWeight = primaryLayout.Weight; - PrimaryTextBlock.MaxLines = 1; - PrimaryTextBlock.TextWrapping = TextWrapping.NoWrap; - PrimaryTextBlock.LineHeight = primaryLayout.LineHeight; - - var secondaryLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - SecondaryTextBlock.Text, - Math.Max(64, contentWidth * 0.58), - Math.Max(16, contentHeight * 0.22), - 1, - _isUltraCompactMode ? 1 : 2, - 8, - Math.Clamp(18 * scale, 8, 18), - [SecondaryTextBlock.FontWeight], - 1.04); - SecondaryTextBlock.FontSize = secondaryLayout.FontSize; - SecondaryTextBlock.FontWeight = secondaryLayout.Weight; - SecondaryTextBlock.MaxLines = secondaryLayout.MaxLines; - SecondaryTextBlock.TextWrapping = secondaryLayout.MaxLines > 1 ? TextWrapping.Wrap : TextWrapping.NoWrap; - SecondaryTextBlock.LineHeight = secondaryLayout.LineHeight; } private void ApplyTypographyByBackground(Color panelColor) diff --git a/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml.cs b/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml.cs index 1e94826..b94dc72 100644 --- a/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/StudySessionHistoryWidget.axaml.cs @@ -9,7 +9,6 @@ using Avalonia.Media; using Avalonia.Threading; using FluentIcons.Avalonia; using FluentIcons.Common; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.Models; using LanMountainDesktop.Services; using LanMountainDesktop.Theme; @@ -196,7 +195,6 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW StatusTextBlock.Text = _transientStatus ?? L("study.session_history.empty", "No session history"); StatusTextBlock.Foreground = CreateAdaptiveBrush(panelSamples, SecondaryColorCandidates, MinTextContrast); - ApplyHistoryTypographyLayout(); UpdateDialogVisual(snapshot, panelColor); return; } @@ -221,7 +219,6 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW StatusTextBlock.Text = _transientStatus ?? string.Empty; StatusTextBlock.Foreground = CreateAdaptiveBrush(panelSamples, SecondaryColorCandidates, MinTextContrast); - ApplyHistoryTypographyLayout(); UpdateDialogVisual(snapshot, panelColor); } @@ -264,25 +261,15 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW { Spacing = _isUltraCompactMode ? 0 : 2 }; - var rowTitleTextBlock = new TextBlock + textStack.Children.Add(new TextBlock { Text = entry.Label, + FontSize = Math.Clamp(12 * (_isCompactMode ? 0.92 : 1.0), 10, 17), + FontWeight = FontWeight.SemiBold, + MaxLines = 1, + TextTrimming = TextTrimming.CharacterEllipsis, Foreground = rowPrimaryBrush - }; - ApplyTextLayout( - rowTitleTextBlock, - ComponentTypographyLayoutService.FitAdaptiveTextLayout( - entry.Label, - ResolveHistoryContentWidth(), - _isUltraCompactMode ? 18 : 22, - 1, - 1, - 10, - 17, - new[] { FontWeight.SemiBold, FontWeight.Medium }, - 1.08d), - TextWrapping.NoWrap); - textStack.Children.Add(rowTitleTextBlock); + }); if (!_isUltraCompactMode) { @@ -294,25 +281,14 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW FormatDuration(entry.Duration), entry.AverageScore); - var metaTextBlock = new TextBlock + textStack.Children.Add(new TextBlock { Text = metaText, + FontSize = Math.Clamp(10.5 * (_isCompactMode ? 0.94 : 1.0), 9, 14), + MaxLines = 1, + TextTrimming = TextTrimming.CharacterEllipsis, Foreground = rowSecondaryBrush - }; - ApplyTextLayout( - metaTextBlock, - ComponentTypographyLayoutService.FitAdaptiveTextLayout( - metaText, - ResolveHistoryContentWidth(), - _isUltraCompactMode ? 16 : 20, - 1, - 1, - 9, - 14, - new[] { FontWeight.Normal, FontWeight.Medium }, - 1.08d), - TextWrapping.NoWrap); - textStack.Children.Add(metaTextBlock); + }); } rowGrid.Children.Add(textStack); @@ -590,8 +566,6 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW DialogConfirmButton.Content = L("study.session_history.dialog.delete_confirm", "Delete"); DialogCancelButton.Content = L("study.session_history.rename_cancel", "Cancel rename"); } - - ApplyHistoryTypographyLayout(); } private void SetTransientStatus(string status, double seconds = 2.2) @@ -625,6 +599,8 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW ? Math.Clamp(4 * scale, 2, 6) : Math.Clamp(7 * scale, 4, 10); + TitleTextBlock.FontSize = Math.Clamp(13 * scale, 10, 22); + StatusTextBlock.FontSize = Math.Clamp(11 * scale, 9, 18); SessionListPanel.Spacing = _isUltraCompactMode ? Math.Clamp(4 * scale, 2, 5) : Math.Clamp(6 * scale, 3, 8); @@ -636,108 +612,13 @@ public partial class StudySessionHistoryWidget : UserControl, IDesktopComponentW DialogCardBorder.Padding = new Thickness( ComponentChromeCornerRadiusHelper.SafeValue(12 * scale, 9, 20), ComponentChromeCornerRadiusHelper.SafeValue(11 * scale, 8, 18)); + DialogTitleTextBlock.FontSize = Math.Clamp(14 * scale, 11, 20); + DialogMessageTextBlock.FontSize = Math.Clamp(12 * scale, 10, 17); + DialogRenameTextBox.FontSize = Math.Clamp(11.5 * scale, 10, 16); DialogCancelButton.FontSize = Math.Clamp(11 * scale, 10, 16); DialogConfirmButton.FontSize = Math.Clamp(11 * scale, 10, 16); DialogCancelButton.Height = Math.Clamp(30 * scale, 26, 38); DialogConfirmButton.Height = Math.Clamp(30 * scale, 26, 38); - - ApplyHistoryTypographyLayout(); - } - - private void ApplyHistoryTypographyLayout() - { - var contentWidth = ResolveHistoryContentWidth(); - - var titleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TitleTextBlock.Text, - contentWidth, - _isUltraCompactMode ? 18 : 24, - 1, - 1, - 10, - 22, - new[] { FontWeight.SemiBold, FontWeight.Medium }, - 1.08d); - ApplyTextLayout(TitleTextBlock, titleLayout, TextWrapping.NoWrap); - - var statusLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - StatusTextBlock.Text, - contentWidth, - _isUltraCompactMode ? 18 : 28, - 1, - _isUltraCompactMode ? 1 : 2, - 9, - 18, - new[] { FontWeight.Normal, FontWeight.Medium }, - 1.10d); - ApplyTextLayout(StatusTextBlock, statusLayout, statusLayout.MaxLines > 1 ? TextWrapping.Wrap : TextWrapping.NoWrap); - - if (!DialogOverlayBorder.IsVisible) - { - return; - } - - var dialogWidth = DialogCardBorder.Bounds.Width > 1 - ? Math.Max(1, DialogCardBorder.Bounds.Width - DialogCardBorder.Padding.Left - DialogCardBorder.Padding.Right) - : Math.Max(180, contentWidth); - - var dialogTitleLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - DialogTitleTextBlock.Text, - dialogWidth, - _isUltraCompactMode ? 18 : 24, - 1, - 1, - 11, - 20, - new[] { FontWeight.SemiBold, FontWeight.Medium }, - 1.08d); - ApplyTextLayout(DialogTitleTextBlock, dialogTitleLayout, TextWrapping.NoWrap); - - var dialogMessageLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - DialogMessageTextBlock.Text, - dialogWidth, - _isUltraCompactMode ? 42 : 56, - 1, - 3, - 10, - 17, - new[] { FontWeight.Normal, FontWeight.Medium }, - 1.12d); - ApplyTextLayout(DialogMessageTextBlock, dialogMessageLayout, dialogMessageLayout.MaxLines > 1 ? TextWrapping.Wrap : TextWrapping.NoWrap); - - var renameLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - DialogRenameTextBox.Text ?? DialogRenameTextBox.Watermark, - dialogWidth, - _isUltraCompactMode ? 30 : 36, - 1, - 1, - 10, - 16, - new[] { FontWeight.Normal }, - 1.08d); - DialogRenameTextBox.FontSize = renameLayout.FontSize; - DialogRenameTextBox.FontWeight = renameLayout.Weight; - } - - private double ResolveHistoryContentWidth() - { - if (Bounds.Width <= 1) - { - return Math.Max(90, _currentCellSize * 4.5); - } - - var reservedWidth = _isUltraCompactMode ? 126 : 150; - return Math.Max(90, Bounds.Width - reservedWidth); - } - - private static void ApplyTextLayout(TextBlock textBlock, ComponentAdaptiveTextLayout layout, TextWrapping wrapping) - { - textBlock.FontSize = layout.FontSize; - textBlock.FontWeight = layout.Weight; - textBlock.LineHeight = layout.LineHeight; - textBlock.MaxLines = layout.MaxLines; - textBlock.TextWrapping = wrapping; - textBlock.TextTrimming = TextTrimming.CharacterEllipsis; } private static StudySessionHistoryEntry? FindHistoryEntry(IReadOnlyList history, string? sessionId) diff --git a/LanMountainDesktop/Views/Components/TimerWidget.axaml.cs b/LanMountainDesktop/Views/Components/TimerWidget.axaml.cs index fd3d5f6..73823f1 100644 --- a/LanMountainDesktop/Views/Components/TimerWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/TimerWidget.axaml.cs @@ -7,7 +7,6 @@ using Avalonia.Input; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; namespace LanMountainDesktop.Views.Components; @@ -123,7 +122,6 @@ public partial class TimerWidget : UserControl, IDesktopComponentWidget MainNumberTextBlock.Text = current.ToString(CultureInfo.InvariantCulture); NextNumberTextBlock.Text = next.ToString(CultureInfo.InvariantCulture); NextNextNumberTextBlock.Text = nextNext.ToString(CultureInfo.InvariantCulture); - UpdateTypography(); } private void UpdateHandGeometry() @@ -208,7 +206,6 @@ public partial class TimerWidget : UserControl, IDesktopComponentWidget PlayButtonBorder.Height = Math.Clamp(42 * scale, 28, 58); PlayButtonBorder.CornerRadius = new CornerRadius(PlayButtonBorder.Width / 2d); - UpdateTypography(); ApplyModeVisualIfNeeded(); } @@ -220,51 +217,6 @@ public partial class TimerWidget : UserControl, IDesktopComponentWidget return Math.Clamp(Math.Min(cellScale, Math.Min(heightScale, widthScale) * 1.05), 0.58, 1.95); } - private void UpdateTypography() - { - var panelWidth = TimerPanelBorder.Bounds.Width > 1 ? TimerPanelBorder.Bounds.Width : 224d; - var panelHeight = TimerPanelBorder.Bounds.Height > 1 ? TimerPanelBorder.Bounds.Height : 224d; - var leftColumnWidth = Math.Max(72, panelWidth * 0.38); - var leftColumnHeight = Math.Max(120, panelHeight - 36); - - TopNumberTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - TopNumberTextBlock.Text, - leftColumnWidth, - Math.Max(20, leftColumnHeight * 0.20), - 1, - 18, - 38, - FontWeight.SemiBold, - 1.02d); - MainNumberTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - MainNumberTextBlock.Text, - leftColumnWidth, - Math.Max(28, leftColumnHeight * 0.30), - 1, - 28, - 64, - FontWeight.Bold, - 1.00d); - NextNumberTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - NextNumberTextBlock.Text, - leftColumnWidth, - Math.Max(18, leftColumnHeight * 0.16), - 1, - 14, - 34, - FontWeight.Medium, - 1.02d); - NextNextNumberTextBlock.FontSize = ComponentTypographyLayoutService.FitFontSize( - NextNextNumberTextBlock.Text, - leftColumnWidth, - Math.Max(16, leftColumnHeight * 0.12), - 1, - 12, - 26, - FontWeight.Medium, - 1.02d); - } - private bool ResolveIsNightMode() { if (ActualThemeVariant == ThemeVariant.Dark) diff --git a/LanMountainDesktop/Views/Components/WeatherClockWidget.axaml.cs b/LanMountainDesktop/Views/Components/WeatherClockWidget.axaml.cs index 5cbfdb1..8946da4 100644 --- a/LanMountainDesktop/Views/Components/WeatherClockWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/WeatherClockWidget.axaml.cs @@ -10,7 +10,6 @@ using Avalonia.Controls.Shapes; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Host.Abstractions; using LanMountainDesktop.Models; @@ -219,36 +218,14 @@ public partial class WeatherClockWidget : UserControl, IDesktopComponentWidget, } var leftWidthFactor = Math.Clamp(leftContentWidth / 122d, 0.48, 1.35); - var timeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TimeTextBlock.Text, - leftContentWidth, - Math.Max(12, contentHeight * 0.42), - 1, - 1, - 10, - Math.Clamp((metrics.PrimaryTemperatureFont * 0.74) * scale * compactFactor * leftWidthFactor, 10, 62), - [ToVariableWeight(Lerp(620, 760, Math.Clamp((scale - 0.68) / 1.35, 0, 1)))], - 1.04); - var dateLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - DateTextBlock.Text, - Math.Max(12, leftContentWidth), - Math.Max(10, contentHeight * 0.24), - 1, - 1, - 8, - Math.Clamp(metrics.SecondaryTextFont * scale * compactFactor * leftWidthFactor, 8, 30), - [ToVariableWeight(Lerp(540, 680, Math.Clamp((scale - 0.68) / 1.35, 0, 1)))], - 1.04); - TimeTextBlock.FontSize = timeLayout.FontSize; - DateTextBlock.FontSize = dateLayout.FontSize; + TimeTextBlock.FontSize = Math.Clamp((metrics.PrimaryTemperatureFont * 0.74) * scale * compactFactor * leftWidthFactor, 10, 62); + DateTextBlock.FontSize = Math.Clamp(metrics.SecondaryTextFont * scale * compactFactor * leftWidthFactor, 8, 30); var weatherIconSize = Math.Clamp(metrics.IconFont * scale * compactFactor * leftWidthFactor, 9, 32); WeatherIconImage.Width = weatherIconSize; WeatherIconImage.Height = weatherIconSize; - TimeTextBlock.FontWeight = timeLayout.Weight; - DateTextBlock.FontWeight = dateLayout.Weight; - TimeTextBlock.LineHeight = timeLayout.LineHeight; - DateTextBlock.LineHeight = dateLayout.LineHeight; + TimeTextBlock.FontWeight = ToVariableWeight(Lerp(620, 760, Math.Clamp((scale - 0.68) / 1.35, 0, 1))); + DateTextBlock.FontWeight = ToVariableWeight(Lerp(540, 680, Math.Clamp((scale - 0.68) / 1.35, 0, 1))); LeftStack.Width = leftContentWidth; LeftStack.MaxWidth = leftContentWidth; diff --git a/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs b/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs index a9af013..156d497 100644 --- a/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/WeatherWidget.axaml.cs @@ -11,7 +11,6 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Platform; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Host.Abstractions; using LanMountainDesktop.Models; @@ -926,21 +925,12 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, IDesk var temperatureSample = string.IsNullOrWhiteSpace(TemperatureTextBlock.Text) ? "00°" : TemperatureTextBlock.Text.Trim(); - var temperatureGlyphCount = Math.Clamp(ComponentTypographyLayoutService.CountTextDisplayUnits(temperatureSample), 3, 6); + var temperatureGlyphCount = Math.Clamp(temperatureSample.Length, 3, 6); var temperatureMaxWidth = Math.Max(34, innerWidth - iconSize - TopRowGrid.ColumnSpacing - 2); var rawTemperatureSize = Math.Clamp(Lerp(94, 118, iconGrowth) * topScale, 22, 340); - var temperatureLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - TemperatureTextBlock.Text, - temperatureMaxWidth, - Math.Max(18, topZoneHeight * 0.84), - 1, - 1, - Math.Max(10, rawTemperatureSize * 0.42), - rawTemperatureSize, - [ToVariableWeight(Lerp(300, 360, emphasis))], - 1.02); - TemperatureTextBlock.FontSize = temperatureLayout.FontSize; - TemperatureTextBlock.FontWeight = temperatureLayout.Weight; + var fitTemperatureSize = temperatureMaxWidth / (temperatureGlyphCount * 0.62); + TemperatureTextBlock.FontSize = Math.Clamp(Math.Min(rawTemperatureSize, fitTemperatureSize), 10, 340); + TemperatureTextBlock.FontWeight = ToVariableWeight(Lerp(300, 360, emphasis)); TemperatureTextBlock.Margin = new Thickness(Math.Clamp(-1.4 * topScale, -6, 0), Math.Clamp(-7.6 * topScale, -16, -1), 0, 0); TemperatureTextBlock.MaxWidth = Math.Clamp(temperatureMaxWidth, 34, Math.Max(34, innerWidth * 0.76)); @@ -971,76 +961,26 @@ public partial class WeatherWidget : UserControl, IDesktopComponentWidget, IDesk } var infoFontWeight = ToVariableWeight(Lerp(580, 690, emphasis)); - var conditionBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - bottomTextMaxWidth, - Math.Max(16, bottomZoneHeight * 0.34), - preferredSizeScale: 0.26d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - ConditionStack.Margin = new Thickness( - conditionBadge.Padding.Left, - conditionBadge.Padding.Top, - conditionBadge.Padding.Right, - conditionBadge.Padding.Bottom); - var conditionContentMaxWidth = Math.Max(24, bottomTextMaxWidth - conditionBadge.Padding.Left - conditionBadge.Padding.Right); - var conditionLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - ConditionTextBlock.Text, - conditionContentMaxWidth, - Math.Max(12, bottomZoneHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, infoFontSize * 0.96), - [infoFontWeight], - infoLineHeightFactor); - var rangeLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - RangeTextBlock.Text, - conditionContentMaxWidth, - Math.Max(12, bottomZoneHeight * 0.30), - 1, - 1, - 7, - Math.Max(6, infoFontSize * 1.03), - [infoFontWeight], - infoLineHeightFactor); - ConditionTextBlock.FontSize = conditionLayout.FontSize; - ConditionTextBlock.FontWeight = conditionLayout.Weight; - ConditionTextBlock.LineHeight = conditionLayout.LineHeight; + ConditionTextBlock.FontSize = Math.Max(6, infoFontSize * 0.96); + ConditionTextBlock.FontWeight = infoFontWeight; + ConditionTextBlock.LineHeight = ConditionTextBlock.FontSize * infoLineHeightFactor; ConditionTextBlock.MaxWidth = bottomTextMaxWidth; - RangeTextBlock.FontSize = rangeLayout.FontSize; - RangeTextBlock.FontWeight = rangeLayout.Weight; - RangeTextBlock.LineHeight = rangeLayout.LineHeight; + RangeTextBlock.FontSize = Math.Max(6, infoFontSize * 1.03); + RangeTextBlock.FontWeight = infoFontWeight; + RangeTextBlock.LineHeight = RangeTextBlock.FontSize * infoLineHeightFactor; RangeTextBlock.MaxWidth = bottomTextMaxWidth; - var cityBadge = ComponentTypographyLayoutService.ResolveBadgeBox( - bottomTextMaxWidth, - Math.Max(16, bottomZoneHeight * 0.38), - preferredSizeScale: 0.28d, - minSize: 10, - maxSize: 24, - insetScale: 0.18d); - CityInfoBadge.Padding = cityBadge.Padding; - CityInfoBadge.CornerRadius = new CornerRadius(cityBadge.Size / 2d); + CityInfoBadge.Padding = new Thickness(0); + CityInfoBadge.CornerRadius = new CornerRadius(0); CityInfoBadge.MaxWidth = bottomTextMaxWidth; LocationIcon.FontSize = Math.Clamp( 12 * bottomScale, 6, 34); LocationIcon.FontSize = Math.Min(LocationIcon.FontSize, infoFontSize * 0.72); - var cityLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - CityTextBlock.Text, - Math.Max(24, bottomTextMaxWidth - cityBadge.Padding.Left - cityBadge.Padding.Right), - Math.Max(12, bottomZoneHeight * 0.36), - 1, - 1, - 6, - Math.Max(6, infoFontSize * 0.84), - [ToVariableWeight(Lerp(500, 620, emphasis))], - infoLineHeightFactor); - CityTextBlock.FontSize = cityLayout.FontSize; - CityTextBlock.FontWeight = cityLayout.Weight; - CityTextBlock.LineHeight = cityLayout.LineHeight; + CityTextBlock.FontSize = Math.Max(6, infoFontSize * 0.84); + CityTextBlock.FontWeight = ToVariableWeight(Lerp(500, 620, emphasis)); + CityTextBlock.LineHeight = CityTextBlock.FontSize * infoLineHeightFactor; CityTextBlock.MaxWidth = bottomTextMaxWidth; } diff --git a/LanMountainDesktop/Views/Components/WorldClockWidget.axaml.cs b/LanMountainDesktop/Views/Components/WorldClockWidget.axaml.cs index 4a6f186..f4d8c33 100644 --- a/LanMountainDesktop/Views/Components/WorldClockWidget.axaml.cs +++ b/LanMountainDesktop/Views/Components/WorldClockWidget.axaml.cs @@ -8,7 +8,6 @@ using Avalonia.Layout; using Avalonia.Media; using Avalonia.Styling; using Avalonia.Threading; -using LanMountainDesktop.DesktopComponents.Runtime; using LanMountainDesktop.ComponentSystem; using LanMountainDesktop.Services; @@ -102,7 +101,6 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT private TimeZoneService? _timeZoneService; private string _languageCode = "zh-CN"; private double _currentCellSize = BaseCellSize; - private double _layoutScale = 1d; private DateTime _nextLanguageProbeUtc = DateTime.MinValue; private string _secondHandMode = ClockSecondHandMode.Tick; private bool _isNightVisual = true; @@ -165,16 +163,14 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT { _currentCellSize = Math.Max(1, cellSize); var scale = ResolveScale(); - var chromeScale = ComponentChromeCornerRadiusHelper.ResolveScale(); - _layoutScale = Math.Clamp(scale * (0.9d + (chromeScale * 0.1d)), 0.58d, 2.0d); var totalWidth = Bounds.Width > 1 ? Bounds.Width : _currentCellSize * BaseWidthCells; var totalHeight = Bounds.Height > 1 ? Bounds.Height : _currentCellSize * BaseHeightCells; - var horizontalPadding = Math.Clamp(10 * _layoutScale, 4, 26); - var verticalPadding = Math.Clamp(8 * _layoutScale, 3, 22); + var horizontalPadding = Math.Clamp(10 * scale, 4, 26); + var verticalPadding = Math.Clamp(8 * scale, 3, 22); RootBorder.Padding = ComponentChromeCornerRadiusHelper.SafeThickness(horizontalPadding, verticalPadding, null, 0.55d); - RootBorder.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(24 * _layoutScale, 10, 46); + RootBorder.CornerRadius = ComponentChromeCornerRadiusHelper.Scale(24 * scale, 10, 46); var usableWidth = Math.Max(48, totalWidth - horizontalPadding * 2); var usableHeight = Math.Max(28, totalHeight - verticalPadding * 2); @@ -183,8 +179,11 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT ClockHostGrid.ColumnSpacing = columnSpacing; var widthPerClock = Math.Max(18, (usableWidth - columnSpacing * 3) / WorldClockTimeZoneCatalog.ClockCount); - var textSpacing = Math.Clamp(2.8 * _layoutScale, 1, 7); - var estimatedTextHeight = Math.Clamp(78 * _layoutScale, 42, 128); + var secondaryFont = Math.Clamp(10.5 * scale * (widthPerClock / 46d), 7, 18); + var cityFont = Math.Clamp(secondaryFont * 1.42, 9, 24); + var textSpacing = Math.Clamp(2.8 * scale, 1, 7); + + var estimatedTextHeight = cityFont * 1.2 + secondaryFont * 2.35 + textSpacing * 3; var dialSize = Math.Clamp(Math.Min(widthPerClock, usableHeight - estimatedTextHeight), 18, 108); if (dialSize < 18) { @@ -198,13 +197,15 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT entry.DialBorder.Height = dialSize; entry.DialBorder.CornerRadius = new CornerRadius(dialSize / 2d); + entry.CityTextBlock.FontSize = cityFont; + entry.DayTextBlock.FontSize = secondaryFont; + entry.OffsetTextBlock.FontSize = secondaryFont; + var maxTextWidth = Math.Max(16, widthPerClock + 10); entry.CityTextBlock.MaxWidth = maxTextWidth; entry.DayTextBlock.MaxWidth = maxTextWidth; entry.OffsetTextBlock.MaxWidth = maxTextWidth; } - - RefreshDialArtwork(_isNightVisual); } private void OnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e) @@ -475,7 +476,6 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT private static void BuildDialTicks(ClockEntryVisual entry, bool isNight) { entry.TickCanvas.Children.Clear(); - var scale = Math.Clamp(entry.Host.Spacing / 3d, 0.78d, 1.22d); var majorColor = isNight ? "#E3E7F2" : "#2D3341"; var minorColor = isNight ? "#9EA7B8" : "#9AA4B3"; @@ -483,8 +483,8 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT { var isMajor = i % 5 == 0; var angle = (i * 6 - 90) * Math.PI / 180d; - var outerRadius = DialCenter - (6.5 * scale); - var innerRadius = outerRadius - (isMajor ? 9 * scale : 4.5 * scale); + var outerRadius = DialCenter - 6.5; + var innerRadius = outerRadius - (isMajor ? 9 : 4.5); var x1 = DialCenter + Math.Cos(angle) * innerRadius; var y1 = DialCenter + Math.Sin(angle) * innerRadius; @@ -496,7 +496,7 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT StartPoint = new Point(x1, y1), EndPoint = new Point(x2, y2), Stroke = CreateBrush(isMajor ? majorColor : minorColor), - StrokeThickness = (isMajor ? 1.9 : 0.8) * scale, + StrokeThickness = isMajor ? 1.9 : 0.8, StrokeLineCap = PenLineCap.Round }); } @@ -505,9 +505,8 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT private static void BuildDialNumbers(ClockEntryVisual entry, bool isNight) { entry.NumberCanvas.Children.Clear(); - var scale = Math.Clamp(entry.Host.Spacing / 3d, 0.78d, 1.22d); var numberColor = isNight ? "#F2F5FB" : "#1B202A"; - var radius = 36 * scale; + var radius = 36; for (var number = 1; number <= 12; number++) { var angle = (number * 30 - 90) * Math.PI / 180d; @@ -515,37 +514,22 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT var y = DialCenter + Math.Sin(angle) * radius; var text = number.ToString(CultureInfo.InvariantCulture); var isDoubleDigit = number >= 10; - var glyphBox = ComponentTypographyLayoutService.ResolveGlyphBox( - isDoubleDigit ? 16 * scale : 12 * scale, - 12 * scale, - preferredSizeScale: 0.98d, - minSize: 8, - maxSize: 16, - insetScale: 0d); - var fontSize = ComponentTypographyLayoutService.FitFontSize( - text, - glyphBox.Width, - glyphBox.Height, - maxLines: 1, - minFontSize: 7 * scale, - maxFontSize: 11 * scale, - weight: FontWeight.SemiBold, - lineHeightFactor: 1d, - fontFamily: MiSansFontFamily); + var width = isDoubleDigit ? 14 : 10; + var height = 12; var numberText = new TextBlock { Text = text, - Width = glyphBox.Width, - Height = glyphBox.Height, + Width = width, + Height = height, FontFamily = MiSansFontFamily, - FontSize = fontSize, + FontSize = 9, FontWeight = FontWeight.SemiBold, Foreground = CreateBrush(numberColor), TextAlignment = TextAlignment.Center }; - Canvas.SetLeft(numberText, x - glyphBox.Width / 2d); - Canvas.SetTop(numberText, y - glyphBox.Height / 2d); + Canvas.SetLeft(numberText, x - width / 2d); + Canvas.SetTop(numberText, y - height / 2d); entry.NumberCanvas.Children.Add(numberText); } } @@ -600,69 +584,18 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT var minuteAngle = minuteValue * 6d; var secondAngle = secondValue * 6d; - SetHandGeometry(entry.HourHand, hourAngle, forwardLength: 24 * _layoutScale, backwardLength: 4.8 * _layoutScale); - SetHandGeometry(entry.MinuteHand, minuteAngle, forwardLength: 33 * _layoutScale, backwardLength: 6 * _layoutScale); - SetHandGeometry(entry.SecondHand, secondAngle, forwardLength: 37 * _layoutScale, backwardLength: 8.5 * _layoutScale); + SetHandGeometry(entry.HourHand, hourAngle, forwardLength: 24, backwardLength: 4.8); + SetHandGeometry(entry.MinuteHand, minuteAngle, forwardLength: 33, backwardLength: 6); + SetHandGeometry(entry.SecondHand, secondAngle, forwardLength: 37, backwardLength: 8.5); entry.CityTextBlock.Text = ResolveCityName(zone); entry.DayTextBlock.Text = ResolveRelativeDayLabel((zonedNow.Date - baseNow.Date).Days); var offsetDelta = zone.GetUtcOffset(utcNow) - baseOffset; entry.OffsetTextBlock.Text = ResolveOffsetLabel(offsetDelta); - ApplyEntryTypography(entry); } } - private void ApplyEntryTypography(ClockEntryVisual entry) - { - var hostWidth = entry.Host.Bounds.Width > 1 ? entry.Host.Bounds.Width : Math.Max(18, _currentCellSize * 0.74); - var hostHeight = entry.Host.Bounds.Height > 1 ? entry.Host.Bounds.Height : Math.Max(18, _currentCellSize * 1.7); - var textWidth = Math.Max(16, hostWidth); - var cityHeight = Math.Clamp(hostHeight * 0.18, 12, 28); - var secondaryHeight = Math.Clamp(hostHeight * 0.14, 10, 22); - - var cityLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - entry.CityTextBlock.Text, - textWidth, - cityHeight, - minLines: 1, - maxLines: 1, - minFontSize: 9, - maxFontSize: 24, - weightCandidates: new[] { FontWeight.SemiBold, FontWeight.Medium }, - lineHeightFactor: 1d, - fontFamily: MiSansFontFamily); - var dayLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - entry.DayTextBlock.Text, - textWidth, - secondaryHeight, - minLines: 1, - maxLines: 1, - minFontSize: 8, - maxFontSize: 18, - weightCandidates: new[] { FontWeight.Medium, FontWeight.Normal }, - lineHeightFactor: 1d, - fontFamily: MiSansFontFamily); - var offsetLayout = ComponentTypographyLayoutService.FitAdaptiveTextLayout( - entry.OffsetTextBlock.Text, - textWidth, - secondaryHeight, - minLines: 1, - maxLines: 1, - minFontSize: 8, - maxFontSize: 18, - weightCandidates: new[] { FontWeight.Medium, FontWeight.Normal }, - lineHeightFactor: 1d, - fontFamily: MiSansFontFamily); - - entry.CityTextBlock.FontSize = cityLayout.FontSize; - entry.CityTextBlock.FontWeight = cityLayout.Weight; - entry.DayTextBlock.FontSize = dayLayout.FontSize; - entry.DayTextBlock.FontWeight = dayLayout.Weight; - entry.OffsetTextBlock.FontSize = offsetLayout.FontSize; - entry.OffsetTextBlock.FontWeight = offsetLayout.Weight; - } - private static void ApplyDialTheme(ClockEntryVisual entry, bool isNight) { if (entry.IsNightApplied.HasValue && entry.IsNightApplied.Value == isNight) @@ -682,21 +615,6 @@ public partial class WorldClockWidget : UserControl, IDesktopComponentWidget, IT BuildDialNumbers(entry, isNight); } - private void RefreshDialArtwork(bool isNight) - { - for (var index = 0; index < _entryVisuals.Length; index++) - { - var entry = _entryVisuals[index]; - if (entry is null) - { - continue; - } - - BuildDialTicks(entry, isNight); - BuildDialNumbers(entry, isNight); - } - } - private void ProbeLanguageCodeIfNeeded(DateTime utcNow) { if (utcNow < _nextLanguageProbeUtc)