Skip to content

Commit

Permalink
TabView: Separate border lines into being everywhere except the selec…
Browse files Browse the repository at this point in the history
…ted tab (#6332)

* Put border line everywhere except the selected tab.
  • Loading branch information
teaP authored Nov 19, 2021
1 parent 92fbfcd commit 019d045
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 29 deletions.
6 changes: 4 additions & 2 deletions dev/TabView/InteractionTests/TabViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ public void VerifySizingBehaviorOnTabCloseComingFromScroll()

CloseTabAndVerifyWidth("Tab 3", 500, "False;False;");

CloseTabAndVerifyWidth("Tab 5", 420, "False;False;");
CloseTabAndVerifyWidth("Tab 5", 430, "False;False;");

CloseTabAndVerifyWidth("Tab 4", 450, "False;False;");

Expand All @@ -726,7 +726,7 @@ void CloseTabAndVerifyWidth(string tabName, int expectedValue, string expectedSc
Log.Comment("Closing tab:" + tabName);
FindCloseButton(FindElement.ByName(tabName)).Click();
Wait.ForIdle();
Log.Comment("Verifying TabView width");
Log.Comment("Verifying TabView width -- expected " + expectedValue + ", actual " + GetActualTabViewWidth());
Verify.IsTrue(Math.Abs(GetActualTabViewWidth() - expectedValue) < pixelTolerance);
Verify.AreEqual(expectedScrollbuttonStates, FindElement.ByName("ScrollButtonStatus").GetText());

Expand Down Expand Up @@ -926,6 +926,8 @@ public void VerifyHeaderSizeWhenClosingLastTab()
var increaseScrollButton = FindElement.ByName<Button>("IncreaseScrollButton");
increaseScrollButton.Click();
Wait.ForIdle();
increaseScrollButton.Click();
Wait.ForIdle();
var readTabViewWidthButton = new Button(FindElement.ByName("GetActualWidthButton"));
readTabViewWidthButton.Click();
Wait.ForIdle();
Expand Down
88 changes: 84 additions & 4 deletions dev/TabView/TabView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,60 @@ void TabView::OnSelectedIndexPropertyChanged(const winrt::DependencyPropertyChan
SetTabSeparatorOpacity(winrt::unbox_value<int>(args.OldValue()) - 1);
SetTabSeparatorOpacity(SelectedIndex() - 1);
SetTabSeparatorOpacity(SelectedIndex());

UpdateTabBottomBorderLineVisualStates();
}

void TabView::UpdateTabBottomBorderLineVisualStates()
{
const int numItems = static_cast<int>(TabItems().Size());
const int selectedIndex = SelectedIndex();

for (int i = 0; i < numItems; i++)
{
auto state = L"NormalBottomBorderLine";
if (m_isDragging)
{
state = L"NoBottomBorderLine";
}
else if (selectedIndex != -1)
{
if (i == selectedIndex - 1)
{
state = L"LeftOfSelectedTab";
}
else if (i == selectedIndex + 1)
{
state = L"RightOfSelectedTab";
}
}

if (const auto tvi = ContainerFromIndex(i).try_as<winrt::Control>())
{
winrt::VisualStateManager::GoToState(tvi, state, false /*useTransitions*/);
}
}
}

void TabView::UpdateBottomBorderLineVisualStates()
{
// Update border line on all tabs
UpdateTabBottomBorderLineVisualStates();

// Update border lines on the TabView
winrt::VisualStateManager::GoToState(*this, m_isDragging ? L"SingleBottomBorderLine" : L"NormalBottomBorderLine", false /*useTransitions*/);

// Update border lines in the inner TabViewListView
if (const auto lv = m_listView.get())
{
winrt::VisualStateManager::GoToState(lv, m_isDragging ? L"NoBottomBorderLine" : L"NormalBottomBorderLine", false /*useTransitions*/);
}

// Update border lines in the ScrollViewer
if (const auto scroller = m_scrollViewer.get())
{
winrt::VisualStateManager::GoToState(scroller, m_isDragging ? L"NoBottomBorderLine" : L"NormalBottomBorderLine", false /*useTransitions*/);
}
}

void TabView::OnSelectedItemPropertyChanged(const winrt::DependencyPropertyChangedEventArgs& args)
Expand Down Expand Up @@ -506,6 +560,8 @@ void TabView::OnListViewLoaded(const winrt::IInspectable&, const winrt::RoutedEv
}
}
}

