From c82a01090de4008ef3436a9ad564fd9d4816e073 Mon Sep 17 00:00:00 2001 From: amwx <40413319+amwx@users.noreply.github.com> Date: Tue, 1 Mar 2022 21:57:51 -0500 Subject: [PATCH 1/3] Update Viewbox to use internal visual and no layout rounding --- src/Avalonia.Controls/ApiCompatBaseline.txt | 3 +- src/Avalonia.Controls/Viewbox.cs | 72 ++++++++++++++++----- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt index 55372a7f1a..d4db1573ad 100644 --- a/src/Avalonia.Controls/ApiCompatBaseline.txt +++ b/src/Avalonia.Controls/ApiCompatBaseline.txt @@ -30,6 +30,7 @@ MembersMustExist : Member 'public System.Double Avalonia.Controls.NumericUpDownV MembersMustExist : Member 'public System.Double Avalonia.Controls.NumericUpDownValueChangedEventArgs.OldValue.get()' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.ScrollViewer.AllowAutoHideProperty' does not exist in the implementation but it does exist in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.TopLevel' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. +CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Viewbox' does not inherit from base type 'Avalonia.Controls.Decorator' in the implementation but it does 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. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Window' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.WindowBase' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. @@ -68,4 +69,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract. -Total Issues: 69 +Total Issues: 70 diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs index 624c61bb82..79e9684c67 100644 --- a/src/Avalonia.Controls/Viewbox.cs +++ b/src/Avalonia.Controls/Viewbox.cs @@ -1,13 +1,15 @@ using Avalonia.Media; +using Avalonia.Metadata; namespace Avalonia.Controls { /// /// Viewbox is used to scale single child to fit in the available space. /// - /// - public class Viewbox : Decorator + public class Viewbox : Control { + private Decorator _containerVisual; + /// /// Defines the property. /// @@ -20,12 +22,27 @@ namespace Avalonia.Controls public static readonly StyledProperty StretchDirectionProperty = AvaloniaProperty.Register(nameof(StretchDirection), StretchDirection.Both); + /// + /// Defines the property + /// + public static readonly StyledProperty ChildProperty = + Decorator.ChildProperty.AddOwner(); + static Viewbox() { ClipToBoundsProperty.OverrideDefaultValue(true); + UseLayoutRoundingProperty.OverrideDefaultValue(true); AffectsMeasure(StretchProperty, StretchDirectionProperty); } + public Viewbox() + { + _containerVisual = new Decorator(); + _containerVisual.RenderTransformOrigin = RelativePoint.TopLeft; + LogicalChildren.Add(_containerVisual); + VisualChildren.Add(_containerVisual); + } + /// /// Gets or sets the stretch mode, /// which determines how child fits into the available space. @@ -45,9 +62,40 @@ namespace Avalonia.Controls set => SetValue(StretchDirectionProperty, value); } + /// + /// Gets or sets the child of the Viewbox + /// + [Content] + public IControl? Child + { + get => GetValue(ChildProperty); + set => SetValue(ChildProperty, value); + } + + /// + /// Gets or sets the transform applied to the container visual that + /// hosts the child of the Viewbox + /// + protected ITransform? InternalTransform + { + get => _containerVisual.RenderTransform; + set => _containerVisual.RenderTransform = value; + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == ChildProperty) + { + _containerVisual.Child = change.NewValue.GetValueOrDefault(); + InvalidateMeasure(); + } + } + protected override Size MeasureOverride(Size availableSize) { - var child = Child; + var child = _containerVisual; if (child != null) { @@ -57,7 +105,7 @@ namespace Avalonia.Controls var size = Stretch.CalculateSize(availableSize, childSize, StretchDirection); - return size.Constrain(availableSize); + return size; } return new Size(); @@ -65,31 +113,21 @@ namespace Avalonia.Controls protected override Size ArrangeOverride(Size finalSize) { - var child = Child; + var child = _containerVisual; if (child != null) { var childSize = child.DesiredSize; 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) - { - child.RenderTransform = scaleTransform = new ScaleTransform(scale.X, scale.Y); - child.RenderTransformOrigin = RelativePoint.TopLeft; - } - - scaleTransform.ScaleX = scale.X; - scaleTransform.ScaleY = scale.Y; + InternalTransform = new ScaleTransform(scale.X, scale.Y); child.Arrange(new Rect(childSize)); return childSize * scale; } - return new Size(); + return finalSize; } } } From 759227799bb2e6f38dc498ad687282bb0f4d15fd Mon Sep 17 00:00:00 2001 From: amwx <40413319+amwx@users.noreply.github.com> Date: Tue, 1 Mar 2022 22:51:17 -0500 Subject: [PATCH 2/3] Fix Unit Tests --- src/Avalonia.Controls/Viewbox.cs | 2 +- .../Avalonia.Controls.UnitTests/ViewboxTests.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs index 79e9684c67..50b9560cac 100644 --- a/src/Avalonia.Controls/Viewbox.cs +++ b/src/Avalonia.Controls/Viewbox.cs @@ -76,7 +76,7 @@ namespace Avalonia.Controls /// Gets or sets the transform applied to the container visual that /// hosts the child of the Viewbox /// - protected ITransform? InternalTransform + protected internal ITransform? InternalTransform { get => _containerVisual.RenderTransform; set => _containerVisual.RenderTransform = value; diff --git a/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs b/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs index 7eaec35506..d33e55341b 100644 --- a/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ViewboxTests.cs @@ -18,7 +18,7 @@ namespace Avalonia.Controls.UnitTests target.Arrange(new Rect(new Point(0, 0), target.DesiredSize)); Assert.Equal(new Size(200, 100), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(2.0, scaleTransform.ScaleX); @@ -36,7 +36,7 @@ namespace Avalonia.Controls.UnitTests target.Arrange(new Rect(new Point(0, 0), target.DesiredSize)); Assert.Equal(new Size(100, 50), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(1.0, scaleTransform.ScaleX); @@ -54,7 +54,7 @@ namespace Avalonia.Controls.UnitTests target.Arrange(new Rect(new Point(0, 0), target.DesiredSize)); Assert.Equal(new Size(200, 200), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(2.0, scaleTransform.ScaleX); @@ -72,7 +72,7 @@ namespace Avalonia.Controls.UnitTests target.Arrange(new Rect(new Point(0, 0), target.DesiredSize)); Assert.Equal(new Size(200, 200), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(4.0, scaleTransform.ScaleX); @@ -90,7 +90,7 @@ namespace Avalonia.Controls.UnitTests target.Arrange(new Rect(new Point(0, 0), target.DesiredSize)); Assert.Equal(new Size(400, 200), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(4.0, scaleTransform.ScaleX); @@ -108,7 +108,7 @@ namespace Avalonia.Controls.UnitTests target.Arrange(new Rect(new Point(0, 0), target.DesiredSize)); Assert.Equal(new Size(200, 100), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(2.0, scaleTransform.ScaleX); @@ -136,7 +136,7 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(expectedScale, scaleTransform.ScaleX); @@ -164,7 +164,7 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize); - var scaleTransform = target.Child.RenderTransform as ScaleTransform; + var scaleTransform = target.InternalTransform as ScaleTransform; Assert.NotNull(scaleTransform); Assert.Equal(expectedScale, scaleTransform.ScaleX); From a529ae88d59e8a8882ade3a2b9e2e281dae68988 Mon Sep 17 00:00:00 2001 From: Mike Irving Date: Wed, 9 Mar 2022 18:18:09 +0000 Subject: [PATCH 3/3] Grammatical corrections to product names: XCode -> Xcode, .Net -> .NET, Javascript -> JavaScript, MacOS -> macOS, MacOs -> macOS --- .gitignore | 2 +- build/SharedVersion.props | 2 +- native/Avalonia.Native/src/OSX/window.mm | 2 +- readme.md | 2 +- .../Remote/HtmlTransport/webapp/src/index.html | 2 +- .../Interop/Typescript/types/dotnet/index.d.ts | 2 +- tests/Avalonia.IntegrationTests.Appium/readme.md | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index d7c4cdefde..44fe5e4ba4 100644 --- a/.gitignore +++ b/.gitignore @@ -192,7 +192,7 @@ dirs.sln ################## -# XCode +# Xcode ################## Index/ Logs/ diff --git a/build/SharedVersion.props b/build/SharedVersion.props index dad40cccb7..3d9548ab9d 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -11,7 +11,7 @@ latest MIT Icon.png - Avalonia is a cross-platform UI framework for .NET providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, MacOS and with experimental support for Android, iOS and WebAssembly. + Avalonia is a cross-platform UI framework for .NET providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS and with experimental support for Android, iOS and WebAssembly. avalonia;avaloniaui;mvvm;rx;reactive extensions;android;ios;mac;forms;wpf;net;netstandard;net461;uwp;xamarin https://github.com/AvaloniaUI/Avalonia/releases git diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 1de82d9f39..9b703c4838 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -735,7 +735,7 @@ private: return E_INVALIDARG; // If one tries to show a child window with a minimized parent window, then the parent window will be - // restored but MacOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive + // restored but macOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive // state. Detect this and explicitly restore the parent window ourselves to avoid this situation. if (cparent->WindowState() == Minimized) cparent->SetWindowState(Normal); diff --git a/readme.md b/readme.md index 96c7937559..7e32dbc321 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ ## 📖 About -Avalonia is a cross-platform UI framework for dotnet, providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, MacOs. Avalonia is mature and production ready. We also have in beta release support for iOS, Android and in early stages support for browser via WASM. +Avalonia is a cross-platform UI framework for dotnet, providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS. Avalonia is mature and production ready. We also have in beta release support for iOS, Android and in early stages support for browser via WASM. ![image](https://user-images.githubusercontent.com/4672627/152126443-932966cf-57e7-4e77-9be6-62463a66b9f8.png) diff --git a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/index.html b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/index.html index f5847cdd58..cf76de0077 100644 --- a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/index.html +++ b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/src/index.html @@ -9,6 +9,6 @@
Loading...
- + diff --git a/src/Web/Avalonia.Web.Blazor/Interop/Typescript/types/dotnet/index.d.ts b/src/Web/Avalonia.Web.Blazor/Interop/Typescript/types/dotnet/index.d.ts index ff6dc4a8f8..932dfa1e1f 100644 --- a/src/Web/Avalonia.Web.Blazor/Interop/Typescript/types/dotnet/index.d.ts +++ b/src/Web/Avalonia.Web.Blazor/Interop/Typescript/types/dotnet/index.d.ts @@ -6,7 +6,7 @@ // Here be dragons! // This is community-maintained definition file intended to ease the process of developing -// high quality JavaScript interop code to be used in Blazor application from your C# .Net code. +// high quality JavaScript interop code to be used in Blazor application from your C# .NET code. // Could be removed without a notice in case official definition types ships with Blazor itself. // tslint:disable:no-unnecessary-generics diff --git a/tests/Avalonia.IntegrationTests.Appium/readme.md b/tests/Avalonia.IntegrationTests.Appium/readme.md index 2a8c3068ba..ee630a31fd 100644 --- a/tests/Avalonia.IntegrationTests.Appium/readme.md +++ b/tests/Avalonia.IntegrationTests.Appium/readme.md @@ -11,12 +11,12 @@ - Run WinAppDriver (it gets installed to the start menu) - Run the tests in this project -## MacOS +## macOS ### Prerequisites - Install Appium: https://appium.io/ -- Give [XCode helper the required permissions](https://apple.stackexchange.com/questions/334008) +- Give [Xcode helper the required permissions](https://apple.stackexchange.com/questions/334008) - `cd samples/IntegrationTestApp` then `./bundle.sh` to create an app bundle for `IntegrationTestApp` - Register the app bundle by running `open -n ./bin/Debug/net6.0/osx-arm64/publish/IntegrationTestApp.app`