From d1192901a1aadbe20abb669cb9f26363b0cb8bd3 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 12 May 2021 18:20:21 +0100 Subject: [PATCH 01/15] add contentattribute to image. --- src/Avalonia.Controls/Image.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Avalonia.Controls/Image.cs b/src/Avalonia.Controls/Image.cs index 5fc7d8b6b6..247b62d3cf 100644 --- a/src/Avalonia.Controls/Image.cs +++ b/src/Avalonia.Controls/Image.cs @@ -1,5 +1,6 @@ using Avalonia.Media; using Avalonia.Media.Imaging; +using Avalonia.Metadata; namespace Avalonia.Controls { @@ -37,6 +38,7 @@ namespace Avalonia.Controls /// /// Gets or sets the image that will be displayed. /// + [Content] public IImage Source { get { return GetValue(SourceProperty); } From 6fc5af3a68dd22130de3d6c6565ec8003d282589 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 12 May 2021 20:24:13 +0100 Subject: [PATCH 02/15] use datatemplates instead of itemstemplate for datavalidationerrors. --- src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml index b513fd5eae..b1c8650292 100644 --- a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml @@ -28,13 +28,13 @@ - + - + From b0d5e3197c1580af8aff283ce9ef9778eb4ef9bc Mon Sep 17 00:00:00 2001 From: Max Katz Date: Thu, 13 May 2021 01:00:34 -0400 Subject: [PATCH 03/15] Include inner exception when throwing from BindingEntry --- src/Avalonia.Base/PropertyStore/BindingEntry.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Base/PropertyStore/BindingEntry.cs b/src/Avalonia.Base/PropertyStore/BindingEntry.cs index 1b29338f07..362736eb06 100644 --- a/src/Avalonia.Base/PropertyStore/BindingEntry.cs +++ b/src/Avalonia.Base/PropertyStore/BindingEntry.cs @@ -79,7 +79,7 @@ namespace Avalonia.PropertyStore public void OnError(Exception error) { - throw new NotImplementedException(); + throw new NotImplementedException("BindingEntry.OnError is not implemented", error); } public void OnNext(BindingValue value) From 2043ed3a30ca9feab071f7683b403b1bf059d912 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 13 May 2021 10:26:22 +0100 Subject: [PATCH 04/15] dont provide any templates for datavalidation errors. --- .../Controls/DataValidationErrors.xaml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml index b1c8650292..53c5d4eda6 100644 --- a/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/DataValidationErrors.xaml @@ -27,14 +27,12 @@ + From b3e2b05d1ffefe52fa5f3a69ab316b6e11f55fe0 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 13 May 2021 13:28:20 +0200 Subject: [PATCH 05/15] Implement StretchDirection for Viewbox. Cleanup Viewbox. --- samples/ControlCatalog/Pages/ViewboxPage.xaml | 28 ++++++- .../ControlCatalog/Pages/ViewboxPage.xaml.cs | 31 ++++++- src/Avalonia.Controls/Image.cs | 4 +- src/Avalonia.Controls/Viewbox.cs | 81 +++++++------------ .../ViewboxTests.cs | 56 +++++++++++++ 5 files changed, 141 insertions(+), 59 deletions(-) diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml index e78cf2bc22..f8b4a62290 100644 --- a/samples/ControlCatalog/Pages/ViewboxPage.xaml +++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml @@ -22,14 +22,38 @@ - + Viewbox A control used to scale single child. + + + + + + + + + + + + + + + + + + + + + + + None Fill diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs index 1b5f4bc7f4..7a2bceb8f2 100644 --- a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs @@ -1,18 +1,47 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.Media; namespace ControlCatalog.Pages { public class ViewboxPage : UserControl { + private readonly Viewbox _viewbox; + private readonly ComboBox _stretchSelector; + public ViewboxPage() { - this.InitializeComponent(); + InitializeComponent(); + + _viewbox = this.FindControl("Viewbox"); + + _stretchSelector = this.FindControl("StretchSelector"); + + _stretchSelector.Items = new[] + { + Stretch.Uniform, Stretch.UniformToFill, Stretch.Fill, Stretch.None + }; + + _stretchSelector.SelectedIndex = 0; + + var stretchDirectionSelector = this.FindControl("StretchDirectionSelector"); + + stretchDirectionSelector.Items = new[] + { + StretchDirection.Both, StretchDirection.DownOnly, StretchDirection.UpOnly + }; + + stretchDirectionSelector.SelectedIndex = 0; } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); } + + private void StretchSelector_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + _viewbox.Stretch = (Stretch) _stretchSelector.SelectedItem!; + } } } diff --git a/src/Avalonia.Controls/Image.cs b/src/Avalonia.Controls/Image.cs index 247b62d3cf..c448729643 100644 --- a/src/Avalonia.Controls/Image.cs +++ b/src/Avalonia.Controls/Image.cs @@ -31,8 +31,8 @@ namespace Avalonia.Controls static Image() { - AffectsRender(SourceProperty, StretchProperty); - AffectsMeasure(SourceProperty, StretchProperty); + AffectsRender(SourceProperty, StretchProperty, StretchDirectionProperty); + AffectsMeasure(SourceProperty, StretchProperty, StretchDirectionProperty); } /// diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs index 781c93bcbe..b65f4b31d8 100644 --- a/src/Avalonia.Controls/Viewbox.cs +++ b/src/Avalonia.Controls/Viewbox.cs @@ -1,40 +1,50 @@ -using System; -using Avalonia.Media; +using Avalonia.Media; namespace Avalonia.Controls { /// - /// Viewbox is used to scale single child. + /// Viewbox is used to scale single child to fit in the available space. /// /// public class Viewbox : Decorator { /// - /// The stretch property + /// Defines the property. /// public static readonly AvaloniaProperty StretchProperty = - AvaloniaProperty.RegisterDirect(nameof(Stretch), - v => v.Stretch, (c, v) => c.Stretch = v, Stretch.Uniform); + AvaloniaProperty.Register(nameof(Stretch), Stretch.Uniform); + + /// + /// Defines the property. + /// + public static readonly StyledProperty StretchDirectionProperty = + AvaloniaProperty.Register(nameof(StretchDirection), StretchDirection.Both); private Stretch _stretch = Stretch.Uniform; + static Viewbox() + { + ClipToBoundsProperty.OverrideDefaultValue(true); + AffectsMeasure(StretchProperty, StretchDirectionProperty); + } + /// /// Gets or sets the stretch mode, /// which determines how child fits into the available space. /// - /// - /// The stretch. - /// public Stretch Stretch { get => _stretch; set => SetAndRaise(StretchProperty, ref _stretch, value); } - static Viewbox() + /// + /// Gets or sets a value controlling in what direction contents will be stretched. + /// + public StretchDirection StretchDirection { - ClipToBoundsProperty.OverrideDefaultValue(true); - AffectsMeasure(StretchProperty); + get => GetValue(StretchDirectionProperty); + set => SetValue(StretchDirectionProperty, value); } protected override Size MeasureOverride(Size availableSize) @@ -47,9 +57,9 @@ namespace Avalonia.Controls var childSize = child.DesiredSize; - var scale = GetScale(availableSize, childSize, Stretch); + var size = Stretch.CalculateSize(availableSize, childSize, StretchDirection); - return (childSize * scale).Constrain(availableSize); + return size.Constrain(availableSize); } return new Size(); @@ -62,7 +72,9 @@ namespace Avalonia.Controls if (child != null) { var childSize = child.DesiredSize; - var scale = GetScale(finalSize, childSize, Stretch); + var scale = Stretch.CalculateScaling(finalSize, childSize, StretchDirection); + + // TODO: Viewbox should have another decorator as a child so we won't affect other render transforms. var scaleTransform = child.RenderTransform as ScaleTransform; if (scaleTransform == null) @@ -81,44 +93,5 @@ namespace Avalonia.Controls return new Size(); } - - private static Vector GetScale(Size availableSize, Size childSize, Stretch stretch) - { - double scaleX = 1.0; - double scaleY = 1.0; - - bool validWidth = !double.IsPositiveInfinity(availableSize.Width); - bool validHeight = !double.IsPositiveInfinity(availableSize.Height); - - if (stretch != Stretch.None && (validWidth || validHeight)) - { - scaleX = childSize.Width <= 0.0 ? 0.0 : availableSize.Width / childSize.Width; - scaleY = childSize.Height <= 0.0 ? 0.0 : availableSize.Height / childSize.Height; - - if (!validWidth) - { - scaleX = scaleY; - } - else if (!validHeight) - { - scaleY = scaleX; - } - else - { - switch (stretch) - { - case Stretch.Uniform: - scaleX = scaleY = Math.Min(scaleX, scaleY); - break; - - case Stretch.UniformToFill: - scaleX = scaleY = Math.Max(scaleX, scaleY); - break; - } - } - } - - return new Vector(scaleX, scaleY); - } } } diff --git a/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs b/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs index e005bafbf9..7eaec35506 100644 --- a/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs @@ -114,5 +114,61 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(2.0, scaleTransform.ScaleX); Assert.Equal(2.0, scaleTransform.ScaleY); } + + [Theory] + [InlineData(50, 100, 50, 100, 50, 100, 1)] + [InlineData(50, 100, 150, 150, 50, 100, 1)] + [InlineData(50, 100, 25, 50, 25, 50, 0.5)] + public void Viewbox_Should_Return_Correct_SizeAndScale_StretchDirection_DownOnly( + double childWidth, double childHeight, + double viewboxWidth, double viewboxHeight, + double expectedWidth, double expectedHeight, + double expectedScale) + { + var target = new Viewbox + { + Child = new Control { Width = childWidth, Height = childHeight }, + StretchDirection = StretchDirection.DownOnly + }; + + target.Measure(new Size(viewboxWidth, viewboxHeight)); + target.Arrange(new Rect(default, target.DesiredSize)); + + Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize); + + var scaleTransform = target.Child.RenderTransform as ScaleTransform; + + Assert.NotNull(scaleTransform); + Assert.Equal(expectedScale, scaleTransform.ScaleX); + Assert.Equal(expectedScale, scaleTransform.ScaleY); + } + + [Theory] + [InlineData(50, 100, 50, 100, 50, 100, 1)] + [InlineData(50, 100, 25, 50, 25, 50, 1)] + [InlineData(50, 100, 150, 150, 75, 150, 1.5)] + public void Viewbox_Should_Return_Correct_SizeAndScale_StretchDirection_UpOnly( + double childWidth, double childHeight, + double viewboxWidth, double viewboxHeight, + double expectedWidth, double expectedHeight, + double expectedScale) + { + var target = new Viewbox + { + Child = new Control { Width = childWidth, Height = childHeight }, + StretchDirection = StretchDirection.UpOnly + }; + + target.Measure(new Size(viewboxWidth, viewboxHeight)); + target.Arrange(new Rect(default, target.DesiredSize)); + + Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize); + + var scaleTransform = target.Child.RenderTransform as ScaleTransform; + + Assert.NotNull(scaleTransform); + Assert.Equal(expectedScale, scaleTransform.ScaleX); + Assert.Equal(expectedScale, scaleTransform.ScaleY); + } } } From 6e2384deb804da5cf3d453933f88ba6bce0cc126 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 13 May 2021 14:57:36 +0200 Subject: [PATCH 06/15] Use an ellipse instead. --- samples/ControlCatalog/Pages/ViewboxPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml index f8b4a62290..f9e9c983d5 100644 --- a/samples/ControlCatalog/Pages/ViewboxPage.xaml +++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml @@ -34,7 +34,7 @@ - + From f775f9d3f0af3eb7fa3aaa6be43659c7783767b0 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 13 May 2021 16:00:14 +0200 Subject: [PATCH 07/15] Remove old viewbox samples. --- samples/ControlCatalog/Pages/ViewboxPage.xaml | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml index f9e9c983d5..6e649b39a5 100644 --- a/samples/ControlCatalog/Pages/ViewboxPage.xaml +++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml @@ -1,26 +1,6 @@ - - - F1 M 16.6309,18.6563C 17.1309, - 8.15625 29.8809,14.1563 29.8809, - 14.1563C 30.8809,11.1563 34.1308, - 11.4063 34.1308,11.4063C 33.5,12 - 34.6309,13.1563 34.6309,13.1563C - 32.1309,13.1562 31.1309,14.9062 - 31.1309,14.9062C 41.1309,23.9062 - 32.6309,27.9063 32.6309,27.9062C - 24.6309,24.9063 21.1309,22.1562 - 16.6309,18.6563 Z M 16.6309,19.9063C - 21.6309,24.1563 25.1309,26.1562 - 31.6309,28.6562C 31.6309,28.6562 - 26.3809,39.1562 18.3809,36.1563C - 18.3809,36.1563 18,38 16.3809,36.9063C - 15,36 16.3809,34.9063 16.3809,34.9063C - 16.3809,34.9063 10.1309,30.9062 16.6309,19.9063 Z - - @@ -51,40 +31,5 @@ - - None - Fill - Uniform - UniformToFill - - - Hello World! - - - Hello World! - - - Hello World! - - - Hello World! - - - - - - - - - - - - - - - From 6d0ac9a5417bdc01048b5e86f9e4a985f58ca091 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 13 May 2021 16:33:49 +0200 Subject: [PATCH 08/15] Fix property type on Stretch. --- samples/ControlCatalog/Pages/ViewboxPage.xaml | 7 ++++--- samples/ControlCatalog/Pages/ViewboxPage.xaml.cs | 16 +++------------- src/Avalonia.Controls/Viewbox.cs | 3 ++- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml index 6e649b39a5..ef802db33e 100644 --- a/samples/ControlCatalog/Pages/ViewboxPage.xaml +++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml @@ -12,8 +12,9 @@ - + @@ -25,7 +26,7 @@ - + diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs index 7a2bceb8f2..94b3f3ea14 100644 --- a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs @@ -6,23 +6,18 @@ namespace ControlCatalog.Pages { public class ViewboxPage : UserControl { - private readonly Viewbox _viewbox; - private readonly ComboBox _stretchSelector; - public ViewboxPage() { InitializeComponent(); - _viewbox = this.FindControl("Viewbox"); - - _stretchSelector = this.FindControl("StretchSelector"); + var stretchSelector = this.FindControl("StretchSelector"); - _stretchSelector.Items = new[] + stretchSelector.Items = new[] { Stretch.Uniform, Stretch.UniformToFill, Stretch.Fill, Stretch.None }; - _stretchSelector.SelectedIndex = 0; + stretchSelector.SelectedIndex = 0; var stretchDirectionSelector = this.FindControl("StretchDirectionSelector"); @@ -38,10 +33,5 @@ namespace ControlCatalog.Pages { AvaloniaXamlLoader.Load(this); } - - private void StretchSelector_OnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - _viewbox.Stretch = (Stretch) _stretchSelector.SelectedItem!; - } } } diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs index b65f4b31d8..15ca070de2 100644 --- a/src/Avalonia.Controls/Viewbox.cs +++ b/src/Avalonia.Controls/Viewbox.cs @@ -12,7 +12,8 @@ namespace Avalonia.Controls /// Defines the property. /// public static readonly AvaloniaProperty StretchProperty = - AvaloniaProperty.Register(nameof(Stretch), Stretch.Uniform); + AvaloniaProperty.RegisterDirect(nameof(Stretch), + v => v.Stretch, (c, v) => c.Stretch = v, Stretch.Uniform); /// /// Defines the property. From 59d51d6a56d1a6b62051e656be331b7cea39f668 Mon Sep 17 00:00:00 2001 From: Splitwirez <34009058+Splitwirez@users.noreply.github.com> Date: Fri, 14 May 2021 00:10:50 -0700 Subject: [PATCH 09/15] New Fluent expander style (#5573) * Updated Fluent theme Expander style. closes #5358 * Fixed padding mismatch between header and content * Fixed CornerRadii, unleashed the c o l o u r e s * Use CornerRadiusFilterConverter instead of expander specific converters * Formatting * Fix default theme in ControlCatalog Co-authored-by: Jumar Macato <16554748+jmacato@users.noreply.github.com> Co-authored-by: Max Katz --- samples/ControlCatalog/App.xaml.cs | 8 + src/Avalonia.Themes.Fluent/Accents/Base.xaml | 8 +- .../Controls/Expander.xaml | 317 +++++++++++------- 3 files changed, 219 insertions(+), 114 deletions(-) diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index 020fb2fff3..f3ec7b48aa 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -39,6 +39,10 @@ namespace ControlCatalog public static Styles DefaultLight = new Styles { + new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) + { + Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml") + }, new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) { Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml") @@ -60,6 +64,10 @@ namespace ControlCatalog public static Styles DefaultDark = new Styles { + new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) + { + Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml") + }, new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) { Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml") diff --git a/src/Avalonia.Themes.Fluent/Accents/Base.xaml b/src/Avalonia.Themes.Fluent/Accents/Base.xaml index 8597c76998..1e2acf736d 100644 --- a/src/Avalonia.Themes.Fluent/Accents/Base.xaml +++ b/src/Avalonia.Themes.Fluent/Accents/Base.xaml @@ -1,6 +1,7 @@ diff --git a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml index a6371a5be9..3f70939953 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml @@ -1,141 +1,232 @@ - + + + + + + + Expanded content + + + + + Expanded content + + + + + Expanded content + + + + + Expanded content + + + + + + + 16 + 16 + + 1 + + 1,1,0,1 + 1,1,1,0 + 0,1,1,1 + 1,0,1,1 + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + From 4db1f41f72ccec0f076015513795ca7e9089987d Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Fri, 14 May 2021 22:58:51 +0200 Subject: [PATCH 10/15] Change Viewbox.Stretch to a styled property --- src/Avalonia.Controls/ApiCompatBaseline.txt | 3 ++- src/Avalonia.Controls/Viewbox.cs | 11 ++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt index 7199c15d21..a79b3b4d7b 100644 --- a/src/Avalonia.Controls/ApiCompatBaseline.txt +++ b/src/Avalonia.Controls/ApiCompatBaseline.txt @@ -4,10 +4,11 @@ InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalon InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.IMenuItem.StaysOpenOnClick.set(System.Boolean)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseClosed()' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseOpening()' is present in the implementation but not in the contract. +MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Viewbox.StretchProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract. EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.ICursorImpl)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' is present in the contract but not in the implementation. MembersMustExist : Member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract. -Total Issues: 11 +Total Issues: 12 diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs index 15ca070de2..624c61bb82 100644 --- a/src/Avalonia.Controls/Viewbox.cs +++ b/src/Avalonia.Controls/Viewbox.cs @@ -11,9 +11,8 @@ namespace Avalonia.Controls /// /// Defines the property. /// - public static readonly AvaloniaProperty StretchProperty = - AvaloniaProperty.RegisterDirect(nameof(Stretch), - v => v.Stretch, (c, v) => c.Stretch = v, Stretch.Uniform); + public static readonly StyledProperty StretchProperty = + AvaloniaProperty.Register(nameof(Stretch), Stretch.Uniform); /// /// Defines the property. @@ -21,8 +20,6 @@ namespace Avalonia.Controls public static readonly StyledProperty StretchDirectionProperty = AvaloniaProperty.Register(nameof(StretchDirection), StretchDirection.Both); - private Stretch _stretch = Stretch.Uniform; - static Viewbox() { ClipToBoundsProperty.OverrideDefaultValue(true); @@ -35,8 +32,8 @@ namespace Avalonia.Controls /// public Stretch Stretch { - get => _stretch; - set => SetAndRaise(StretchProperty, ref _stretch, value); + get => GetValue(StretchProperty); + set => SetValue(StretchProperty, value); } /// From 08382e5bf554381a327e215b191d901ab4b16663 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 15 May 2021 20:52:59 -0400 Subject: [PATCH 11/15] Fix SolidColorBrushAnimator NRE --- .../Animation/Animators/SolidColorBrushAnimator.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs index cec96fecf8..a56cc1de8c 100644 --- a/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs +++ b/src/Avalonia.Visuals/Animation/Animators/SolidColorBrushAnimator.cs @@ -12,6 +12,11 @@ namespace Avalonia.Animation.Animators { public override ISolidColorBrush Interpolate(double progress, ISolidColorBrush oldValue, ISolidColorBrush newValue) { + if (oldValue is null || newValue is null) + { + return oldValue; + } + return new ImmutableSolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color)); } @@ -26,6 +31,11 @@ namespace Avalonia.Animation.Animators { public override SolidColorBrush Interpolate(double progress, SolidColorBrush oldValue, SolidColorBrush newValue) { + if (oldValue is null || newValue is null) + { + return oldValue; + } + return new SolidColorBrush(ColorAnimator.InterpolateCore(progress, oldValue.Color, newValue.Color)); } } From 34505c4c8b41c9f98553e4b2f500a8462be5811f Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 15 May 2021 20:53:28 -0400 Subject: [PATCH 12/15] Reuse Animator.Interpolate in transitions code --- .../Transitions/DoubleTransition.cs | 10 ++++----- .../Transitions/FloatTransition.cs | 7 +++++-- .../Transitions/IntegerTransition.cs | 7 +++++-- .../Transitions/CornerRadiusTransition.cs | 21 +++++-------------- .../Animation/Transitions/PointTransition.cs | 10 ++++----- .../Animation/Transitions/SizeTransition.cs | 10 ++++----- .../Transitions/ThicknessTransition.cs | 10 ++++----- .../Animation/Transitions/VectorTransition.cs | 10 ++++----- 8 files changed, 40 insertions(+), 45 deletions(-) diff --git a/src/Avalonia.Animation/Transitions/DoubleTransition.cs b/src/Avalonia.Animation/Transitions/DoubleTransition.cs index 8cae1e1f81..d5bb1aac20 100644 --- a/src/Avalonia.Animation/Transitions/DoubleTransition.cs +++ b/src/Avalonia.Animation/Transitions/DoubleTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,15 +10,13 @@ namespace Avalonia.Animation /// public class DoubleTransition : Transition { + private static readonly DoubleAnimator s_animator = new DoubleAnimator(); + /// public override IObservable DoTransition(IObservable progress, double oldValue, double newValue) { return progress - .Select(p => - { - var f = Easing.Ease(p); - return ((newValue - oldValue) * f) + oldValue; - }); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } diff --git a/src/Avalonia.Animation/Transitions/FloatTransition.cs b/src/Avalonia.Animation/Transitions/FloatTransition.cs index 427563e559..37b644fa96 100644 --- a/src/Avalonia.Animation/Transitions/FloatTransition.cs +++ b/src/Avalonia.Animation/Transitions/FloatTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,12 +10,13 @@ namespace Avalonia.Animation /// public class FloatTransition : Transition { + private static readonly FloatAnimator s_animator = new FloatAnimator(); + /// public override IObservable DoTransition(IObservable progress, float oldValue, float newValue) { - var delta = newValue - oldValue; return progress - .Select(p => (float)Easing.Ease(p) * delta + oldValue); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } diff --git a/src/Avalonia.Animation/Transitions/IntegerTransition.cs b/src/Avalonia.Animation/Transitions/IntegerTransition.cs index 7a85bd75dc..223b2ba531 100644 --- a/src/Avalonia.Animation/Transitions/IntegerTransition.cs +++ b/src/Avalonia.Animation/Transitions/IntegerTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,12 +10,13 @@ namespace Avalonia.Animation /// public class IntegerTransition : Transition { + private static readonly Int32Animator s_animator = new Int32Animator(); + /// public override IObservable DoTransition(IObservable progress, int oldValue, int newValue) { - var delta = newValue - oldValue; return progress - .Select(p => (int)(Easing.Ease(p) * delta + oldValue)); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } diff --git a/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs index 0b0f04ca94..9ffdf53694 100644 --- a/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs +++ b/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,26 +10,13 @@ namespace Avalonia.Animation /// public class CornerRadiusTransition : Transition { + private static readonly CornerRadiusAnimator s_animator = new CornerRadiusAnimator(); + /// public override IObservable DoTransition(IObservable progress, CornerRadius oldValue, CornerRadius newValue) { return progress - .Select(p => - { - var f = Easing.Ease(p); - - var deltaTL = newValue.TopLeft - oldValue.TopLeft; - var deltaTR = newValue.TopRight - oldValue.TopRight; - var deltaBR = newValue.BottomRight - oldValue.BottomRight; - var deltaBL = newValue.BottomLeft - oldValue.BottomLeft; - - var nTL = f * deltaTL + oldValue.TopLeft; - var nTR = f * deltaTR + oldValue.TopRight; - var nBR = f * deltaBR + oldValue.BottomRight; - var nBL = f * deltaBL + oldValue.BottomLeft; - - return new CornerRadius(nTL, nTR, nBR, nBL); - }); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } diff --git a/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs index 29db5fc868..fbe24c6d55 100644 --- a/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs +++ b/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,15 +10,13 @@ namespace Avalonia.Animation /// public class PointTransition : Transition { + private static readonly PointAnimator s_animator = new PointAnimator(); + /// public override IObservable DoTransition(IObservable progress, Point oldValue, Point newValue) { return progress - .Select(p => - { - var f = Easing.Ease(p); - return ((newValue - oldValue) * f) + oldValue; - }); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } diff --git a/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs index b40e789915..464f83bec7 100644 --- a/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs +++ b/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,15 +10,13 @@ namespace Avalonia.Animation /// public class SizeTransition : Transition { + private static readonly SizeAnimator s_animator = new SizeAnimator(); + /// public override IObservable DoTransition(IObservable progress, Size oldValue, Size newValue) { return progress - .Select(p => - { - var f = Easing.Ease(p); - return ((newValue - oldValue) * f) + oldValue; - }); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } diff --git a/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs index 28d4ea067f..9fb3380780 100644 --- a/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs +++ b/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,15 +10,13 @@ namespace Avalonia.Animation /// public class ThicknessTransition : Transition { + private static readonly ThicknessAnimator s_animator = new ThicknessAnimator(); + /// public override IObservable DoTransition(IObservable progress, Thickness oldValue, Thickness newValue) { return progress - .Select(p => - { - var f = Easing.Ease(p); - return ((newValue - oldValue) * f) + oldValue; - }); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } diff --git a/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs index c073e8e192..5038117faa 100644 --- a/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs +++ b/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs @@ -1,6 +1,8 @@ using System; using System.Reactive.Linq; +using Avalonia.Animation.Animators; + namespace Avalonia.Animation { /// @@ -8,15 +10,13 @@ namespace Avalonia.Animation /// public class VectorTransition : Transition { + private static readonly VectorAnimator s_animator = new VectorAnimator(); + /// public override IObservable DoTransition(IObservable progress, Vector oldValue, Vector newValue) { return progress - .Select(p => - { - var f = Easing.Ease(p); - return ((newValue - oldValue) * f) + oldValue; - }); + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); } } } From f29d050e73c0144909757c085bf6bcd5a156f7ae Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 15 May 2021 20:53:45 -0400 Subject: [PATCH 13/15] Add BoxShadows transition --- .../Transitions/BoxShadowsTransition.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/Avalonia.Visuals/Animation/Transitions/BoxShadowsTransition.cs diff --git a/src/Avalonia.Visuals/Animation/Transitions/BoxShadowsTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/BoxShadowsTransition.cs new file mode 100644 index 0000000000..008613fb40 --- /dev/null +++ b/src/Avalonia.Visuals/Animation/Transitions/BoxShadowsTransition.cs @@ -0,0 +1,23 @@ +using System; +using System.Reactive.Linq; + +using Avalonia.Animation.Animators; +using Avalonia.Media; + +namespace Avalonia.Animation +{ + /// + /// Transition class that handles with type. + /// + public class BoxShadowsTransition : Transition + { + private static readonly BoxShadowsAnimator s_animator = new BoxShadowsAnimator(); + + /// + public override IObservable DoTransition(IObservable progress, BoxShadows oldValue, BoxShadows newValue) + { + return progress + .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue)); + } + } +} From f5a01afc6de7ac794d9dfb1a16792cf7f6296ee0 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 15 May 2021 22:05:01 -0400 Subject: [PATCH 14/15] Update RenderDemo pages --- samples/RenderDemo/Pages/AnimationsPage.xaml | 7 +- samples/RenderDemo/Pages/TransitionsPage.xaml | 65 +++++++++++++++++-- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/samples/RenderDemo/Pages/AnimationsPage.xaml b/samples/RenderDemo/Pages/AnimationsPage.xaml index 12fb31ea59..21c7d68b5d 100644 --- a/samples/RenderDemo/Pages/AnimationsPage.xaml +++ b/samples/RenderDemo/Pages/AnimationsPage.xaml @@ -1,7 +1,8 @@ + x:Class="RenderDemo.Pages.AnimationsPage" + MaxWidth="600"> @@ -167,8 +168,8 @@ - - Hover to activate Transform Keyframe Animations. + + Hover to activate Keyframe Animations.