Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TabViewItem: Make background of the selected tab all one path #6282

Merged
merged 2 commits into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions dev/Generated/TabViewItemTemplateSettings.properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace winrt::Microsoft::UI::Xaml::Controls
#include "TabViewItemTemplateSettings.g.cpp"

GlobalDependencyProperty TabViewItemTemplateSettingsProperties::s_IconElementProperty{ nullptr };
GlobalDependencyProperty TabViewItemTemplateSettingsProperties::s_TabGeometryProperty{ nullptr };

TabViewItemTemplateSettingsProperties::TabViewItemTemplateSettingsProperties()
{
Expand All @@ -33,11 +34,23 @@ void TabViewItemTemplateSettingsProperties::EnsureProperties()
ValueHelper<winrt::IconElement>::BoxedDefaultValue(),
nullptr);
}
if (!s_TabGeometryProperty)
{
s_TabGeometryProperty =
InitializeDependencyProperty(
L"TabGeometry",
winrt::name_of<winrt::Geometry>(),
winrt::name_of<winrt::TabViewItemTemplateSettings>(),
false /* isAttached */,
ValueHelper<winrt::Geometry>::BoxedDefaultValue(),
nullptr);
}
}

void TabViewItemTemplateSettingsProperties::ClearProperties()
{
s_IconElementProperty = nullptr;
s_TabGeometryProperty = nullptr;
}

void TabViewItemTemplateSettingsProperties::IconElement(winrt::IconElement const& value)
Expand All @@ -52,3 +65,16 @@ winrt::IconElement TabViewItemTemplateSettingsProperties::IconElement()
{
return ValueHelper<winrt::IconElement>::CastOrUnbox(static_cast<TabViewItemTemplateSettings*>(this)->GetValue(s_IconElementProperty));
}

void TabViewItemTemplateSettingsProperties::TabGeometry(winrt::Geometry const& value)
{
[[gsl::suppress(con)]]
{
static_cast<TabViewItemTemplateSettings*>(this)->SetValue(s_TabGeometryProperty, ValueHelper<winrt::Geometry>::BoxValueIfNecessary(value));
}
}

winrt::Geometry TabViewItemTemplateSettingsProperties::TabGeometry()
{
return ValueHelper<winrt::Geometry>::CastOrUnbox(static_cast<TabViewItemTemplateSettings*>(this)->GetValue(s_TabGeometryProperty));
}
5 changes: 5 additions & 0 deletions dev/Generated/TabViewItemTemplateSettings.properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ class TabViewItemTemplateSettingsProperties
void IconElement(winrt::IconElement const& value);
winrt::IconElement IconElement();

void TabGeometry(winrt::Geometry const& value);
winrt::Geometry TabGeometry();

static winrt::DependencyProperty IconElementProperty() { return s_IconElementProperty; }
static winrt::DependencyProperty TabGeometryProperty() { return s_TabGeometryProperty; }

static GlobalDependencyProperty s_IconElementProperty;
static GlobalDependencyProperty s_TabGeometryProperty;

static void EnsureProperties();
static void ClearProperties();
Expand Down
10 changes: 10 additions & 0 deletions dev/TabView/TabView.idl
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,17 @@ unsealed runtimeclass TabViewItemTemplateSettings : Windows.UI.Xaml.DependencyOb

Windows.UI.Xaml.Controls.IconElement IconElement;

[MUX_PUBLIC_V2]
{
Windows.UI.Xaml.Media.Geometry TabGeometry;
}

static Windows.UI.Xaml.DependencyProperty IconElementProperty{ get; };

