Prechádzať zdrojové kódy

Implement drag to zoom

Equbuxu 4 rokov pred
rodič
commit
dcad54b28f
1 zmenil súbory, kde vykonal 124 pridanie a 42 odobranie
  1. 124 42
      PixiEditor/Views/UserControls/ZoomBox.xaml.cs

+ 124 - 42
PixiEditor/Views/UserControls/ZoomBox.xaml.cs

@@ -5,87 +5,169 @@ using System.Windows.Input;
 
 namespace PixiEditor.Views.UserControls
 {
-    /// <summary>
-    /// Interaction logic for ZoomBox.xaml
-    /// </summary>
     public partial class ZoomBox : ContentControl
     {
-        private bool captured = false;
-        private Point prevMousePos;
+        public enum Mode
+        {
+            Normal, Move, Zoom
+        }
+
+        private interface IDragOperation
+        {
+            void Start(MouseButtonEventArgs e);
+
+            void Update(MouseEventArgs e);
+
+            void Terminate();
+        }
+
+        private class MoveDragOperation : IDragOperation
+        {
+            private ZoomBox parent;
+            private Point prevMousePos;
+
+            public MoveDragOperation(ZoomBox zoomBox)
+            {
+                parent = zoomBox;
+            }
+            public void Start(MouseButtonEventArgs e)
+            {
+                prevMousePos = e.GetPosition(parent.mainCanvas);
+                parent.mainCanvas.CaptureMouse();
+            }
+
+            public void Update(MouseEventArgs e)
+            {
+                var curMousePos = e.GetPosition(parent.mainCanvas);
+                parent.SpaceOriginPos += curMousePos - prevMousePos;
+                prevMousePos = e.GetPosition(parent.mainCanvas);
+            }
+
+            public void Terminate()
+            {
+                parent.mainCanvas.ReleaseMouseCapture();
+            }
+        }
+
+        private class ZoomDragOperation : IDragOperation
+        {
+            private ZoomBox parent;
+
+            private int initZoomPower;
+            private Point initSpaceOriginPos;
+
+            private Point zoomOrigin;
+            private Point screenZoomOrigin;
+
+            public ZoomDragOperation(ZoomBox zoomBox)
+            {
+                parent = zoomBox;
+            }
+            public void Start(MouseButtonEventArgs e)
+            {
+                screenZoomOrigin = e.GetPosition(parent.mainCanvas);
+                zoomOrigin = parent.ToZoomboxSpace(screenZoomOrigin);
+                initZoomPower = parent.ZoomPower;
+                initSpaceOriginPos = parent.SpaceOriginPos;
+                parent.mainCanvas.CaptureMouse();
+            }
 
-        private Point backingSpaceOriginPos;
+            public void Update(MouseEventArgs e)
+            {
+                var curScreenPos = e.GetPosition(parent.mainCanvas);
+                double deltaX = screenZoomOrigin.X - curScreenPos.X;
+                int deltaPower = (int)(deltaX / 10.0);
+                parent.ZoomPower = initZoomPower - deltaPower;
+
+                parent.SpaceOriginPos = initSpaceOriginPos;
+                var shiftedOriginPos = parent.ToScreenSpace(zoomOrigin);
+                var deltaOriginPos = shiftedOriginPos - screenZoomOrigin;
+                parent.SpaceOriginPos = initSpaceOriginPos - deltaOriginPos;
+            }
+
+            public void Terminate()
+            {
+                parent.mainCanvas.ReleaseMouseCapture();
+            }
+        }
+
+        private Point spaceOriginPos;
         private Point SpaceOriginPos
         {
-            get => backingSpaceOriginPos;
+            get => spaceOriginPos;
             set
             {
-                backingSpaceOriginPos = value;
-                Canvas.SetLeft(mainGrid, backingSpaceOriginPos.X);
-                Canvas.SetTop(mainGrid, backingSpaceOriginPos.Y);
+                spaceOriginPos = value;
+                Canvas.SetLeft(mainGrid, spaceOriginPos.X);
+                Canvas.SetTop(mainGrid, spaceOriginPos.Y);
             }
         }
 
-        private int backingZoomPower;
+        private int zoomPower;
         private int ZoomPower
         {
-            get => backingZoomPower;
+            get => zoomPower;
             set
             {
-                backingZoomPower = value;
+                zoomPower = value;
                 var mult = Zoom;
                 scaleTransform.ScaleX = mult;
                 scaleTransform.ScaleY = mult;
             }
         }
-        private double Zoom => Math.Pow(1.1, backingZoomPower);
+        private double Zoom => Math.Pow(1.1, zoomPower);
+        private Mode mode;
+
+        private IDragOperation activeDragOperation = null;
 
         public ZoomBox()
         {
             InitializeComponent();
+            mode = Mode.Zoom;
         }
 
-        private void OnMouseDown(object sender, MouseButtonEventArgs e)
+        private Point ToScreenSpace(Point p)
         {
-            mainCanvas.CaptureMouse();
-            captured = true;
-            prevMousePos = e.GetPosition(mainCanvas);
+            double zoom = Zoom;
+            p.X *= zoom;
+            p.Y *= zoom;
+            p += (Vector)SpaceOriginPos;
+            return p;
         }
 
-        private void OnMouseUp(object sender, MouseButtonEventArgs e)
+        private Point ToZoomboxSpace(Point mousePos)
         {
-            mainCanvas.ReleaseMouseCapture();
-            captured = false;
-            prevMousePos = e.GetPosition(mainCanvas);
+            double zoom = Zoom;
+            mousePos -= (Vector)SpaceOriginPos;
+            mousePos.X /= zoom;
+            mousePos.Y /= zoom;
+            return mousePos;
         }
 
-        private void OnMouseMove(object sender, MouseEventArgs e)
+        private void OnMouseDown(object sender, MouseButtonEventArgs e)
         {
-            if (!captured)
+            if (mode == Mode.Normal)
                 return;
-            var curMousePos = e.GetPosition(mainCanvas);
-            SpaceOriginPos += curMousePos - prevMousePos;
 
-            prevMousePos = e.GetPosition(mainCanvas);
+            activeDragOperation?.Terminate();
+
+            if (mode == Mode.Move)
+                activeDragOperation = new MoveDragOperation(this);
+            else if (mode == Mode.Zoom)
+                activeDragOperation = new ZoomDragOperation(this);
+
+            activeDragOperation.Start(e);
         }
 
-        private Point ToScreenSpace(Point p)
+        private void OnMouseUp(object sender, MouseButtonEventArgs e)
         {
-            double zoom = Zoom;
-            p.X /= zoom;
-            p.Y /= zoom;
-            p.X += SpaceOriginPos.X;
-            p.Y += SpaceOriginPos.Y;
-            return p;
+            activeDragOperation?.Terminate();
+            activeDragOperation = null;
         }
 
-        private Point ToZoomboxSpace(Point mousePos)
+        private void OnMouseMove(object sender, MouseEventArgs e)
         {
-            double zoom = Zoom;
-            mousePos.X -= SpaceOriginPos.X;
-            mousePos.Y -= SpaceOriginPos.Y;
-            mousePos.X *= zoom;
-            mousePos.Y *= zoom;
-            return mousePos;
+            activeDragOperation?.Update(e);
         }
 
         private void OnScroll(object sender, MouseWheelEventArgs e)
@@ -97,7 +179,7 @@ namespace PixiEditor.Views.UserControls
 
             var shiftedMousePos = ToScreenSpace(oldZoomboxMousePos);
             var deltaMousePos = oldMousePos - shiftedMousePos;
-            SpaceOriginPos = SpaceOriginPos - deltaMousePos;
+            SpaceOriginPos = SpaceOriginPos + deltaMousePos;
         }
     }
 }