Skip to content

Commit

Permalink
feat: Update TabView to latest MUX
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Jun 14, 2021
1 parent bbc56d9 commit eb3c105
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 35 deletions.
3 changes: 3 additions & 0 deletions src/Uno.UI.FluentTheme/XamlControlsResources.cs
Expand Up @@ -51,5 +51,8 @@ public ControlsResourcesVersion ControlsResourcesVersion
[NotImplemented]
public static DependencyProperty ControlsResourcesVersionProperty { get; } =
DependencyProperty.Register(nameof(ControlsResourcesVersion), typeof(ControlsResourcesVersion), typeof(XamlControlsResources), new PropertyMetadata(ControlsResourcesVersion.Version1));

[NotImplemented]
internal static bool IsUsingResourcesVersion2() => false;
}
}
@@ -1,4 +1,6 @@
#if !WINDOWS_UWP
// MUX Reference: TabViewTests.cs, commit 542e6f9

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

Expand Down
107 changes: 75 additions & 32 deletions src/Uno.UI/Microsoft/UI/Xaml/Controls/TabView/TabView.cs
@@ -1,4 +1,4 @@
// MUX Reference: TabView.cpp, commit 309c88f
// MUX Reference: TabView.cpp, TabView.h, commit a987a18

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
Expand Down Expand Up @@ -202,25 +202,60 @@ Button GetAddButton()

if (SharedHelpers.IsThemeShadowAvailable())
{
var shadowCaster = GetTemplateChild("ShadowCaster") as Grid;
if (shadowCaster != null)
if (!SharedHelpers.Is21H1OrHigher())
{
var shadow = new ThemeShadow();
shadow.Receivers.Add(GetShadowReceiver());
var shadowCaster = GetTemplateChild("ShadowCaster") as Grid;
if (shadowCaster != null)
{
var shadow = new ThemeShadow();
shadow.Receivers.Add(GetShadowReceiver());

double shadowDepth = (double)SharedHelpers.FindInApplicationResources(c_tabViewShadowDepthName, c_tabShadowDepth);
double shadowDepth = (double)SharedHelpers.FindInApplicationResources(c_tabViewShadowDepthName, c_tabShadowDepth);

var currentTranslation = shadowCaster.Translation;
var translation = new Vector3(currentTranslation.X, currentTranslation.Y, (float)shadowDepth);
shadowCaster.Translation = translation;
var currentTranslation = shadowCaster.Translation;
var translation = new Vector3(currentTranslation.X, currentTranslation.Y, (float)shadowDepth);
shadowCaster.Translation = translation;

shadowCaster.Shadow = shadow;
shadowCaster.Shadow = shadow;
}
}
}

UpdateListViewItemContainerTransitions();
}

internal void SetTabSeparatorOpacity(int index, int opacityValue)
{
if (ContainerFromIndex(index) is TabViewItem tvi)
{
// The reason we set the opacity directly instead of using VisualState
// is because we want to hide the separator on hover/pressed
// but the tab adjacent on the left to the selected tab
// must hide the tab separator at all times.
// It causes two visual states to modify the same property
// what leads to undesired behaviour.
if (tvi.GetTemplateChild("TabSeparator") is FrameworkElement tabSeparator)
{
tabSeparator.Opacity = opacityValue;
}
}
}

internal void SetTabSeparatorOpacity(int index)
{
var selectedIndex = SelectedIndex;

// If Tab is adjacent on the left to selected one or
// it is selected tab - we hide the tabSeparator.
if (index == selectedIndex || index + 1 == selectedIndex)
{
SetTabSeparatorOpacity(index, 0);
}
else
{
SetTabSeparatorOpacity(index, 1);
}
}