[MUX_PUBLIC_V2]
{
static Windows.UI.Xaml.DependencyProperty TabGeometryProperty{ get; };
}
}

}
Expand Down
39 changes: 11 additions & 28 deletions dev/TabView/TabView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -391,15 +391,12 @@
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Target="RightRadiusRenderArc.Visibility" Value="Visible"/>
<Setter Target="RightRadiusRenderTriangle.Visibility" Value="Visible"/>
<Setter Target="RightRadiusRenderTriangle.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="LeftRadiusRenderArc.Visibility" Value="Visible"/>
<Setter Target="LeftRadiusRenderTriangle.Visibility" Value="Visible"/>
<Setter Target="LeftRadiusRenderTriangle.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="SelectedBackgroundPath.Visibility" Value="Visible"/>
<Setter Target="SelectedBackgroundPath.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="TabContainer.Margin" Value="{ThemeResource TabViewSelectedItemHeaderMargin}"/>
<Setter Target="TabContainer.BorderBrush" Value="{ThemeResource TabViewSelectedItemBorderBrush}"/>
<Setter Target="TabContainer.BorderThickness" Value="{ThemeResource TabViewSelectedItemBorderThickness}"/>
<Setter Target="TabContainer.Background" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}" />
<Setter Target="TabContainer.Padding" Value="{ThemeResource TabViewSelectedItemHeaderPadding}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundSelected}" />
<Setter Target="IconControl.Foreground" Value="{ThemeResource TabViewItemIconForegroundSelected}" />
Expand All @@ -413,15 +410,12 @@
<VisualState x:Name="PointerOverSelected">
<VisualState.Setters>
<Setter Target="RightRadiusRenderArc.Visibility" Value="Visible"/>
<Setter Target="RightRadiusRenderTriangle.Visibility" Value="Visible"/>
<Setter Target="RightRadiusRenderTriangle.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="LeftRadiusRenderArc.Visibility" Value="Visible"/>
<Setter Target="LeftRadiusRenderTriangle.Visibility" Value="Visible"/>
<Setter Target="LeftRadiusRenderTriangle.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="SelectedBackgroundPath.Visibility" Value="Visible"/>
<Setter Target="SelectedBackgroundPath.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="TabContainer.Margin" Value="{ThemeResource TabViewSelectedItemHeaderMargin}"/>
<Setter Target="TabContainer.BorderBrush" Value="{ThemeResource TabViewSelectedItemBorderBrush}"/>
<Setter Target="TabContainer.BorderThickness" Value="{ThemeResource TabViewSelectedItemBorderThickness}"/>
<Setter Target="TabContainer.Background" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}" />
<Setter Target="TabContainer.Padding" Value="{ThemeResource TabViewSelectedItemHeaderPadding}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundSelected}" />
<Setter Target="IconControl.Foreground" Value="{ThemeResource TabViewItemIconForegroundSelected}" />
Expand All @@ -435,15 +429,12 @@
<VisualState x:Name="PressedSelected">
<VisualState.Setters>
<Setter Target="RightRadiusRenderArc.Visibility" Value="Visible"/>
<Setter Target="RightRadiusRenderTriangle.Visibility" Value="Visible"/>
<Setter Target="RightRadiusRenderTriangle.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="LeftRadiusRenderArc.Visibility" Value="Visible"/>
<Setter Target="LeftRadiusRenderTriangle.Visibility" Value="Visible"/>
<Setter Target="LeftRadiusRenderTriangle.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="SelectedBackgroundPath.Visibility" Value="Visible"/>
<Setter Target="SelectedBackgroundPath.Fill" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}"/>
<Setter Target="TabContainer.Margin" Value="{ThemeResource TabViewSelectedItemHeaderMargin}"/>
<Setter Target="TabContainer.BorderBrush" Value="{ThemeResource TabViewSelectedItemBorderBrush}"/>
<Setter Target="TabContainer.BorderThickness" Value="{ThemeResource TabViewSelectedItemBorderThickness}"/>
<Setter Target="TabContainer.Background" Value="{ThemeResource TabViewItemHeaderBackgroundSelected}" />
<Setter Target="TabContainer.Padding" Value="{ThemeResource TabViewSelectedItemHeaderPadding}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TabViewItemHeaderForegroundSelected}" />
<Setter Target="IconControl.Foreground" Value="{ThemeResource TabViewItemIconForegroundSelected}" />
Expand Down Expand Up @@ -635,14 +626,6 @@
Width="4"
Data="M4 0C4 1.19469 3.47624 2.26706 2.64582 3H0C1.65685 3 3 1.65685 3 0H4Z" />

<Path x:Name="LeftRadiusRenderTriangle"
x:Load="False"
Fill="{ThemeResource TabViewItemHeaderBackgroundSelected}"
VerticalAlignment="Bottom"
Margin="-4,0,0,0"
Visibility="Collapsed"
Data="M0 4H4V0C4 2.20914 2.20914 4 0 4Z" />

<Path x:Name="RightRadiusRenderArc"
x:Load="False"
Grid.Column="2"
Expand All @@ -654,14 +637,14 @@
Width="4"
Data="M0 0C0 1.19469 0.523755 2.26706 1.35418 3H4C2.34315 3 1 1.65685 1 0H0Z"/>

<Path x:Name="RightRadiusRenderTriangle"
<Path x:Name="SelectedBackgroundPath"
x:Load="False"
Grid.Column="2"
Visibility="Collapsed"
Grid.ColumnSpan="3"
Fill="{ThemeResource TabViewItemHeaderBackgroundSelected}"
VerticalAlignment="Bottom"
Margin="0,0,-4,0"
Data="M4 4H0V0C0 2.20914 1.79086 4 4 4Z"/>
Margin="-4,0,-4,0"
Visibility="Collapsed"
Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TabViewTemplateSettings.TabGeometry}" />

