Browse Source

Merge pull request #7735 from amwx/ViewboxFix

Updates to Viewbox
pull/7783/head
Jumar Macato 5 years ago
committed by GitHub
parent
commit
90279d80fc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/Avalonia.Controls/ApiCompatBaseline.txt
  2. 72
      src/Avalonia.Controls/Viewbox.cs
  3. 16
      tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

3
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<System.Boolean> Avalonia.StyledProperty<System.Boolean> 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<Avalonia.Controls.ResourcesChangedEventArgs>' 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.Media.Stretch> Avalonia.AvaloniaProperty<Avalonia.Media.Stretch> 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<Avalonia.Controls.ResourcesChangedEventArgs>' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.WindowBase' does not implement interface 'Avalonia.Utilities.IWeakSubscriber<Avalonia.Controls.ResourcesChangedEventArgs>' 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

72
src/Avalonia.Controls/Viewbox.cs

@ -1,13 +1,15 @@
using Avalonia.Media;
using Avalonia.Metadata;
namespace Avalonia.Controls
{
/// <summary>
/// Viewbox is used to scale single child to fit in the available space.
/// </summary>
/// <seealso cref="Avalonia.Controls.Decorator" />
public class Viewbox : Decorator
public class Viewbox : Control
{
private Decorator _containerVisual;
/// <summary>
/// Defines the <see cref="Stretch"/> property.
/// </summary>
@ -20,12 +22,27 @@ namespace Avalonia.Controls
public static readonly StyledProperty<StretchDirection> StretchDirectionProperty =
AvaloniaProperty.Register<Viewbox, StretchDirection>(nameof(StretchDirection), StretchDirection.Both);
/// <summary>
/// Defines the <see cref="Child"/> property
/// </summary>
public static readonly StyledProperty<IControl?> ChildProperty =
Decorator.ChildProperty.AddOwner<Viewbox>();
static Viewbox()
{
ClipToBoundsProperty.OverrideDefaultValue<Viewbox>(true);
UseLayoutRoundingProperty.OverrideDefaultValue<Viewbox>(true);
AffectsMeasure<Viewbox>(StretchProperty, StretchDirectionProperty);
}
public Viewbox()
{
_containerVisual = new Decorator();
_containerVisual.RenderTransformOrigin = RelativePoint.TopLeft;
LogicalChildren.Add(_containerVisual);
VisualChildren.Add(_containerVisual);
}
/// <summary>
/// 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);
}
/// <summary>
/// Gets or sets the child of the Viewbox
/// </summary>
[Content]
public IControl? Child
{
get => GetValue(ChildProperty);
set => SetValue(ChildProperty, value);
}
/// <summary>
/// Gets or sets the transform applied to the container visual that
/// hosts the child of the Viewbox
/// </summary>
protected internal ITransform? InternalTransform
{
get => _containerVisual.RenderTransform;
set => _containerVisual.RenderTransform = value;
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
if (change.Property == ChildProperty)
{
_containerVisual.Child = change.NewValue.GetValueOrDefault<IControl>();
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;
}
}
}

16
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);

Loading…
Cancel
Save