csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
3.7 KiB
124 lines
3.7 KiB
using System;
|
|
using Avalonia.Media;
|
|
|
|
namespace Avalonia.Controls
|
|
{
|
|
/// <summary>
|
|
/// Viewbox is used to scale single child.
|
|
/// </summary>
|
|
/// <seealso cref="Avalonia.Controls.Decorator" />
|
|
public class Viewbox : Decorator
|
|
{
|
|
/// <summary>
|
|
/// The stretch property
|
|
/// </summary>
|
|
public static AvaloniaProperty<Stretch> StretchProperty =
|
|
AvaloniaProperty.RegisterDirect<Viewbox, Stretch>(nameof(Stretch),
|
|
v => v.Stretch, (c, v) => c.Stretch = v, Stretch.Uniform);
|
|
|
|
private Stretch _stretch = Stretch.Uniform;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the stretch mode,
|
|
/// which determines how child fits into the available space.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The stretch.
|
|
/// </value>
|
|
public Stretch Stretch
|
|
{
|
|
get => _stretch;
|
|
set => SetAndRaise(StretchProperty, ref _stretch, value);
|
|
}
|
|
|
|
static Viewbox()
|
|
{
|
|
ClipToBoundsProperty.OverrideDefaultValue<Viewbox>(true);
|
|
AffectsMeasure<Viewbox>(StretchProperty);
|
|
}
|
|
|
|
protected override Size MeasureOverride(Size availableSize)
|
|
{
|
|
var child = Child;
|
|
|
|
if (child != null)
|
|
{
|
|
child.Measure(Size.Infinity);
|
|
|
|
var childSize = child.DesiredSize;
|
|
|
|
var scale = GetScale(availableSize, childSize, Stretch);
|
|
|
|
return childSize * scale;
|
|
}
|
|
|
|
return new Size();
|
|
}
|
|
|
|
protected override Size ArrangeOverride(Size finalSize)
|
|
{
|
|
var child = Child;
|
|
|
|
if (child != null)
|
|
{
|
|
var childSize = child.DesiredSize;
|
|
var scale = GetScale(finalSize, childSize, Stretch);
|
|
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;
|
|
|
|
child.Arrange(new Rect(childSize));
|
|
|
|
return childSize * scale;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|