private void OnListViewDraggingPropertyChanged(DependencyObject sender, DependencyProperty args)
{
Expand Down Expand Up @@ -287,7 +322,14 @@ private void OnListViewGettingFocus(object sender, GettingFocusEventArgs args)

private void OnSelectedIndexPropertyChanged(DependencyPropertyChangedEventArgs args)
{
// We update previous selected and adjacent on the left tab
// as well as current selected and adjacent on the left tab
// to show/hide tabSeparator accordingly.
UpdateSelectedIndex();
SetTabSeparatorOpacity((int)args.OldValue);
SetTabSeparatorOpacity(((int)args.OldValue) - 1);
SetTabSeparatorOpacity(SelectedIndex - 1);
SetTabSeparatorOpacity(SelectedIndex);
}

private void OnSelectedItemPropertyChanged(DependencyPropertyChangedEventArgs args)
Expand Down Expand Up @@ -708,13 +750,21 @@ internal void OnItemsChanged(object item)

int numItems = TabItems.Count;

var listViewInnerSelectedIndex = m_listView.SelectedIndex;
var selectedIndex = SelectedIndex;

if (selectedIndex != listViewInnerSelectedIndex && listViewInnerSelectedIndex != -1)
{
SelectedIndex = listViewInnerSelectedIndex;
selectedIndex = listViewInnerSelectedIndex;
}

if (args.CollectionChange == CollectionChange.ItemRemoved)
{
m_updateTabWidthOnPointerLeave = true;
if (numItems > 0)
{
// SelectedIndex might also already be -1
var selectedIndex = SelectedIndex;
if (selectedIndex == -1 || selectedIndex == args.Index)
{
// Find the closest tab to select instead.
Expand Down Expand Up @@ -759,6 +809,7 @@ internal void OnItemsChanged(object item)
else
{
UpdateTabWidths();
SetTabSeparatorOpacity(numItems - 1);
}
}
}
Expand Down Expand Up @@ -916,7 +967,7 @@ void OnTabContentPresenterLosingFocus(object sender, LosingFocusEventArgs args)
}
}

internal void RequestCloseTab(TabViewItem container)
internal void RequestCloseTab(TabViewItem container, bool updateTabWidths)
{
var listView = m_listView;
if (listView != null)
Expand All @@ -931,7 +982,7 @@ internal void RequestCloseTab(TabViewItem container)
internalTabViewItem.RaiseRequestClose(args);
}
}
UpdateTabWidths(false);
UpdateTabWidths(updateTabWidths);
}

private void OnScrollDecreaseClick(object sender, RoutedEventArgs args)
Expand Down Expand Up @@ -1056,7 +1107,7 @@ private void UpdateTabWidths(bool shouldUpdateWidths = true, bool fillAllAvailab
// Size tab column to needed size
tabColumn.MaxWidth = availableWidth;
var requiredWidth = tabWidth * TabItems.Count;
if (requiredWidth >= availableWidth)
if (requiredWidth > (availableWidth - (padding.Left + padding.Right)))
{
tabColumn.Width = GridLengthHelper.FromPixels(availableWidth);
var listview = m_listView;
Expand Down Expand Up @@ -1158,23 +1209,6 @@ void UpdateSelectedItem()
if (listView != null)
{
listView.SelectedItem = SelectedItem;

// TODO: Uno specific - this is currently commented out,
// possibly a WinUI bug - https://github.com/microsoft/microsoft-ui-xaml/issues/3969
//var tvi = SelectedItem as TabViewItem;
//if (tvi == null)
//{
// tvi = ContainerFromItem(SelectedItem) as TabViewItem;
//}

//if (tvi != null)
//{
// listView.SelectedItem = tvi;

// // Setting ListView.SelectedItem will not work here in all cases.
// // The reason why that doesn't work but this does is unknown.
// tvi.IsSelected = true;
//}
}
}

Expand Down Expand Up @@ -1212,6 +1246,15 @@ public DependencyObject ContainerFromIndex(int index)
return null;
}

internal int IndexFromContainer(DependencyObject container)
{
if (m_listView is ListView listView)
{
return listView.IndexFromContainer(container);
}
return -1;
}