UpdateTabBottomBorderLineVisualStates();
}

void TabView::OnTabStripPointerExited(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args)
Expand Down Expand Up @@ -701,6 +757,7 @@ void TabView::OnItemsChanged(winrt::IInspectable const& item)
}
}

UpdateTabBottomBorderLineVisualStates();
}

void TabView::OnListViewSelectionChanged(const winrt::IInspectable& sender, const winrt::SelectionChangedEventArgs& args)
Expand Down Expand Up @@ -750,11 +807,15 @@ winrt::TabViewItem TabView::FindTabViewItemFromDragItem(const winrt::IInspectabl

void TabView::OnListViewDragItemsStarting(const winrt::IInspectable& sender, const winrt::DragItemsStartingEventArgs& args)
{
m_isDragging = true;

auto item = args.Items().GetAt(0);
auto tab = FindTabViewItemFromDragItem(item);
auto myArgs = winrt::make_self<TabViewTabDragStartingEventArgs>(args, item, tab);

m_tabDragStartingEventSource(*this, *myArgs);

UpdateBottomBorderLineVisualStates();
}

void TabView::OnListViewDragOver(const winrt::IInspectable& sender, const winrt::DragEventArgs& args)
Expand All @@ -769,6 +830,8 @@ void TabView::OnListViewDrop(const winrt::IInspectable& sender, const winrt::Dra

void TabView::OnListViewDragItemsCompleted(const winrt::IInspectable& sender, const winrt::DragItemsCompletedEventArgs& args)
{
m_isDragging = false;

auto item = args.Items().GetAt(0);
auto tab = FindTabViewItemFromDragItem(item);
auto myArgs = winrt::make_self<TabViewTabDragCompletedEventArgs>(args, item, tab);
Expand All @@ -781,6 +844,8 @@ void TabView::OnListViewDragItemsCompleted(const winrt::IInspectable& sender, co
auto tabDroppedArgs = winrt::make_self<TabViewTabDroppedOutsideEventArgs>(item, tab);
m_tabDroppedOutsideEventSource(*this, *tabDroppedArgs);
}

UpdateBottomBorderLineVisualStates();
}

void TabView::UpdateTabContent()
Expand Down Expand Up @@ -925,15 +990,30 @@ void TabView::UpdateTabWidths(bool shouldUpdateWidths, bool fillAllAvailableSpac

// 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)) / (double)(TabItems().Size());
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));
double availableTabViewSpace = (tabColumn.ActualWidth() - (padding.Left + padding.Right + headerWidth + footerWidth));
if (const auto increaseButton = m_scrollIncreaseButton.get())
{
if (increaseButton.Visibility() == winrt::Visibility::Visible)
Expand All @@ -957,8 +1037,8 @@ void TabView::UpdateTabWidths(bool shouldUpdateWidths, bool fillAllAvailableSpac


// Size tab column to needed size
tabColumn.MaxWidth(availableWidth);
auto requiredWidth = tabWidth * TabItems().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));
Expand Down
5 changes: 5 additions & 0 deletions dev/TabView/TabView.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ class TabView :

int GetItemCount();

void UpdateBottomBorderLineVisualStates();
void UpdateTabBottomBorderLineVisualStates();

winrt::TabViewItem FindTabViewItemFromDragItem(const winrt::IInspectable& item);

bool m_updateTabWidthOnPointerLeave{ false };
Expand Down Expand Up @@ -215,4 +218,6 @@ class TabView :
winrt::hstring m_tabCloseButtonTooltipText{};

winrt::Size previousAvailableSize{};

bool m_isDragging{ false };
};
Loading

0 comments on commit 019d045

Please sign in to comment.