in dev/TabView/TabView.cpp [955:1123]
void TabView::UpdateTabWidths(bool shouldUpdateWidths, bool fillAllAvailableSpace)
{
double tabWidth = std::numeric_limits<double>::quiet_NaN();
if (auto&& tabGrid = m_tabContainerGrid.get())
{
// Add up width taken by custom content and + button
double widthTaken = 0.0;
if (auto&& leftContentColumn = m_leftContentColumn.get())
{
widthTaken += leftContentColumn.ActualWidth();
}
if (auto&& addButtonColumn = m_addButtonColumn.get())
{
widthTaken += addButtonColumn.ActualWidth();
}
if (auto&& rightContentColumn = m_rightContentColumn.get())
{
if (auto&& rightContentPresenter = m_rightContentPresenter.get())
{
const winrt::Size rightContentSize = rightContentPresenter.DesiredSize();
rightContentColumn.MinWidth(rightContentSize.Width);
widthTaken += rightContentSize.Width;
}
}
if (auto&& tabColumn = m_tabColumn.get())
{
// Note: can be infinite
const auto availableWidth = previousAvailableSize.Width - widthTaken;
// Size can be 0 when window is first created; in that case, skip calculations; we'll get a new size soon
if (availableWidth > 0)
{
if (TabWidthMode() == winrt::TabViewWidthMode::Equal)
{
auto const minTabWidth = unbox_value<double>(SharedHelpers::FindInApplicationResources(c_tabViewItemMinWidthName, box_value(c_tabMinimumWidth)));
auto const maxTabWidth = unbox_value<double>(SharedHelpers::FindInApplicationResources(c_tabViewItemMaxWidthName, box_value(c_tabMaximumWidth)));
// If we should fill all of the available space, use scrollviewer dimensions
auto const padding = Padding();
double headerWidth = 0.0;
double footerWidth = 0.0;
if (auto&& itemsPresenter = m_itemsPresenter.get())
{
if (auto const header = itemsPresenter.Header().try_as<winrt::FrameworkElement>())
{
headerWidth = header.ActualWidth();
}
if (auto const footer = itemsPresenter.Footer().try_as<winrt::FrameworkElement>())
{
footerWidth = footer.ActualWidth();
}
}
if (fillAllAvailableSpace)
{
// Calculate the proportional width of each tab given the width of the ScrollViewer.
auto const tabWidthForScroller = (availableWidth - (padding.Left + padding.Right + headerWidth + footerWidth)) / (double)(TabItems().Size());
tabWidth = std::clamp(tabWidthForScroller, minTabWidth, maxTabWidth);
}
else
{
double availableTabViewSpace = (tabColumn.ActualWidth() - (padding.Left + padding.Right + headerWidth + footerWidth));
if (const auto increaseButton = m_scrollIncreaseButton.get())
{
if (increaseButton.Visibility() == winrt::Visibility::Visible)
{
availableTabViewSpace -= increaseButton.ActualWidth();
}
}
if (const auto decreaseButton = m_scrollDecreaseButton.get())
{
if (decreaseButton.Visibility() == winrt::Visibility::Visible)
{
availableTabViewSpace -= decreaseButton.ActualWidth();
}
}
// Use current size to update items to fill the currently occupied space
auto const tabWidthUnclamped = availableTabViewSpace / (double)(TabItems().Size());
tabWidth = std::clamp(tabWidthUnclamped, minTabWidth, maxTabWidth);
}
// Size tab column to needed size
tabColumn.MaxWidth(availableWidth + headerWidth + footerWidth);
auto requiredWidth = tabWidth * TabItems().Size() + headerWidth + footerWidth;
if (requiredWidth > availableWidth - (padding.Left + padding.Right))
{
tabColumn.Width(winrt::GridLengthHelper::FromPixels(availableWidth));
if (auto&& listview = m_listView.get())
{
winrt::FxScrollViewer::SetHorizontalScrollBarVisibility(listview, winrt::Windows::UI::Xaml::Controls::ScrollBarVisibility::Visible);
UpdateScrollViewerDecreaseAndIncreaseButtonsViewState();
}
}
else
{
tabColumn.Width(winrt::GridLengthHelper::FromValueAndType(1.0, winrt::GridUnitType::Auto));
if (auto&& listview = m_listView.get())
{
if (shouldUpdateWidths && fillAllAvailableSpace)
{
winrt::FxScrollViewer::SetHorizontalScrollBarVisibility(listview, winrt::Windows::UI::Xaml::Controls::ScrollBarVisibility::Hidden);
}
else
{
if (auto&& decreaseButton = m_scrollDecreaseButton.get())
{
decreaseButton.IsEnabled(false);
}
if (auto&& increaseButton = m_scrollIncreaseButton.get())
{
increaseButton.IsEnabled(false);
}
}
}
}
}
else
{
// Case: TabWidthMode "Compact" or "FitToContent"
tabColumn.MaxWidth(availableWidth);
tabColumn.Width(winrt::GridLengthHelper::FromValueAndType(1.0, winrt::GridUnitType::Auto));
if (auto&& listview = m_listView.get())
{
listview.MaxWidth(availableWidth);
// Calculate if the scroll buttons should be visible.
if (auto&& itemsPresenter = m_itemsPresenter.get())
{
const auto visible = itemsPresenter.ActualWidth() > availableWidth;
winrt::FxScrollViewer::SetHorizontalScrollBarVisibility(listview, visible
? winrt::Windows::UI::Xaml::Controls::ScrollBarVisibility::Visible
: winrt::Windows::UI::Xaml::Controls::ScrollBarVisibility::Hidden);
if (visible)
{
UpdateScrollViewerDecreaseAndIncreaseButtonsViewState();
}
}
}
}
}
}
}
if (shouldUpdateWidths || TabWidthMode() != winrt::TabViewWidthMode::Equal)
{
for (auto item : TabItems())
{
// Set the calculated width on each tab.
auto tvi = item.try_as<winrt::TabViewItem>();
if (!tvi)
{
tvi = ContainerFromItem(item).as<winrt::TabViewItem>();
}
if (tvi)
{
tvi.Width(tabWidth);
}
}
}
}