From e1bebefe06410450cdfb9a8c65411cbbff0b077c Mon Sep 17 00:00:00 2001 From: waynebian01 Date: Sat, 22 Aug 2026 15:08:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=97=E5=AE=BD=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF=E6=8C=81=E5=9C=A8?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=20UI=20=E6=8E=A7=E4=BB=B6=E4=B8=AD=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E5=92=8C=E6=81=A2=E5=A4=8D=E5=88=97=E5=AE=BD=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Infrastructure/UiCacheStore.cs | 44 +++++++ UI/ClassConfigEditorControl.cs | 13 +- UI/ClassMacrosEditorControl.cs | 12 +- UI/MainForm.cs | 1 + UI/ModuleEditorControl.cs | 103 ++------------- UI/StatusForm.cs | 12 +- UI/UiTheme.cs | 225 ++++++++++++++++++++++++++++----- 7 files changed, 266 insertions(+), 144 deletions(-) diff --git a/Infrastructure/UiCacheStore.cs b/Infrastructure/UiCacheStore.cs index 2610a79e..5e3aa744 100644 --- a/Infrastructure/UiCacheStore.cs +++ b/Infrastructure/UiCacheStore.cs @@ -52,6 +52,49 @@ internal static class UiCacheStore return Screen.AllScreens.Any(screen => screen.WorkingArea.IntersectsWith(bounds)); } + + public static Dictionary? LoadColumnWidths(string cacheKey) + { + var state = Load(); + if (state.ColumnWidths?.TryGetValue(cacheKey, out var widths) == true) + { + return new Dictionary(widths, StringComparer.Ordinal); + } + + // 兼容旧版本只保存模块逻辑编辑列宽的字段。 + if (string.Equals(cacheKey, "module-rules", StringComparison.Ordinal) + && state.ModuleRulesGridColumns is { Count: > 0 } legacyWidths) + { + return new Dictionary(legacyWidths, StringComparer.Ordinal); + } + + return null; + } + + public static void SaveColumnWidth(string cacheKey, string columnKey, int width) + { + if (string.IsNullOrWhiteSpace(cacheKey) || string.IsNullOrWhiteSpace(columnKey) || width <= 0) + { + return; + } + + var state = Load(); + state.ColumnWidths ??= new Dictionary>(StringComparer.Ordinal); + if (!state.ColumnWidths.TryGetValue(cacheKey, out var widths)) + { + widths = LoadColumnWidths(cacheKey) ?? new Dictionary(StringComparer.Ordinal); + state.ColumnWidths[cacheKey] = widths; + } + + widths[columnKey] = width; + if (string.Equals(cacheKey, "module-rules", StringComparison.Ordinal)) + { + state.ModuleRulesGridColumns ??= new Dictionary(StringComparer.Ordinal); + state.ModuleRulesGridColumns[columnKey] = width; + } + + Save(state); + } } internal sealed class UiCacheState @@ -67,6 +110,7 @@ internal sealed class UiCacheState public string? ToggleKey { get; set; } public string? SelectedModuleId { get; set; } public Dictionary? ModuleRulesGridColumns { get; set; } + public Dictionary>? ColumnWidths { get; set; } } internal sealed class WindowLocation diff --git a/UI/ClassConfigEditorControl.cs b/UI/ClassConfigEditorControl.cs index 4b170e72..512c4306 100644 --- a/UI/ClassConfigEditorControl.cs +++ b/UI/ClassConfigEditorControl.cs @@ -386,7 +386,7 @@ public sealed class ClassConfigEditorControl : UserControl panel.Controls.Add(BuildStateCategoryTabs(), 0, 0); - ConfigureGrid(_statesGrid); + ConfigureGrid(_statesGrid, "class-config-states"); _stateNameColumn.Name = "Name"; _stateNameColumn.HeaderText = "状态名"; _stateNameColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; @@ -476,7 +476,7 @@ public sealed class ClassConfigEditorControl : UserControl panel.Controls.Add(BuildAuraBucketTabs(), 0, 0); - ConfigureGrid(_aurasGrid); + ConfigureGrid(_aurasGrid, "class-config-auras"); _aurasGrid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Name", HeaderText = "名称", Width = 160 }); _aurasGrid.Columns.Add(new DataGridViewTextBoxColumn { Name = "SpellId", HeaderText = "spellId", Width = 110 }); _aurasGrid.Columns.Add(new DataGridViewTextBoxColumn @@ -573,7 +573,7 @@ public sealed class ClassConfigEditorControl : UserControl textureOrderHint.Padding = new Padding(8, 0, 0, 0); panel.Controls.Add(textureOrderHint, 0, 0); - ConfigureGrid(_spellsGrid); + ConfigureGrid(_spellsGrid, "class-config-spells"); _spellsGrid.Columns.Add(CreateSpellIconColumn()); _spellsGrid.Columns.Add(CreateSpellTextColumn("Name", "名称", 24, 160)); _spellsGrid.Columns.Add(CreateSpellTextColumn("SpellId", "法术 ID", 14, 120)); @@ -688,7 +688,7 @@ public sealed class ClassConfigEditorControl : UserControl hint.Padding = new Padding(8, 0, 0, 0); panel.Controls.Add(hint, 0, 1); - ConfigureGrid(_spellsListGrid); + ConfigureGrid(_spellsListGrid, "class-config-spells-list"); _spellsListGrid.AllowUserToAddRows = false; _spellsListGrid.CellValueChanged += (_, e) => { @@ -787,7 +787,7 @@ public sealed class ClassConfigEditorControl : UserControl fields.HandleCreated += (_, _) => FitGroupCards(); panel.Controls.Add(fields, 0, 0); - ConfigureGrid(_groupAurasGrid); + ConfigureGrid(_groupAurasGrid, "class-config-group-auras"); _groupAurasGrid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Offset", HeaderText = "偏移", Width = 70 }); _groupAurasGrid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Name", HeaderText = "名称", Width = 160 }); _groupAurasGrid.Columns.Add(new DataGridViewTextBoxColumn { Name = "SpellId", HeaderText = "spellId", Width = 110 }); @@ -951,9 +951,10 @@ public sealed class ClassConfigEditorControl : UserControl return bar; } - private static void ConfigureGrid(DataGridView grid) + private static void ConfigureGrid(DataGridView grid, string cacheKey) { UiTheme.StyleDataGridView(grid); + UiTheme.CacheDataGridViewColumnWidths(grid, cacheKey); grid.AllowUserToAddRows = true; grid.AllowUserToDeleteRows = false; grid.RowHeadersVisible = false; diff --git a/UI/ClassMacrosEditorControl.cs b/UI/ClassMacrosEditorControl.cs index c74bde55..827295eb 100644 --- a/UI/ClassMacrosEditorControl.cs +++ b/UI/ClassMacrosEditorControl.cs @@ -259,8 +259,8 @@ public sealed class ClassMacrosEditorControl : UserControl var pages = new Control[] { BuildDynamicPage(), - BuildArrayPage(_staticGrid, "完整宏", "注释", showParsedMacro: true), - BuildArrayPage(_specialGrid, "完整宏", "注释", showParsedMacro: true) + BuildArrayPage(_staticGrid, "class-macros-static", "完整宏", "注释", showParsedMacro: true), + BuildArrayPage(_specialGrid, "class-macros-special", "完整宏", "注释", showParsedMacro: true) }; foreach (var page in pages) { @@ -334,7 +334,7 @@ public sealed class ClassMacrosEditorControl : UserControl editor.RowStyles.Add(new RowStyle(SizeType.Percent, 100)); editor.RowStyles.Add(new RowStyle(SizeType.Absolute, 44)); - ConfigureGrid(_dynamicGrid); + ConfigureGrid(_dynamicGrid, "class-macros-dynamic"); _dynamicGrid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Name", @@ -396,6 +396,7 @@ public sealed class ClassMacrosEditorControl : UserControl private Control BuildArrayPage( DataGridView grid, + string cacheKey, string textHeader, string commentHeader, bool showParsedMacro) @@ -410,7 +411,7 @@ public sealed class ClassMacrosEditorControl : UserControl panel.RowStyles.Add(new RowStyle(SizeType.Percent, 100)); panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 44)); - ConfigureGrid(grid); + ConfigureGrid(grid, cacheKey); grid.Columns.Add(new DataGridViewTextBoxColumn { Name = "Index", @@ -519,9 +520,10 @@ public sealed class ClassMacrosEditorControl : UserControl return bar; } - private static void ConfigureGrid(DataGridView grid) + private static void ConfigureGrid(DataGridView grid, string cacheKey) { UiTheme.StyleDataGridView(grid); + UiTheme.CacheDataGridViewColumnWidths(grid, cacheKey); grid.AllowUserToAddRows = true; grid.AllowUserToDeleteRows = false; grid.RowHeadersVisible = false; diff --git a/UI/MainForm.cs b/UI/MainForm.cs index c13eacd2..65fcdc14 100644 --- a/UI/MainForm.cs +++ b/UI/MainForm.cs @@ -2042,6 +2042,7 @@ public sealed class MainForm : Form, IMessageFilter { var latestCache = UiCacheStore.Load(); _uiCache.ModuleRulesGridColumns = latestCache.ModuleRulesGridColumns; + _uiCache.ColumnWidths = latestCache.ColumnWidths; var currentBounds = CaptureMainWindowBounds(); _uiCache.MainWindowBounds = currentBounds; diff --git a/UI/ModuleEditorControl.cs b/UI/ModuleEditorControl.cs index 749239fc..ded37118 100644 --- a/UI/ModuleEditorControl.cs +++ b/UI/ModuleEditorControl.cs @@ -56,9 +56,6 @@ public sealed class ModuleEditorControl : UserControl private readonly List _valueAdjustments = new(); private HashSet? _availableConditionFields; private HashSet? _availableGroupConditionFields; - // 程序化恢复列宽时置真, 避免 ColumnWidthChanged 把默认值回写覆盖用户保存的宽度。 - private bool _suppressColumnSave; - private bool _suppressUnitsColumnResize; // 载入时程序化写入"类型"单元格会触发 CellValueChanged; 置真以跳过"按类型清空数值"的联动。 private bool _suppressAdjustmentTypeChange; private bool _moduleCommandInProgress; @@ -73,8 +70,6 @@ public sealed class ModuleEditorControl : UserControl new("队伍 (46)", "46") ]; private static readonly MatchOption[] ClassOptions = BuildClassOptions(); - // 这些列固定宽度并缓存; "条件"列为 Fill, 图标列固定且不缓存。 - private static readonly string[] FixedWidthColumns = ["Enabled", "Spell", "Unit", "MacroCondition"]; private static readonly HashSet NonAuraGroupFields = new(StringComparer.OrdinalIgnoreCase) { "生命值", @@ -427,24 +422,16 @@ public sealed class ModuleEditorControl : UserControl panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 92)); panel.RowStyles.Add(new RowStyle(SizeType.Percent, 100)); - foreach (var column in new[] { ("名称", 210), ("类型", 80), ("摘要", 160) }) - { - _unitsList.Columns.Add(column.Item1, column.Item2); - } - + UiTheme.ConfigureListViewColumns( + _unitsList, + Font, + "module-units", + new UiTheme.ListColumn("名称", 210, 420), + new UiTheme.ListColumn("类型", 80, 240), + new UiTheme.ListColumn("摘要", 160, 2000, FillRemaining: true)); _unitsList.MultiSelect = false; - UiTheme.StyleListView(_unitsList, Font); _unitsList.DoubleClick += (_, _) => EditSelectedUnit(); _unitsList.KeyDown += OnUnitsListKeyDown; - _unitsList.Resize += (_, _) => StretchUnitsSummaryColumn(); - _unitsList.HandleCreated += (_, _) => StretchUnitsSummaryColumn(); - _unitsList.ColumnWidthChanged += (_, _) => - { - if (!_suppressUnitsColumnResize) - { - StretchUnitsSummaryColumn(); - } - }; _unitsEmptyHint.Text = "暂无动态单位 / 数量\n点击右侧「添加」创建"; _unitsEmptyHint.Dock = DockStyle.Fill; @@ -681,6 +668,7 @@ public sealed class ModuleEditorControl : UserControl } }; RefreshAdjustmentFieldColumn(); + UiTheme.CacheDataGridViewColumnWidths(_adjustmentsGrid, "module-adjustments"); return _adjustmentsGrid; } @@ -730,6 +718,7 @@ public sealed class ModuleEditorControl : UserControl } }; RefreshAdjustmentFieldColumn(); + UiTheme.CacheDataGridViewColumnWidths(_formulaAdjustmentsGrid, "module-formula-adjustments"); return _formulaAdjustmentsGrid; } @@ -832,12 +821,11 @@ public sealed class ModuleEditorControl : UserControl _rulesGrid.DragLeave += (_, _) => ClearDragIndicator(); _rulesGrid.Paint += OnRulesGridPaint; _rulesGrid.DataError += (_, e) => e.ThrowException = false; - _rulesGrid.ColumnWidthChanged += OnColumnWidthChanged; _rulesGrid.CellValueChanged += OnRulesGridCellValueChanged; _rulesGrid.HandleCreated += (_, _) => SetCompactRulePrefixColumns(); SetCompactRulePrefixColumns(); RefreshKeymapColumns(); - ApplyColumnWidths(UiCacheStore.Load().ModuleRulesGridColumns); + UiTheme.CacheDataGridViewColumnWidths(_rulesGrid, "module-rules"); return _rulesGrid; } @@ -1653,55 +1641,6 @@ public sealed class ModuleEditorControl : UserControl public int? LogicDelayMs { get; set; } = logicDelayMs; } - private void ApplyColumnWidths(Dictionary? widths) - { - if (widths is null || widths.Count == 0) - { - return; - } - - _suppressColumnSave = true; - try - { - foreach (var name in FixedWidthColumns) - { - if (widths.TryGetValue(name, out var width) && width > 0) - { - var column = _rulesGrid.Columns[name]!; - column.Width = Math.Max(column.MinimumWidth, width); - } - } - } - finally - { - _suppressColumnSave = false; - } - } - - private void OnColumnWidthChanged(object? sender, DataGridViewColumnEventArgs e) - { - // Fill 列(条件)宽度随窗口/其它列变化, 不参与保存; 程序化恢复期间也跳过。 - if (_suppressColumnSave || e.Column.Name == "Condition") - { - return; - } - - SaveColumnWidths(); - } - - private void SaveColumnWidths() - { - var cache = UiCacheStore.Load(); - cache.ModuleRulesGridColumns ??= new(); - - foreach (var name in FixedWidthColumns) - { - cache.ModuleRulesGridColumns[name] = _rulesGrid.Columns[name]!.Width; - } - - UiCacheStore.Save(cache); - } - private void OnRulesGridCellClick(object? sender, DataGridViewCellEventArgs e) { if (e.RowIndex < 0 || e.ColumnIndex < 0) @@ -3211,7 +3150,6 @@ public sealed class ModuleEditorControl : UserControl _rulesGrid.Rows.Clear(); RefreshKeymapColumns(); - ApplyColumnWidths(UiCacheStore.Load().ModuleRulesGridColumns); foreach (var rule in module.Rules) { @@ -3634,27 +3572,6 @@ public sealed class ModuleEditorControl : UserControl } } - private void StretchUnitsSummaryColumn() - { - if (_unitsList.Columns.Count < 3 || _suppressUnitsColumnResize) - { - return; - } - - _suppressUnitsColumnResize = true; - try - { - var summaryWidth = _unitsList.ClientSize.Width - - _unitsList.Columns[0].Width - - _unitsList.Columns[1].Width; - _unitsList.Columns[2].Width = Math.Max(120, summaryWidth); - } - finally - { - _suppressUnitsColumnResize = false; - } - } - private void SelectClass(int? value) { var index = FindMatchOption(_classBox, value); diff --git a/UI/StatusForm.cs b/UI/StatusForm.cs index d9ab888d..05a8572a 100644 --- a/UI/StatusForm.cs +++ b/UI/StatusForm.cs @@ -138,27 +138,27 @@ public sealed class StatusForm : Form _moduleHost = CreatePageHost(); _aboutHost = CreatePageHost(); - _stateList = UiTheme.CreateListView(Font, + _stateList = UiTheme.CreateListView(Font, "status-state", new UiTheme.ListColumn("#", 48, 48, FixedWidth: true), new UiTheme.ListColumn("名称", 110, 260), new UiTheme.ListColumn("值", 100, 900, FillRemaining: true)); - _auraList = UiTheme.CreateListView(Font, + _auraList = UiTheme.CreateListView(Font, "status-aura", new UiTheme.ListColumn("#", 48, 48, FixedWidth: true), new UiTheme.ListColumn("光环", 120, 300), new UiTheme.ListColumn("值", 96, 900, FillRemaining: true)); - _dynamicUnitList = UiTheme.CreateListView(Font, + _dynamicUnitList = UiTheme.CreateListView(Font, "status-dynamic-unit", new UiTheme.ListColumn("类型", 72, 160), new UiTheme.ListColumn("名称", 92, 280), new UiTheme.ListColumn("值", 96, 900, FillRemaining: true)); - _spellList = UiTheme.CreateListView(Font, + _spellList = UiTheme.CreateListView(Font, "status-spell", new UiTheme.ListColumn("#", 48, 48, FixedWidth: true), new UiTheme.ListColumn("技能", 120, 300), new UiTheme.ListColumn("状态", 100, 900, FillRemaining: true)); - _partyList = UiTheme.CreateListView(Font, + _partyList = UiTheme.CreateListView(Font, "status-party", new UiTheme.ListColumn("单位", 120, 180, FixedWidth: true), new UiTheme.ListColumn("摘要", 320, 1600, FillRemaining: true)); - _unitInfoList = UiTheme.CreateListView(Font, + _unitInfoList = UiTheme.CreateListView(Font, "status-unit-info", new UiTheme.ListColumn("名称", 180, 320), new UiTheme.ListColumn("值", 320, 1400, FillRemaining: true)); _logTextBox = new TextBox diff --git a/UI/UiTheme.cs b/UI/UiTheme.cs index 0a2f2c19..5bc02364 100644 --- a/UI/UiTheme.cs +++ b/UI/UiTheme.cs @@ -951,6 +951,23 @@ internal static class UiTheme public static ListView CreateListView(Font font, params ListColumn[] columns) { var listView = new ListView(); + ConfigureListViewColumns(listView, font, null, columns); + return listView; + } + + public static ListView CreateListView(Font font, string cacheKey, params ListColumn[] columns) + { + var listView = new ListView(); + ConfigureListViewColumns(listView, font, cacheKey, columns); + return listView; + } + + public static void ConfigureListViewColumns( + ListView listView, + Font font, + string? cacheKey, + params ListColumn[] columns) + { StyleListView(listView, font); foreach (var column in columns) @@ -972,7 +989,130 @@ internal static class UiTheme } }); }; - return listView; + + if (!string.IsNullOrWhiteSpace(cacheKey)) + { + CacheListViewColumnWidths(listView, cacheKey); + } + } + + public static void CacheDataGridViewColumnWidths(DataGridView grid, string cacheKey) + { + var isApplying = false; + var isInitializing = true; + + void ApplyCachedWidths() + { + var widths = UiCacheStore.LoadColumnWidths(cacheKey); + if (widths is null || widths.Count == 0) + { + return; + } + + isApplying = true; + try + { + foreach (DataGridViewColumn column in grid.Columns) + { + if (column.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill + || !widths.TryGetValue(column.Name, out var width) + || width <= 0) + { + continue; + } + + column.Width = Math.Max(column.MinimumWidth, width); + } + } + finally + { + isApplying = false; + } + } + + grid.ColumnWidthChanged += (_, e) => + { + if (isInitializing + || isApplying + || e.Column.AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill + || string.IsNullOrWhiteSpace(e.Column.Name)) + { + return; + } + + UiCacheStore.SaveColumnWidth(cacheKey, e.Column.Name, e.Column.Width); + }; + grid.HandleCreated += (_, _) => + { + ApplyCachedWidths(); + isInitializing = false; + }; + ApplyCachedWidths(); + if (grid.IsHandleCreated) + { + isInitializing = false; + } + } + + public static void CacheListViewColumnWidths(ListView listView, string cacheKey) + { + if (!ListColumnLayouts.TryGetValue(listView, out var state) + || state.Columns.Count != listView.Columns.Count + || listView.Columns.Count == 0) + { + return; + } + + state.CachedWidths = UiCacheStore.LoadColumnWidths(cacheKey) + ?? new Dictionary(StringComparer.Ordinal); + + void ApplyCachedWidths() + { + state.IsApplyingCachedWidths = true; + try + { + for (var columnIndex = 0; columnIndex < state.Columns.Count; columnIndex++) + { + var layout = state.Columns[columnIndex]; + if (layout.FillRemaining + || !state.CachedWidths.TryGetValue(layout.Text, out var width) + || width <= 0) + { + continue; + } + + var minimum = Scale(listView, layout.MinimumWidth); + var maximum = Scale(listView, Math.Max(layout.MinimumWidth, layout.MaximumWidth)); + listView.Columns[columnIndex].Width = Math.Clamp(width, minimum, maximum); + } + } + finally + { + state.IsApplyingCachedWidths = false; + } + } + + listView.ColumnWidthChanged += (_, e) => + { + if (state.IsApplyingCachedWidths + || state.IsFitting + || e.ColumnIndex < 0 + || e.ColumnIndex >= state.Columns.Count) + { + return; + } + + var layout = state.Columns[e.ColumnIndex]; + if (layout.FillRemaining) + { + return; + } + + state.CachedWidths[layout.Text] = listView.Columns[e.ColumnIndex].Width; + UiCacheStore.SaveColumnWidth(cacheKey, layout.Text, listView.Columns[e.ColumnIndex].Width); + }; + + ApplyCachedWidths(); } public static void FitListViewColumns(ListView listView) @@ -985,46 +1125,60 @@ internal static class UiTheme return; } - var availableWidth = Math.Max(0, listView.ClientSize.Width - Scale(listView, 2)); - var widths = new int[state.Columns.Count]; - var fillIndexes = new List(); - var usedWidth = 0; - - for (var columnIndex = 0; columnIndex < state.Columns.Count; columnIndex++) + state.IsFitting = true; + try { - var layout = state.Columns[columnIndex]; - var minimum = Scale(listView, layout.MinimumWidth); - var maximum = Scale(listView, Math.Max(layout.MinimumWidth, layout.MaximumWidth)); - var measured = MeasureListColumn(listView, columnIndex, layout.Text); - var width = layout.FixedWidth ? minimum : Math.Clamp(measured, minimum, maximum); - widths[columnIndex] = width; - if (layout.FillRemaining) + var availableWidth = Math.Max(0, listView.ClientSize.Width - Scale(listView, 2)); + var widths = new int[state.Columns.Count]; + var fillIndexes = new List(); + var usedWidth = 0; + + for (var columnIndex = 0; columnIndex < state.Columns.Count; columnIndex++) { - fillIndexes.Add(columnIndex); + var layout = state.Columns[columnIndex]; + var minimum = Scale(listView, layout.MinimumWidth); + var maximum = Scale(listView, Math.Max(layout.MinimumWidth, layout.MaximumWidth)); + var cachedWidth = 0; + var hasCachedWidth = !layout.FillRemaining + && state.CachedWidths is not null + && state.CachedWidths.TryGetValue(layout.Text, out cachedWidth); + var measured = MeasureListColumn(listView, columnIndex, layout.Text); + var width = hasCachedWidth + ? Math.Clamp(cachedWidth, minimum, maximum) + : layout.FixedWidth ? minimum : Math.Clamp(measured, minimum, maximum); + widths[columnIndex] = width; + if (layout.FillRemaining) + { + fillIndexes.Add(columnIndex); + } + else + { + usedWidth += width; + } } - else + + if (fillIndexes.Count > 0) { - usedWidth += width; + var remaining = Math.Max(0, availableWidth - usedWidth); + var share = remaining / fillIndexes.Count; + foreach (var index in fillIndexes) + { + var layout = state.Columns[index]; + widths[index] = Math.Clamp( + share, + Scale(listView, layout.MinimumWidth), + Scale(listView, Math.Max(layout.MinimumWidth, layout.MaximumWidth))); + } + } + + for (var i = 0; i < widths.Length; i++) + { + listView.Columns[i].Width = widths[i]; } } - - if (fillIndexes.Count > 0) + finally { - var remaining = Math.Max(0, availableWidth - usedWidth); - var share = remaining / fillIndexes.Count; - foreach (var index in fillIndexes) - { - var layout = state.Columns[index]; - widths[index] = Math.Clamp( - share, - Scale(listView, layout.MinimumWidth), - Scale(listView, Math.Max(layout.MinimumWidth, layout.MaximumWidth))); - } - } - - for (var i = 0; i < widths.Length; i++) - { - listView.Columns[i].Width = widths[i]; + state.IsFitting = false; } } @@ -1094,6 +1248,9 @@ internal static class UiTheme private sealed class ListColumnLayoutState(IReadOnlyList columns) { public IReadOnlyList Columns { get; } = columns; + public Dictionary? CachedWidths { get; set; } + public bool IsApplyingCachedWidths { get; set; } + public bool IsFitting { get; set; } } public static string FormatValue(object? value)