From ed31e13ff3cf076f459ba1349945a06957f4b104 Mon Sep 17 00:00:00 2001 From: Marcel Wagner Date: Sun, 31 Oct 2021 23:11:24 +0100 Subject: [PATCH] [TabView] Fix bug where removing tabs from tabcollection would not resize tabs (#6160) --- dev/TabView/InteractionTests/TabViewTests.cs | 89 +++++++++++++++++++ dev/TabView/TabView.cpp | 13 ++- dev/TabView/TabView.h | 3 + .../TestUI/TabViewTabClosingBehaviorPage.xaml | 6 +- .../TabViewTabClosingBehaviorPage.xaml.cs | 21 ++++- .../MUXTestInfra/Infra/Application.cs | 4 +- 6 files changed, 126 insertions(+), 10 deletions(-) diff --git a/dev/TabView/InteractionTests/TabViewTests.cs b/dev/TabView/InteractionTests/TabViewTests.cs index 8408c0da79..f7361aee35 100755 --- a/dev/TabView/InteractionTests/TabViewTests.cs +++ b/dev/TabView/InteractionTests/TabViewTests.cs @@ -795,6 +795,95 @@ double GetActualTabViewWidth() } } + [TestMethod] + public void VerifySizingBehaviorModifyingCollectionRemovingLastItem() + { + int pixelTolerance = 5; + + using (var setup = new TestSetupHelper(new[] { "TabView Tests", "TabViewTabClosingBehaviorButton" })) + { + + Log.Comment("Verifying sizing behavior when removing the last tab from tab collection"); + CloseTabAndVerifyWidth("Tab 5", 500, 100); + + CloseTabAndVerifyWidth("Tab 4", 500, 100); + + CloseTabAndVerifyWidth("Tab 3", 500, 140); + + CloseTabAndVerifyWidth("Tab 2", 500, 225); + } + + void CloseTabAndVerifyWidth(string tabName, int expectedWidth, int expectedItemWidth) + { + Log.Comment("Closing tab:" + tabName); + new Button(FindElement.ByName("RemoveLastItemButton")).Click(); + Wait.ForIdle(); + new Button(FindElement.ByName("GetActualWidthButton")).Click(); + Log.Comment("Verifying TabView width"); + Verify.IsTrue(Math.Abs(GetActualTabViewWidth() - expectedWidth) < pixelTolerance); + var firstTabItemWidth = GetFirstTabItemWidth(); + Verify.IsTrue(Math.Abs(firstTabItemWidth - expectedItemWidth) < pixelTolerance); + } + + double GetActualTabViewWidth() + { + var tabviewWidth = new TextBlock(FindElement.ByName("TabViewWidth")); + + return double.Parse(tabviewWidth.GetText()); + } + + double GetFirstTabItemWidth() + { + var tabviewWidth = new TextBlock(FindElement.ByName("TabViewHeaderWidth")); + + return double.Parse(tabviewWidth.GetText().Split(".")[0]); + } + } + + [TestMethod] + public void VerifySizingBehaviorModifyingCollectionRemovingSecondItem() + { + int pixelTolerance = 5; + + using (var setup = new TestSetupHelper(new[] { "TabView Tests", "TabViewTabClosingBehaviorButton" })) + { + + Log.Comment("Verifying sizing behavior when removing the second tab from tab collection"); + CloseTabAndVerifyWidth("Tab 5", 500, 100); + + CloseTabAndVerifyWidth("Tab 4", 500, 100); + + CloseTabAndVerifyWidth("Tab 3", 500, 140); + + CloseTabAndVerifyWidth("Tab 2", 500, 225); + } + + void CloseTabAndVerifyWidth(string tabName, int expectedWidth, int expectedItemWidth) + { + Log.Comment("Closing tab:" + tabName); + new Button(FindElement.ByName("RemoveMiddleItemButton")).Click(); + Wait.ForIdle(); + new Button(FindElement.ByName("GetActualWidthButton")).Click(); + Log.Comment("Verifying TabView width"); + Verify.IsTrue(Math.Abs(GetActualTabViewWidth() - expectedWidth) < pixelTolerance); + Verify.IsTrue(Math.Abs(GetFirstTabItemWidth() - expectedItemWidth) < pixelTolerance); + } + + double GetActualTabViewWidth() + { + var tabviewWidth = new TextBlock(FindElement.ByName("TabViewWidth")); + + return double.Parse(tabviewWidth.GetText()); + } + + double GetFirstTabItemWidth() + { + var tabviewWidth = new TextBlock(FindElement.ByName("TabViewHeaderWidth")); + + return double.Parse(tabviewWidth.GetText().Split(".")[0]); + } + } + [TestMethod] public void VerifySizingBehaviorOnTabCloseComingFromCtrlF4() { diff --git a/dev/TabView/TabView.cpp b/dev/TabView/TabView.cpp index 0c0237b635..f88ea86d25 100755 --- a/dev/TabView/TabView.cpp +++ b/dev/TabView/TabView.cpp @@ -86,6 +86,7 @@ void TabView::OnApplyTemplate() { m_tabContainerGrid.set(containerGrid); m_tabStripPointerExitedRevoker = containerGrid.PointerExited(winrt::auto_revoke, { this,&TabView::OnTabStripPointerExited }); + m_tabStripPointerEnteredRevoker = containerGrid.PointerEntered(winrt::auto_revoke, { this,&TabView::OnTabStripPointerEntered }); } if (!SharedHelpers::Is21H1OrHigher()) @@ -355,6 +356,7 @@ void TabView::UnhookEventsAndClearFields() m_addButtonClickRevoker.revoke(); m_itemsPresenterSizeChangedRevoker.revoke(); m_tabStripPointerExitedRevoker.revoke(); + m_tabStripPointerEnteredRevoker.revoke(); m_scrollViewerLoadedRevoker.revoke(); m_scrollViewerViewChangedRevoker.revoke(); m_scrollDecreaseClickRevoker.revoke(); @@ -508,6 +510,7 @@ void TabView::OnListViewLoaded(const winrt::IInspectable&, const winrt::RoutedEv void TabView::OnTabStripPointerExited(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args) { + m_pointerInTabstrip = false; if (m_updateTabWidthOnPointerLeave) { auto scopeGuard = gsl::finally([this]() @@ -518,6 +521,11 @@ void TabView::OnTabStripPointerExited(const winrt::IInspectable& sender, const w } } +void TabView::OnTabStripPointerEntered(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args) +{ + m_pointerInTabstrip = true; +} + void TabView::OnScrollViewerLoaded(const winrt::IInspectable&, const winrt::RoutedEventArgs& args) { if (auto&& scrollViewer = m_scrollViewer.get()) @@ -678,12 +686,9 @@ void TabView::OnItemsChanged(winrt::IInspectable const& item) } } - // Last item removed, update sizes - // The index of the last element is "Size() - 1", but in TabItems, it is already removed. if (TabWidthMode() == winrt::TabViewWidthMode::Equal) { - m_updateTabWidthOnPointerLeave = true; - if (args.Index() == TabItems().Size()) + if (!m_pointerInTabstrip || args.Index() == TabItems().Size()) { UpdateTabWidths(true, false); } diff --git a/dev/TabView/TabView.h b/dev/TabView/TabView.h index 7ed2aee08e..3cec00eb31 100755 --- a/dev/TabView/TabView.h +++ b/dev/TabView/TabView.h @@ -134,6 +134,7 @@ class TabView : void OnListViewLoaded(const winrt::IInspectable& sender, const winrt::RoutedEventArgs& args); void OnTabStripPointerExited(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args); + void OnTabStripPointerEntered(const winrt::IInspectable& sender, const winrt::PointerRoutedEventArgs& args); void OnListViewSelectionChanged(const winrt::IInspectable& sender, const winrt::SelectionChangedEventArgs& args); void OnListViewDragItemsStarting(const winrt::IInspectable& sender, const winrt::DragItemsStartingEventArgs& args); @@ -166,6 +167,7 @@ class TabView : winrt::TabViewItem FindTabViewItemFromDragItem(const winrt::IInspectable& item); bool m_updateTabWidthOnPointerLeave{ false }; + bool m_pointerInTabstrip{ false }; tracker_ref m_leftContentColumn{ this }; tracker_ref m_tabColumn{ this }; @@ -186,6 +188,7 @@ class TabView : winrt::ListView::Loaded_revoker m_listViewLoadedRevoker{}; winrt::ListView::PointerExited_revoker m_tabStripPointerExitedRevoker{}; + winrt::ListView::PointerEntered_revoker m_tabStripPointerEnteredRevoker{}; winrt::Selector::SelectionChanged_revoker m_listViewSelectionChangedRevoker{}; winrt::UIElement::GettingFocus_revoker m_listViewGettingFocusRevoker{}; diff --git a/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml b/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml index 07a803a666..23a15af2a7 100644 --- a/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml +++ b/dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml @@ -20,10 +20,10 @@ TabCloseRequested="TabViewTabCloseRequested" AddTabButtonClick="AddButtonClick"> - + - + @@ -43,6 +43,8 @@