using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Metadata;
using System;
namespace InABox.Avalonia.Components;
///
/// Presents a control within a panel in which to zoom in and out and pan. The must be a ,
/// and its and must be set.
///
[TemplatePart("PART_ZoomContent", typeof(ContentControl))]
[TemplatePart("PART_ZoomCanvas", typeof(Canvas))]
[TemplatePart("PART_ZoomContentBorder", typeof(Border))]
public partial class ZoomPanel : TemplatedControl
{
public static readonly StyledProperty ContentProperty =
AvaloniaProperty.Register(nameof(Content));
[Content]
public Layoutable? Content
{
get => GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
private double ContentWidth => Content?.Width ?? 1;
private double ContentHeight => Content?.Height ?? 1;
private Canvas OuterCanvas = null!;
private ContentControl ZoomContent = null!;
private Border ZoomContentBorder = null!;
private double ScaleFactor = 1.0;
private double _originalScaleFactor = 1.0;
private const double _wheelSpeed = 0.1;
private const double _panSpeed = 30;
// Center of the image.
private Point ContentCentre = new();
public ZoomPanel()
{
this.GetPropertyChangedObservable(ContentProperty).Subscribe(ContentChanged);
}
private void ContentChanged(AvaloniaPropertyChangedEventArgs args)
{
if(Content is null) return;
void Update(AvaloniaPropertyChangedEventArgs? args = null)
{
if(OuterCanvas is not null)
{
PositionContent();
}
}
Update();
Content.GetPropertyChangedObservable(Layoutable.WidthProperty).Subscribe(Update);
Content.GetPropertyChangedObservable(Layoutable.HeightProperty).Subscribe(Update);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
OuterCanvas = e.NameScope.Get