JT
1 year ago
6 changed files with 245 additions and 43 deletions
@ -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 |
||||
{ |
||||
/// <summary> |
||||
/// Defines the <see cref="Source"/> property. |
||||
/// </summary> |
||||
public static readonly StyledProperty<IImage?> SourceProperty = |
||||
AvaloniaProperty.Register<BetterImage, IImage?>(nameof(Source)); |
||||
|
||||
/// <summary> |
||||
/// Defines the <see cref="Stretch"/> property. |
||||
/// </summary> |
||||
public static readonly StyledProperty<Stretch> StretchProperty = |
||||
AvaloniaProperty.Register<BetterImage, Stretch>(nameof(Stretch), Stretch.Uniform); |
||||
|
||||
/// <summary> |
||||
/// Defines the <see cref="StretchDirection"/> property. |
||||
/// </summary> |
||||
public static readonly StyledProperty<StretchDirection> StretchDirectionProperty = |
||||
AvaloniaProperty.Register<BetterImage, StretchDirection>( |
||||
nameof(StretchDirection), |
||||
StretchDirection.Both); |
||||
|
||||
static BetterImage() |
||||
{ |
||||
AffectsRender<BetterImage>(SourceProperty, StretchProperty, StretchDirectionProperty); |
||||
AffectsMeasure<BetterImage>(SourceProperty, StretchProperty, StretchDirectionProperty); |
||||
AutomationProperties.ControlTypeOverrideProperty.OverrideDefaultValue<BetterImage>( |
||||
AutomationControlType.Image); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Gets or sets the image that will be displayed. |
||||
/// </summary> |
||||
[Content] |
||||
public IImage? Source |
||||
{ |
||||
get { return GetValue(SourceProperty); } |
||||
set { SetValue(SourceProperty, value); } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Gets or sets a value controlling how the image will be stretched. |
||||
/// </summary> |
||||
public Stretch Stretch |
||||
{ |
||||
get { return GetValue(StretchProperty); } |
||||
set { SetValue(StretchProperty, value); } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Gets or sets a value controlling in what direction the image will be stretched. |
||||
/// </summary> |
||||
public StretchDirection StretchDirection |
||||
{ |
||||
get { return GetValue(StretchDirectionProperty); } |
||||
set { SetValue(StretchDirectionProperty, value); } |
||||
} |
||||
|
||||
/// <inheritdoc /> |
||||
protected override bool BypassFlowDirectionPolicies => true; |
||||
|
||||
/// <summary> |
||||
/// Renders the control. |
||||
/// </summary> |
||||
/// <param name="context">The drawing context.</param> |
||||
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); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Measures the control. |
||||
/// </summary> |
||||
/// <param name="availableSize">The available size.</param> |
||||
/// <returns>The desired size of the control.</returns> |
||||
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; |
||||
} |
||||
|
||||
/// <inheritdoc/> |
||||
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); |
||||
} |
||||
} |
Loading…
Reference in new issue