diff --git a/StabilityMatrix.Avalonia/Controls/BetterImage.cs b/StabilityMatrix.Avalonia/Controls/BetterImage.cs new file mode 100644 index 00000000..8eb77eee --- /dev/null +++ b/StabilityMatrix.Avalonia/Controls/BetterImage.cs @@ -0,0 +1,140 @@ +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); + } +} diff --git a/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml b/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml index c8347362..a0aa7133 100644 --- a/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml +++ b/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml @@ -6,7 +6,8 @@ @@ -195,21 +199,21 @@ - - - - - - - + + + + + + + +