using Avalonia; using Avalonia.Automation; using Avalonia.Automation.Peers; using Avalonia.Controls; using Avalonia.Controls.Automation.Peers; using Avalonia.Media; using Avalonia.Metadata; namespace StabilityMatrix.Avalonia.Controls; public class BetterImage : Control { /// /// Defines the property. /// public static readonly StyledProperty SourceProperty = AvaloniaProperty.Register(nameof(Source)); /// /// Defines the property. /// public static readonly StyledProperty StretchProperty = AvaloniaProperty.Register(nameof(Stretch), Stretch.Uniform); /// /// Defines the property. /// public static readonly StyledProperty StretchDirectionProperty = AvaloniaProperty.Register( nameof(StretchDirection), StretchDirection.Both); static BetterImage() { AffectsRender(SourceProperty, StretchProperty, StretchDirectionProperty); AffectsMeasure(SourceProperty, StretchProperty, StretchDirectionProperty); AutomationProperties.ControlTypeOverrideProperty.OverrideDefaultValue( AutomationControlType.Image); } /// /// Gets or sets the image that will be displayed. /// [Content] public IImage? Source { get { return GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } /// /// Gets or sets a value controlling how the image will be stretched. /// public Stretch Stretch { get { return GetValue(StretchProperty); } set { SetValue(StretchProperty, value); } } /// /// Gets or sets a value controlling in what direction the image will be stretched. /// public StretchDirection StretchDirection { get { return GetValue(StretchDirectionProperty); } set { SetValue(StretchDirectionProperty, value); } } /// protected override bool BypassFlowDirectionPolicies => true; /// /// Renders the control. /// /// The drawing context. public sealed override void Render(DrawingContext context) { var source = Source; if (source != null && Bounds.Width > 0 && Bounds.Height > 0) { Rect viewPort = new Rect(Bounds.Size); Size sourceSize = source.Size; Vector scale = Stretch.CalculateScaling(Bounds.Size, sourceSize, StretchDirection); Size scaledSize = sourceSize * scale; Rect destRect = viewPort .CenterRect(new Rect(scaledSize)) .WithX(0) .WithY(0) .Intersect(viewPort); Rect sourceRect = new Rect(sourceSize) .CenterRect(new Rect(destRect.Size / scale)) .WithX(0) .WithY(0); context.DrawImage(source, sourceRect, destRect); } } /// /// Measures the control. /// /// The available size. /// The desired size of the control. protected override Size MeasureOverride(Size availableSize) { var source = Source; var result = new Size(); if (source != null) { result = Stretch.CalculateSize(availableSize, source.Size, StretchDirection); } return result; } /// protected override Size ArrangeOverride(Size finalSize) { var source = Source; if (source != null) { var sourceSize = source.Size; var result = Stretch.CalculateSize(finalSize, sourceSize); return result; } else { return new Size(); } } protected override AutomationPeer OnCreateAutomationPeer() { return new ImageAutomationPeer(this); } }