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 @@
latestMITIcon.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;xamarinhttps://github.com/AvaloniaUI/Avalonia/releasesgit
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.

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..50b9560cac 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 internal 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;
}
}
}
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 @@