Skip to content

Commit

Permalink
fix: Handle Animations precedence as in WinUI
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef1313 committed Feb 19, 2024
1 parent 38924fc commit 00c6bfe
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 3 deletions.
16 changes: 15 additions & 1 deletion src/SamplesApp/UITests.Shared/UITests.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml\VisualStateTests\VisualState_LocalOverride.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml\VisualStateTests\VisualState_ReturnPreviousValue.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml\VisualStateTests\VisualState_Setters.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -6141,6 +6149,12 @@
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml\VisualStateTests\VisualState_Forever_Events.xaml.cs">
<DependentUpon>VisualState_Forever_Events.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml\VisualStateTests\VisualState_LocalOverride.xaml.cs">
<DependentUpon>VisualState_LocalOverride.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml\VisualStateTests\VisualState_ReturnPreviousValue.xaml.cs">
<DependentUpon>VisualState_ReturnPreviousValue.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml\VisualStateTests\VisualState_Setters.xaml.cs">
<DependentUpon>VisualState_Setters.xaml</DependentUpon>
</Compile>
Expand Down Expand Up @@ -9425,4 +9439,4 @@
</Compile>
</ItemGroup>
<Import Project="ItemExclusions.props" />
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<Page
x:Class="UITests.Windows_UI_Xaml.VisualStateTests.VisualState_LocalOverride"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UITests.Windows_UI_Xaml.VisualStateTests"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Large">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="10" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="#FF0000" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="RootGrid" Background="#00FF00">
<Button
HorizontalAlignment="Center"
VerticalAlignment="Center"
x:Name="SetColorButton"
Click="SetColorButton_Click"
Content="Set color" />
</Grid>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Uno.UI.Samples.Controls;
using Windows.UI;

namespace UITests.Windows_UI_Xaml.VisualStateTests;

