Browse Source

avalonia: Made DocumentViewer into a ZoomPanel to reduce code repetition

Kenric Nugteren 2 months ago
parent
commit
cc0579b3c8

+ 4 - 6
PRS.Avalonia/PRS.Avalonia/Components/DocumentList/DocumentViewer.axaml

@@ -11,12 +11,10 @@
 			<RowDefinition Height="*"/>
 			<RowDefinition Height="Auto"/>
 		</Grid.RowDefinitions>
-		<Canvas Name="OuterCanvas" Grid.Row="0" Background="Transparent">
-			<Canvas.GestureRecognizers>
-				<iComponents:PanAndZoomGestureRecognizer/>
-			</Canvas.GestureRecognizers>
-			<Image Name="Image"/>
-		</Canvas>
+		<iComponents:ZoomPanel Grid.Row="0">
+			<Image Name="Image"
+				   Stretch="UniformToFill"/>
+		</iComponents:ZoomPanel>
 		<Label Name="NoImage" Grid.Row="0"
 			   Content="No Image Available"
 			   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

+ 10 - 103
PRS.Avalonia/PRS.Avalonia/Components/DocumentList/DocumentViewer.axaml.cs

@@ -1,6 +1,7 @@
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Input;
+using Avalonia.Interactivity;
 using Avalonia.Markup.Xaml;
 using Avalonia.Media;
 using DynamicData.Binding;
@@ -34,15 +35,7 @@ public partial class DocumentViewer : UserControl
         set => SetValue(DataProperty, value);
     }
 
-    private double ScaleFactor = 1.0;
-    private double _originalScaleFactor = 1.0;
-    private double _startScaleFactor = 1.0;
-
-    // Center of the image.
-    private Point ImageCenter = new();
     private IImage? _image;
-    private double ImageWidth => _image?.Size.Width ?? 0;
-    private double ImageHeight => _image?.Size.Height ?? 0;
 
     public DocumentViewer()
     {
@@ -50,101 +43,15 @@ public partial class DocumentViewer : UserControl
 
         this.GetPropertyChangedObservable(FileNameProperty).Subscribe(x => Update().ContinueWith(ContinueTask));
         this.GetPropertyChangedObservable(DataProperty).Subscribe(x => Update().ContinueWith(ContinueTask));
-
-        OuterCanvas.AddHandler(PanAndZoomGestureRecognizer.PanAndZoomEndedEvent, ImageContainer_PinchEnded);
-        OuterCanvas.AddHandler(PanAndZoomGestureRecognizer.PanAndZoomEvent, ImageContainer_Pinch);
-
-        OuterCanvas.PointerWheelChanged += OuterCanvas_PointerWheelChanged;
-    }
-
-    private const double _wheelSpeed = 0.1;
-    private const double _panSpeed = 30;
-
-    private void Pan(double x, double y)
-    {
-        ImageCenter += 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
+        
+        Image.GetPropertyChangedObservable(Image.SourceProperty).Subscribe(x =>
         {
-            Pan(e.Delta.X * _panSpeed, e.Delta.Y * _panSpeed);
-        }
-    }
-
-    private void ImageContainer_Pinch(object? sender, PanAndZoomEventArgs e)
-    {
-        Zoom(e.ScaleOrigin - e.Pan, e.ScaleOrigin, _originalScaleFactor * e.Scale);
-    }
-
-    private void ImageContainer_PinchEnded(object? sender, PanAndZoomEndedEventArgs e)
-    {
-        _originalScaleFactor = ScaleFactor;
-    }
-
-    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 - ImageCenter;
-        var contentMPos = pos / ScaleFactor;
-
-        ScaleFactor = Math.Max(_startScaleFactor, newScaleFactor);
-
-        var scaledPos = ImageCenter + contentMPos * ScaleFactor;
-        var offset = scaledPos - newOrigin;
-
-        ImageCenter -= offset;
-
-        UpdateCanvasPosition();
-    }
-
-    private void PositionImage()
-    {
-        if (ImageWidth == 0 || ImageHeight == 0) return;
-
-        var canvasWidth = OuterCanvas.Bounds.Width;
-        var canvasHeight = OuterCanvas.Bounds.Height;
-
-        var scaleFactor = Math.Min(canvasWidth / ImageWidth, canvasHeight / ImageHeight);
-        ScaleFactor = scaleFactor;
-        _originalScaleFactor = ScaleFactor;
-        _startScaleFactor = ScaleFactor;
-
-        ImageCenter = new Point(
-            OuterCanvas.Bounds.Width / 2,
-            OuterCanvas.Bounds.Height / 2);
-
-        UpdateCanvasPosition();
-    }
-
-    private void UpdateCanvasPosition()
-    {
-        var imageWidth = ImageWidth * ScaleFactor;
-        var imageHeight = ImageHeight * ScaleFactor;
-
-        Image.Width = imageWidth;
-        Image.Height = imageHeight;
-
-        Canvas.SetLeft(Image, ImageCenter.X - imageWidth / 2);
-        Canvas.SetTop(Image, ImageCenter.Y - imageHeight / 2);
-
-        // OuterCanvas.Width = ImageWidth;
-        // OuterCanvas.Height = ImageHeight;
+            if (Image.Source is not null)
+            {
+                Image.Width = Image.Source.Size.Width;
+                Image.Height = Image.Source.Size.Height;
+            }
+        });
     }
 
     private void ContinueTask(Task task)
@@ -172,7 +79,7 @@ public partial class DocumentViewer : UserControl
             {
                 _image = ByteArrayToImageSourceConverter.Instance.Convert(bitmap);
                 Image.Source = _image;
-                PositionImage();
+                // PositionImage();
                 Image.IsVisible = true;
                 NoImage.IsVisible = false;
                 return;

+ 1 - 1
PRS.Avalonia/PRS.Avalonia/Modules/DocumentScanner/DocumentScannerEditorViewModel.cs

@@ -68,7 +68,7 @@ internal partial class DocumentScannerEditorViewModel : ModuleViewModel
             Document.Data = imgData;
             Document.CRC = CoreUtils.CalculateCRC(imgData);
             Document.TimeStamp = DateTime.Now;
-            await Document.SaveAsync("Updated from Mobile Device");
+            await DocumentModel!.SaveAsync("Updated from Mobile Device");
 
             DataEntryDocument.Thumbnail = PlatformTools.ImageTools.CreateThumbnail(imgData, 256, 256);
         }