| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 | 
							- 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;
 
- namespace InABox.Avalonia.Components;
 
- [TemplatePart("PART_ZoomContent", typeof(ContentControl))]
 
- [TemplatePart("PART_ZoomCanvas", typeof(Canvas))]
 
- [TemplatePart("PART_ZoomContentBorder", typeof(Border))]
 
- public partial class ZoomPanel : TemplatedControl
 
- {
 
-     public static readonly StyledProperty<Layoutable?> ContentProperty =
 
-         AvaloniaProperty.Register<ZoomPanel, Layoutable?>(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();
 
-     protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
 
-     {
 
-         base.OnApplyTemplate(e);
 
-         OuterCanvas = e.NameScope.Get<Canvas>("PART_ZoomCanvas");
 
-         ZoomContent = e.NameScope.Get<ContentControl>("PART_ZoomContent");
 
-         ZoomContentBorder = e.NameScope.Get<Border>("PART_ZoomContentBorder");
 
-         OuterCanvas.LayoutUpdated += OuterCanvas_LayoutUpdated;
 
-         OuterCanvas.AddHandler(PanAndZoomGestureRecognizer.PanAndZoomEndedEvent, OuterCanvas_PinchEnded);
 
-         OuterCanvas.AddHandler(PanAndZoomGestureRecognizer.PanAndZoomEvent, OuterCanvas_Pinch);
 
-         OuterCanvas.PointerWheelChanged += OuterCanvas_PointerWheelChanged;
 
-     }
 
-     private void OuterCanvas_PinchEnded(object? sender, PanAndZoomEndedEventArgs e)
 
-     {
 
-         _originalScaleFactor = ScaleFactor;
 
-     }
 
-     private void OuterCanvas_Pinch(object? sender, PanAndZoomEventArgs e)
 
-     {
 
-         Zoom(e.ScaleOrigin - e.Pan, e.ScaleOrigin, _originalScaleFactor * e.Scale);
 
-     }
 
-     private void Zoom(Point originalOrigin, Point newOrigin, double newScaleFactor)
 
-     {
 
-         // Convert Scale Origin to image coordinates (relative to center).
 
-         // Work out where this position will move to under the new scaling.
 
-         // Adjust so that these are the same.
 
-         var pos = originalOrigin - ContentCentre;
 
-         var contentMPos = pos / ScaleFactor;
 
-         ScaleFactor = newScaleFactor;
 
-         var scaledPos = ContentCentre + contentMPos * ScaleFactor;
 
-         var offset = scaledPos - newOrigin;
 
-         ContentCentre -= offset;
 
-         UpdateCanvasPosition();
 
-     }
 
-     private void Pan(double x, double y)
 
-     {
 
-         ContentCentre += new Vector(x, y);
 
-         UpdateCanvasPosition();
 
-     }
 
-     private void OuterCanvas_PointerWheelChanged(object? sender, PointerWheelEventArgs e)
 
-     {
 
-         if (e.KeyModifiers.HasFlag(KeyModifiers.Control))
 
-         {
 
-             var pos = e.GetPosition(OuterCanvas);
 
-             var wheelSpeed = _wheelSpeed;
 
-             Zoom(pos, pos, e.Delta.Y > 0 ? ScaleFactor * (1 + e.Delta.Y * wheelSpeed) : ScaleFactor / (1 + (-e.Delta.Y) * wheelSpeed));
 
-         }
 
-         else if(e.KeyModifiers.HasFlag(KeyModifiers.Shift))
 
-         {
 
-             Pan(e.Delta.Y * _panSpeed, e.Delta.X * _panSpeed);
 
-         }
 
-         else
 
-         {
 
-             Pan(e.Delta.X * _panSpeed, e.Delta.Y * _panSpeed);
 
-         }
 
-     }
 
-     private void OuterCanvas_LayoutUpdated(object? sender, EventArgs e)
 
-     {
 
-         // PositionImage();
 
-     }
 
-     protected override void OnLoaded(RoutedEventArgs e)
 
-     {
 
-         base.OnLoaded(e);
 
-         PositionContent();
 
-     }
 
-     private void PositionContent()
 
-     {
 
-         var canvasWidth = OuterCanvas.Bounds.Width;
 
-         var canvasHeight = OuterCanvas.Bounds.Height;
 
-         var scaleFactor = Math.Min(canvasWidth / ContentWidth, canvasHeight / ContentHeight);
 
-         ScaleFactor = scaleFactor;
 
-         _originalScaleFactor = ScaleFactor;
 
-         ContentCentre = new Point(
 
-             OuterCanvas.Bounds.Width / 2,
 
-             OuterCanvas.Bounds.Height / 2);
 
-         UpdateCanvasPosition();
 
-     }
 
-     private void UpdateCanvasPosition()
 
-     {
 
-         var imageWidth = ContentWidth * ScaleFactor;
 
-         var imageHeight = ContentHeight * ScaleFactor;
 
-         ZoomContentBorder.Width = imageWidth;
 
-         ZoomContentBorder.Height = imageHeight;
 
-         Canvas.SetLeft(ZoomContentBorder, ContentCentre.X - imageWidth / 2);
 
-         Canvas.SetTop(ZoomContentBorder, ContentCentre.Y - imageHeight / 2);
 
-         ZoomContent.RenderTransform = new ScaleTransform(ScaleFactor, ScaleFactor);
 
-         ZoomContent.Width = ContentWidth;
 
-         ZoomContent.Height = ContentHeight;
 
-     }
 
- }
 
 
  |