<Border x:Name="TabSeparator"
HorizontalAlignment="Right"
Expand Down
36 changes: 33 additions & 3 deletions dev/TabView/TabViewItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ TabViewItem::TabViewItem()
SetValue(s_TabViewTemplateSettingsProperty, winrt::make<TabViewItemTemplateSettings>());

Loaded({ this, &TabViewItem::OnLoaded });
SizeChanged({ this, &TabViewItem::OnSizeChanged });

RegisterPropertyChangedCallback(winrt::SelectorItem::IsSelectedProperty(), { this, &TabViewItem::OnIsSelectedPropertyChanged });
RegisterPropertyChangedCallback(winrt::Control::ForegroundProperty(), { this, &TabViewItem::OnForegroundPropertyChanged });
}

void TabViewItem::OnApplyTemplate()
{
auto popupRadius = unbox_value<winrt::CornerRadius>(ResourceAccessor::ResourceLookup(*this, box_value(c_overlayCornerRadiusKey)));

winrt::IControlProtected controlProtected{ *this };

m_headerContentPresenter.set(GetTemplateChildT<winrt::ContentPresenter>(L"ContentPresenter", controlProtected));
Expand Down Expand Up @@ -97,7 +96,33 @@ void TabViewItem::OnApplyTemplate()

UpdateCloseButton();
UpdateForeground();
UpdateWidthModeVisualState();
UpdateWidthModeVisualState();
UpdateTabGeometry();
}

void TabViewItem::UpdateTabGeometry()
{
auto const templateSettings = winrt::get_self<TabViewItemTemplateSettings>(TabViewTemplateSettings());

auto const height = ActualHeight();
auto const popupRadius = unbox_value<winrt::CornerRadius>(ResourceAccessor::ResourceLookup(*this, box_value(c_overlayCornerRadiusKey)));
auto const leftCorner = popupRadius.TopLeft;
auto const rightCorner = popupRadius.TopRight;

// Assumes 4px curving-out corners, which are hardcoded in the markup
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these really hardcoded? Couldn't the 4px be customized in XAML markup?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the width/height of the LeftRadiusRenderArc and RightRadiusRenderArc, which I guess I could measure... the string is getting very unreadable/undebuggable, though. Is there a better way to construct this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as is for now, and if a request for customizability comes up, we can investigate at that point.

auto data = L"<Geometry xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>F1 M0,%f a 4,4 0 0 0 4,-4 L 4,%f a %f,%f 0 0 1 %f,-%f l %f,0 a %f,%f 0 0 1 %f,%f l 0,%f a 4,4 0 0 0 4,4 Z</Geometry>";

WCHAR strOut[1024];
StringCchPrintf(strOut, ARRAYSIZE(strOut), data,
height - 1,
leftCorner, leftCorner, leftCorner, leftCorner, leftCorner,
ActualWidth() - (leftCorner + rightCorner),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if ActualWidth is real small, like smaller than 8? Any issues there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't look right, that's for sure. The MinWidth of a TabViewItem is set to 100, though; it could be changed but I wouldn't expect tabs that small.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - MinWidth is not likely to be 8 or smaller.

rightCorner, rightCorner, rightCorner, rightCorner,
height - (4 + rightCorner + 1));

const auto geometry = winrt::XamlReader::Load(strOut).try_as<winrt::Geometry>();

templateSettings->TabGeometry(geometry);
}

void TabViewItem::OnLoaded(const winrt::IInspectable& sender, const winrt::RoutedEventArgs& args)
Expand All @@ -110,6 +135,11 @@ void TabViewItem::OnLoaded(const winrt::IInspectable& sender, const winrt::Route
}
}

void TabViewItem::OnSizeChanged(const winrt::IInspectable&, const winrt::SizeChangedEventArgs& args)
{
UpdateTabGeometry();
}

void TabViewItem::OnIsSelectedPropertyChanged(const winrt::DependencyObject& sender, const winrt::DependencyProperty& args)
{

Expand Down
3 changes: 3 additions & 0 deletions dev/TabView/TabViewItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class TabViewItem :
void OnIconSourceChanged();
void UpdateWidthModeVisualState();

void OnSizeChanged(const winrt::IInspectable&, const winrt::SizeChangedEventArgs& args);
void UpdateTabGeometry();

bool m_firstTimeSettingToolTip{ true };

winrt::ButtonBase::Click_revoker m_closeButtonClickRevoker{};
Expand Down