[Sample("Visual states", Description = "Background should start off as red, but turn blue after the button is clicked.", IsManualTest = true)]
public sealed partial class VisualState_LocalOverride : Page
{
public VisualState_LocalOverride()
{
this.InitializeComponent();
}

private void SetColorButton_Click(object sender, RoutedEventArgs e)
{
RootGrid.Background = new SolidColorBrush(Color.FromArgb(255, 0, 0, 255));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Page
x:Class="UITests.Windows_UI_Xaml.VisualStateTests.VisualState_ReturnPreviousValue"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UITests.Windows_UI_Xaml.VisualStateTests"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultState" />
<VisualState x:Name="SecondState">
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="Red" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="ThirdState">
<VisualState.Setters>
<Setter Target="RootGrid.Background" Value="Blue" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="RootGrid" Background="Green">
<StackPanel Orientation="Vertical">
<Button x:Name="ChangeBackgroundButton" Click="ChangeBackground_Click">Change background (white)</Button>
<Button x:Name="DefaultStateButton" Tag="DefaultState" Click="SetState_Click">Set default state (Green)</Button>
<Button x:Name="SecondStateButton" Tag="SecondState" Click="SetState_Click">Set second state (Red)</Button>
<Button x:Name="ThirdStateButton" Tag="ThirdState" Click="SetState_Click">Set third state (Blue)</Button>
</StackPanel>
</Grid>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Threading.Tasks;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Uno.UI.Samples.Controls;
using Windows.UI;

namespace UITests.Windows_UI_Xaml.VisualStateTests;

[Sample(
"Visual states",
Description = "Background should start off as green, but turn to different color depending on button, keeping in mind that once changed to white, you shouldn't be able to get it green again",
IsManualTest = true)]
public sealed partial class VisualState_ReturnPreviousValue : Page
{
private bool _wasWhiteSet;

public VisualState_ReturnPreviousValue()
{
this.InitializeComponent();
}

private async void SetState_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
var tag = button.Tag.ToString();
VisualStateManager.GoToState(this, tag, true);

if (tag == "DefaultState")
{
if (_wasWhiteSet && ((SolidColorBrush)RootGrid.Background).Color != Microsoft.UI.Colors.White)
{
await ErrorAsync("Background is expected to be white.");
}
else if (!_wasWhiteSet && ((SolidColorBrush)RootGrid.Background).Color != Microsoft.UI.Colors.Green)
{
await ErrorAsync("Background is expected to be green.");
}
}
else if (tag == "SecondState" && ((SolidColorBrush)RootGrid.Background).Color != Microsoft.UI.Colors.Red)
{
await ErrorAsync("Background is expected to be red.");
}
else if (tag == "ThirdState" && ((SolidColorBrush)RootGrid.Background).Color != Microsoft.UI.Colors.Blue)
{
await ErrorAsync("Background is expected to be blue.");
}
}

private async Task ErrorAsync(string text)
{
var dialog = new ContentDialog()
{
XamlRoot = this.XamlRoot,
Content = text,
};

await dialog.ShowAsync();
}

private async void ChangeBackground_Click(object sender, RoutedEventArgs e)
{
RootGrid.Background = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
_wasWhiteSet = true;
if (((SolidColorBrush)RootGrid.Background).Color != Microsoft.UI.Colors.White)
{
await ErrorAsync("Background is expected to be white.");
}
}
}
3 changes: 2 additions & 1 deletion src/Uno.UI.Tests/BinderTests/Given_BindingPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ public void When_WithHigherPrecedence_SetValueAndLocalValue_Then_ValueUpdated()
sut.Value = "Animations";
sut.SetLocalValue("Local");

Assert.AreEqual("Animations", target.Value);
// Local value takes over Animations if it's newer.
Assert.AreEqual("Local", target.Value);

Assert.AreEqual("Animations", target.GetPrecedenceSpecificValue(MyTarget.ValueProperty, DependencyPropertyValuePrecedences.Animations));
Assert.AreEqual("Local", target.GetPrecedenceSpecificValue(MyTarget.ValueProperty, DependencyPropertyValuePrecedences.Local));
Expand Down
23 changes: 22 additions & 1 deletion src/Uno.UI/UI/Xaml/DependencyPropertyDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,18 @@ internal void SetValue(object? value, DependencyPropertyValuePrecedences precede
{
Property.ValidateValue(value);

if (precedence == DependencyPropertyValuePrecedences.Local && value is not UnsetValue)
{
_flags |= Flags.LocalValueNewerThanAnimationsValue;
}
else
{
// This might not make much sense, but this is what we are seeing in WinUI code.
// See https://github.com/unoplatform/uno/issues/5168#issuecomment-1948115761
// If it turned out there is more complexity going on in WinUI, we can adjust as needed.
_flags &= ~Flags.LocalValueNewerThanAnimationsValue;
}

if (!SetValueFast(value, precedence))
{
SetValueFull(value, precedence);
Expand Down Expand Up @@ -265,7 +277,9 @@ internal void ClearBinding()
/// </summary>
/// <returns>The value at the current highest precedence level</returns>
internal object? GetValue()
=> GetValue(_highestPrecedence);
=> GetValue(_highestPrecedence == DependencyPropertyValuePrecedences.Animations && (_flags & Flags.LocalValueNewerThanAnimationsValue) != 0
? DependencyPropertyValuePrecedences.Local
: _highestPrecedence);

/// <summary>
/// Gets the value at a given precedence level
Expand Down Expand Up @@ -468,6 +482,13 @@ private enum Flags : byte
/// Determines if the property inherits Value from its parent
/// </summary>
Inherits = 1 << 4,

/// <summary>
/// Normally, Animations has higher precedence than Local. However,
/// we want local to take higher precedence if it's newer.
/// This flag records this information.
/// </summary>
LocalValueNewerThanAnimationsValue = 1 << 5,
}
}
}

0 comments on commit 00c6bfe

Please sign in to comment.