using Microsoft.UI.Xaml.Media;
using System.Runtime.CompilerServices;
namespace XFEEDToolBox.Controls;
internal static class OutfittingSelectorSizing
{
private static readonly ConditionalWeakTable<ItemsView,object> Observed=new();
public static void Fit(SelectorBar selector)
{
selector.ApplyTemplate();
var items=Find<ItemsView>(selector);
if(items is null||selector.Items.Count==0)return;
if(!Observed.TryGetValue(items,out _))
{
Observed.Add(items,new());
items.SizeChanged+=(_,_)=>Fit(selector);
}
items.ApplyTemplate();
if(items.ScrollView is {} scroll)
{
scroll.ContentOrientation=ScrollingContentOrientation.Vertical;
scroll.HorizontalScrollMode=ScrollingScrollMode.Disabled;
scroll.VerticalScrollMode=ScrollingScrollMode.Disabled;
scroll.HorizontalScrollBarVisibility=ScrollingScrollBarVisibility.Hidden;
scroll.VerticalScrollBarVisibility=ScrollingScrollBarVisibility.Hidden;
}
var available=(items.ScrollView?.ViewportWidth is >0?items.ScrollView.ViewportWidth:items.ActualWidth)-items.Padding.Left-items.Padding.Right;
if(available<=0)return;
var spacing=(items.Layout as StackLayout)?.Spacing??0;
// Share actual pixels as well as layout units. Independently rounding
// four fractional widths at 150% scaling can create a scroll extent.
var scale=selector.XamlRoot?.RasterizationScale??1;
var pixels=Math.Max(0,(int)Math.Floor(available*scale)-(int)Math.Round(spacing*scale)*(selector.Items.Count-1));
var width=pixels/selector.Items.Count;var remainder=pixels%selector.Items.Count;
for(var index=0;index<selector.Items.Count;index++)
{
var item=selector.Items[index];
item.Margin=new(0);
item.MinWidth=0;
item.Width=(width+(index<remainder?1:0))/scale;
}
}
private static T? Find<T>(DependencyObject root) where T:DependencyObject
{
if(root is T found)return found;
for(var i=0;i<VisualTreeHelper.GetChildrenCount(root);i++)
if(Find<T>(VisualTreeHelper.GetChild(root,i)) is {} child)return child;
return null;
}
}
using Microsoft.UI.Xaml.Media;
using System.Runtime.CompilerServices;
namespace XFEEDToolBox.Controls;
internal static class OutfittingSelectorSizing
{
private static readonly ConditionalWeakTable<ItemsView,object> Observed=new();
public static void Fit(SelectorBar selector)
{
selector.ApplyTemplate();
var items=Find<ItemsView>(selector);
if(items is null||selector.Items.Count==0)return;
if(!Observed.TryGetValue(items,out _))
{
Observed.Add(items,new());
items.SizeChanged+=(_,_)=>Fit(selector);
}
items.ApplyTemplate();
if(items.ScrollView is {} scroll)
{
scroll.ContentOrientation=ScrollingContentOrientation.Vertical;
scroll.HorizontalScrollMode=ScrollingScrollMode.Disabled;
scroll.VerticalScrollMode=ScrollingScrollMode.Disabled;
scroll.HorizontalScrollBarVisibility=ScrollingScrollBarVisibility.Hidden;
scroll.VerticalScrollBarVisibility=ScrollingScrollBarVisibility.Hidden;
}
var available=(items.ScrollView?.ViewportWidth is >0?items.ScrollView.ViewportWidth:items.ActualWidth)-items.Padding.Left-items.Padding.Right;
if(available<=0)return;
var spacing=(items.Layout as StackLayout)?.Spacing??0;
// Share actual pixels as well as layout units. Independently rounding
// four fractional widths at 150% scaling can create a scroll extent.
var scale=selector.XamlRoot?.RasterizationScale??1;
var pixels=Math.Max(0,(int)Math.Floor(available*scale)-(int)Math.Round(spacing*scale)*(selector.Items.Count-1));
var width=pixels/selector.Items.Count;var remainder=pixels%selector.Items.Count;
for(var index=0;index<selector.Items.Count;index++)
{
var item=selector.Items[index];
item.Margin=new(0);
item.MinWidth=0;
item.Width=(width+(index<remainder?1:0))/scale;
}
}
private static T? Find<T>(DependencyObject root) where T:DependencyObject
{
if(root is T found)return found;
for(var i=0;i<VisualTreeHelper.GetChildrenCount(root);i++)
if(Find<T>(VisualTreeHelper.GetChild(root,i)) is {} child)return child;
return null;
}
}