Skip to content

Commit

Permalink
[TabView] Fix bug where removing tabs from tabcollection would not re…
Browse files Browse the repository at this point in the history
…size tabs (#6160)
  • Loading branch information
marcelwgn authored Oct 31, 2021
1 parent 7762387 commit ed31e13
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 10 deletions.
89 changes: 89 additions & 0 deletions dev/TabView/InteractionTests/TabViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
13 changes: 9 additions & 4 deletions dev/TabView/TabView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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]()
Expand All @@ -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())
Expand Down Expand Up @@ -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);
}
Expand Down
3 changes: 3 additions & 0 deletions dev/TabView/TabView.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -166,6 +167,7 @@ class TabView :
winrt::TabViewItem FindTabViewItemFromDragItem(const winrt::IInspectable& item);

bool m_updateTabWidthOnPointerLeave{ false };
bool m_pointerInTabstrip{ false };

tracker_ref<winrt::ColumnDefinition> m_leftContentColumn{ this };
tracker_ref<winrt::ColumnDefinition> m_tabColumn{ this };
Expand All @@ -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{};

Expand Down
6 changes: 4 additions & 2 deletions dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
TabCloseRequested="TabViewTabCloseRequested"
AddTabButtonClick="AddButtonClick">

<muxc:TabViewItem Header="Tab 0" AutomationProperties.Name="Tab 0"/>
<muxc:TabViewItem Header="Tab 0" x:Name="Tab0" AutomationProperties.Name="Tab 0"/>
<muxc:TabViewItem Header="Tab 1" AutomationProperties.Name="Tab 1"/>
<muxc:TabViewItem Header="Tab 2" AutomationProperties.Name="Tab 2"/>
<muxc:TabViewItem Header="Tab 3" x:Name="Tab3" AutomationProperties.Name="Tab 3"/>
<muxc:TabViewItem Header="Tab 3" AutomationProperties.Name="Tab 3"/>
<muxc:TabViewItem Header="Tab 4" AutomationProperties.Name="Tab 4"/>
<muxc:TabViewItem Header="Tab 5" AutomationProperties.Name="Tab 5"/>
</muxc:TabView>
Expand All @@ -43,6 +43,8 @@
<Button AutomationProperties.Name="IncreaseScrollButton"
Click="IncreaseScrollButton_Click"
Content="Increase scroll" />
<Button AutomationProperties.Name="RemoveMiddleItemButton" Click="RemoveMiddleItem_Click" Content="Remove Middle item"/>
<Button AutomationProperties.Name="RemoveLastItemButton" Click="RemoveLastItem_Click" Content="Remove last item"/>
</StackPanel>
</StackPanel>
</Grid>
Expand Down
21 changes: 19 additions & 2 deletions dev/TabView/TestUI/TabViewTabClosingBehaviorPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private void TabViewTabCloseRequested(object sender, Microsoft.UI.Xaml.Controls.
Tabs.TabItems.Remove(e.Tab);

TabViewWidth.Text = Tabs.ActualWidth.ToString();
TabViewHeaderWidth.Text = Tab3.Width.ToString();
TabViewHeaderWidth.Text = Tab0.Width.ToString();

var scrollButtonStateValue = "";

Expand All @@ -63,13 +63,21 @@ private void TabViewTabCloseRequested(object sender, Microsoft.UI.Xaml.Controls.
ScrollButtonStatus.Text = scrollButtonStateValue;
}

public void GetFirstItemWidthButton_Click(object sender, RoutedEventArgs e)
{
// This is the smallest width that fits our content without any scrolling.
TabViewWidth.Text = Tabs.ActualWidth.ToString();

// Header width
TabViewHeaderWidth.Text = Tab0.Width.ToString();
}
public void GetActualWidthsButton_Click(object sender, RoutedEventArgs e)
{
// This is the smallest width that fits our content without any scrolling.
TabViewWidth.Text = Tabs.ActualWidth.ToString();

// Header width
TabViewHeaderWidth.Text = Tab3.Width.ToString();
TabViewHeaderWidth.Text = Tab0.Width.ToString();
}

public void IncreaseScrollButton_Click(object sender, RoutedEventArgs e)
Expand All @@ -78,5 +86,14 @@ public void IncreaseScrollButton_Click(object sender, RoutedEventArgs e)
sv.ChangeView(10000, null, null, disableAnimation: true);
}

private void RemoveMiddleItem_Click(object sender, RoutedEventArgs e)
{
Tabs.TabItems.RemoveAt(1);
}

private void RemoveLastItem_Click(object sender, RoutedEventArgs e)
{
Tabs.TabItems.RemoveAt(Tabs.TabItems.Count - 1);
}
}
}
4 changes: 2 additions & 2 deletions test/testinfra/MUXTestInfra/Infra/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ private UIObject LaunchApp()
catch (Exception ex)
{
Log.Comment("Failed to launch app. Exception: " + ex.ToString());

if (retries < MaxLaunchRetries)
{
Log.Comment("UAPApp.Launch might not have waited long enough, trying again {0}", retries);
Expand Down Expand Up @@ -354,7 +354,7 @@ private void EnsureApplicationProcessHasExited(int appWindowsProccessId)
// 3. Use the Process obj we found when this Application object was initialized.
// This is just a sanity check. Under normal circumstances, there should only be
// one app process.

var appProcesses = Process.GetProcessesByName(_appProcessName).ToList();

if (appWindowsProccessId != -1)
Expand Down

0 comments on commit ed31e13

Please sign in to comment.