public object ItemFromContainer(DependencyObject container)
{
var listView = m_listView;
Expand Down Expand Up @@ -1271,7 +1314,7 @@ private bool RequestCloseCurrentTab()
if (selectedTab.IsClosable)
{
// Close the tab on ctrl + F4
RequestCloseTab(selectedTab);
RequestCloseTab(selectedTab, true);
handled = true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/Microsoft/UI/Xaml/Controls/TabView/TabView.xaml
@@ -1,5 +1,5 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
<!-- MUX Reference TabView.xaml, commit 309c88f -->
<!-- MUX Reference TabView_v1.xaml, commit 3706758 -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Expand Down
49 changes: 47 additions & 2 deletions src/Uno.UI/Microsoft/UI/Xaml/Controls/TabView/TabViewItem.cs
Expand Up @@ -43,6 +43,8 @@ public TabViewItem()

SetValue(TabViewTemplateSettingsProperty, new TabViewItemTemplateSettings());

Loaded += OnLoaded;

RegisterPropertyChangedCallback(SelectorItem.IsSelectedProperty, OnIsSelectedPropertyChanged);
}

Expand Down Expand Up @@ -88,7 +90,13 @@ Button GetCloseButton(TabView internalTabView)
if (internalTabView != null)
{
var shadow = new ThemeShadow();
shadow.Receivers.Add(internalTabView.GetShadowReceiver());
if (!SharedHelpers.Is21H1OrHigher())
{
if (internalTabView.GetShadowReceiver() is UIElement shadowReceiver)
{
shadow.Receivers.Add(shadowReceiver);
}
}
m_shadow = shadow;

double shadowDepth = (double)SharedHelpers.FindInApplicationResources(TabView.c_tabViewShadowDepthName, TabView.c_tabShadowDepth);
Expand All @@ -109,6 +117,16 @@ Button GetCloseButton(TabView internalTabView)
UpdateWidthModeVisualState();
}

private void OnLoaded(object sender, RoutedEventArgs args)
{
if (GetParentTabView() is TabView tabView)
{
var internalTabView = tabView;
var index = internalTabView.IndexFromContainer(this);
internalTabView.SetTabSeparatorOpacity(index);
}
}

private void OnIsSelectedPropertyChanged(DependencyObject sender, DependencyProperty args)
{
var peer = FrameworkElementAutomationPeer.CreatePeerForElement(this);
Expand All @@ -120,6 +138,7 @@ private void OnIsSelectedPropertyChanged(DependencyObject sender, DependencyProp
if (IsSelected)
{
SetValue(Canvas.ZIndexProperty, 20);
StartBringIntoView();
}
else
{
Expand All @@ -135,6 +154,8 @@ private void OnIsSelectedPropertyChanged(DependencyObject sender, DependencyProp
private void UpdateShadow()
{
if (SharedHelpers.IsThemeShadowAvailable())
// TODO Uno: Can't access XamlControlsResources from Uno.UI
//&& !Microsoft.UI.Xaml.Controls.XamlControlsResources.IsUsingControlsResourcesVersion2)
{
if (IsSelected && !m_isDragging)
{
Expand Down Expand Up @@ -241,7 +262,7 @@ private void RequestClose()
var internalTabView = tabView;
if (internalTabView != null)
{
internalTabView.RequestCloseTab(this);
internalTabView.RequestCloseTab(this, false);
}
}
}
Expand Down Expand Up @@ -352,6 +373,26 @@ protected override void OnPointerReleased(PointerRoutedEventArgs args)
}
}

private void HideLeftAdjacentTabSeparator()
{
if (GetParentTabView() is TabView tabView)
{
var internalTabView = tabView;
var index = internalTabView.IndexFromContainer(this);
internalTabView.SetTabSeparatorOpacity(index - 1, 0);
}
}

private void RestoreLeftAdjacentTabSeparatorVisibility()
{
if (GetParentTabView() is TabView tabView)
{
var internalTabView = tabView;
var index = internalTabView.IndexFromContainer(this);
internalTabView.SetTabSeparatorOpacity(index - 1);
}
}

protected override void OnPointerEntered(PointerRoutedEventArgs args)
{
base.OnPointerEntered(args);
Expand All @@ -364,6 +405,7 @@ protected override void OnPointerEntered(PointerRoutedEventArgs args)
}

UpdateCloseButton();
HideLeftAdjacentTabSeparator();
}

protected override void OnPointerExited(PointerRoutedEventArgs args)
Expand All @@ -374,6 +416,7 @@ protected override void OnPointerExited(PointerRoutedEventArgs args)
m_isMiddlePointerButtonPressed = false;

UpdateCloseButton();
RestoreLeftAdjacentTabSeparatorVisibility();
}

protected override void OnPointerCanceled(PointerRoutedEventArgs args)
Expand All @@ -385,6 +428,7 @@ protected override void OnPointerCanceled(PointerRoutedEventArgs args)
ReleasePointerCapture(args.Pointer);
m_isMiddlePointerButtonPressed = false;
}
RestoreLeftAdjacentTabSeparatorVisibility();
}

protected override void OnPointerCaptureLost(PointerRoutedEventArgs args)
Expand All @@ -393,6 +437,7 @@ protected override void OnPointerCaptureLost(PointerRoutedEventArgs args)

m_hasPointerCapture = false;
m_isMiddlePointerButtonPressed = false;
RestoreLeftAdjacentTabSeparatorVisibility();
}

private void OnIconSourcePropertyChanged(DependencyPropertyChangedEventArgs args)
Expand Down
@@ -1,4 +1,5 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
<!-- MUX Reference TabView_themeresources_v1.xaml, commit 3706758 -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Expand Down

0 comments on commit eb3c105

Please sign in to comment.