Skip to content

Commit 3d51643

Browse files
committed
Auto-size NavigationView pane to fit the widest sidebar label
The previously hardcoded OpenPaneLength="185" clipped English labels like "Software information", "Donate to the author", and "Backup and restore", as well as longer translations such as de-DE "Programmeinstellungen" / "Backup-Wiederherstellung", pt-BR "Configurações do Programa", tr-TR "Yedekleme ve Geri Yükleme", and ru-RU "Поблагодарить автора". Computes the required pane length at startup from the actual labels: the natural width of each item's text (via FormattedText at the NavigationView's typeface/size/DPI) plus role-specific chrome measured against iNKORE.UI.WPF.Modern v0.10.2's NavigationViewItem template — 100px for expandable parents (icon + chevron slot), 74px for icon-only footer leaves, 67px for nested leaves. Result is clamped to [185, 400] so section items with short text don't shrink the pane below the original width and no single pathological label eats the content area. Since language changes trigger SingleInstance.Restart(), the calculation runs exactly once per launch.
1 parent 0bdb13a commit 3d51643

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

ContextMenuManager/MainWindow.xaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
AlwaysShowHeader="False"
3333
IsBackButtonVisible="Collapsed"
3434
IsSettingsVisible="False"
35-
OpenPaneLength="185"
3635
SelectionChanged="NavView_SelectionChanged">
3736

3837
<!-- Main content area -->

ContextMenuManager/MainWindow.xaml.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Linq;
1212
using System.Windows;
1313
using System.Windows.Input;
14+
using System.Windows.Media;
1415
using DrawingSize = System.Drawing.Size;
1516

1617
namespace ContextMenuManager
@@ -63,6 +64,7 @@ public MainWindow()
6364

6465
// Populate navigation items from AppString
6566
BuildNavigation();
67+
AdjustPaneWidthToContent();
6668

6769
// First-run language download prompt
6870
Loaded += (_, _) => FirstRunDownloadLanguage();
@@ -149,6 +151,50 @@ private void BuildNavigation()
149151
}
150152
}
151153

154+
// Sizes OpenPaneLength to fit the widest item label so translations don't get clipped.
155+
// Chrome values are measured against iNKORE.UI.WPF.Modern v0.10.2's NavigationViewItem template
156+
// (Segoe UI 14pt): an item's rendered width = LPad + content + RPad, where LPad/RPad depend
157+
// on whether the item has an icon or an expand chevron.
158+
private void AdjustPaneWidthToContent()
159+
{
160+
const double chevronChrome = 100; // expandable parent (icon + chevron slot)
161+
const double iconChrome = 74; // leaf with icon (footer items)
162+
const double plainChrome = 67; // nested leaf, no icon
163+
const double minPaneLength = 185;
164+
const double maxPaneLength = 400;
165+
166+
var typeface = new Typeface(NavView.FontFamily, NavView.FontStyle, NavView.FontWeight, NavView.FontStretch);
167+
var pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip;
168+
var fontSize = NavView.FontSize > 0 ? NavView.FontSize : 14;
169+
170+
double maxRequired = 0;
171+
foreach (var item in EnumerateNavigationItems())
172+
{
173+
if (item.Content is not string text || text.Length == 0) continue;
174+
175+
double chrome = item.MenuItems.Count > 0 ? chevronChrome
176+
: item.Icon != null ? iconChrome
177+
: plainChrome;
178+
179+
var ft = new FormattedText(
180+
text,
181+
CultureInfo.CurrentUICulture,
182+
FlowDirection.LeftToRight,
183+
typeface,
184+
fontSize,
185+
Brushes.Black,
186+
pixelsPerDip);
187+
188+
double required = ft.Width + chrome;
189+
if (required > maxRequired) maxRequired = required;
190+
}
191+
192+
NavView.OpenPaneLength = Math.Clamp(
193+
Math.Ceiling(maxRequired),
194+
minPaneLength,
195+
maxPaneLength);
196+
}
197+
152198
private static NavigationViewItem MakeSectionItem(string content, string glyph)
153199
{
154200
var item = new NavigationViewItem() { Content = content, Icon = new FontIcon { Glyph = glyph } };

0 commit comments

Comments
 (0)