Browse Source

Merge pull request #439 from PixiEditor/mouse-move-limit

Mouse Move update limiting hacky fix
Krzysztof Krysiński 2 years ago
parent
commit
1ade0033b6

+ 5 - 2
src/PixiEditor/Helpers/Behaviours/MouseBehavior.cs

@@ -1,6 +1,7 @@
 using System.Windows;
 using System.Windows.Input;
 using Microsoft.Xaml.Behaviors;
+using PixiEditor.Models.Controllers;
 
 namespace PixiEditor.Helpers.Behaviours
 {
@@ -34,15 +35,17 @@ namespace PixiEditor.Helpers.Behaviours
             get => (FrameworkElement)GetValue(RelativeToProperty);
             set => SetValue(RelativeToProperty, value);
         }
+        
+        private MouseUpdateController mouseUpdateController;
 
         protected override void OnAttached()
         {
-            AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
+            mouseUpdateController = new MouseUpdateController(AssociatedObject, AssociatedObjectOnMouseMove);
         }
 
         protected override void OnDetaching()
         {
-            AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
+            mouseUpdateController.Dispose();
         }
 
         private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs)

+ 48 - 0
src/PixiEditor/Models/Controllers/MouseUpdateController.cs

@@ -0,0 +1,48 @@
+using System.Timers;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Threading;
+
+namespace PixiEditor.Models.Controllers;
+
+public class MouseUpdateController : IDisposable
+{
+    private const int MouseUpdateIntervalMs = 7;  // 7ms ~= 142 Hz
+    
+    private readonly System.Timers.Timer _timer;
+    
+    private UIElement element;
+    
+    private MouseEventHandler mouseMoveHandler;
+    
+    public MouseUpdateController(UIElement uiElement, MouseEventHandler onMouseMove)
+    {
+        mouseMoveHandler = onMouseMove;
+        element = uiElement;
+        
+        _timer = new System.Timers.Timer(MouseUpdateIntervalMs);
+        _timer.AutoReset = true;
+        _timer.Elapsed += TimerOnElapsed;
+        
+        element.MouseMove += OnMouseMove;
+    }
+
+    private void TimerOnElapsed(object sender, ElapsedEventArgs e)
+    {
+        _timer.Stop();
+        element.MouseMove += OnMouseMove;
+    }
+
+    private void OnMouseMove(object sender, MouseEventArgs e)
+    {
+        element.MouseMove -= OnMouseMove;
+        _timer.Start();
+        mouseMoveHandler(sender, e);
+    }
+
+    public void Dispose()
+    {
+        _timer.Dispose();
+        element.MouseMove -= OnMouseMove;
+    }
+}

+ 18 - 0
src/PixiEditor/Views/UserControls/Layers/FolderControl.xaml.cs

@@ -1,6 +1,7 @@
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Media;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Enums;
 using PixiEditor.ViewModels.SubViewModels.Document;
 
@@ -20,12 +21,29 @@ internal partial class FolderControl : UserControl
     public static string? FolderControlDataName = typeof(FolderControl).FullName;
     public static string? LayerControlDataName = typeof(LayerControl).FullName;
 
+    public static readonly DependencyProperty ManagerProperty = DependencyProperty.Register(
+        nameof(Manager), typeof(LayersManager), typeof(FolderControl), new PropertyMetadata(default(LayersManager)));
+
+    public LayersManager Manager
+    {
+        get { return (LayersManager)GetValue(ManagerProperty); }
+        set { SetValue(ManagerProperty, value); }
+    }
+
     private readonly Brush? highlightColor;
+    
+    private MouseUpdateController mouseUpdateController;
 
     public FolderControl()
     {
         InitializeComponent();
         highlightColor = (Brush?)App.Current.Resources["SoftSelectedLayerColor"];
+        Loaded += OnLoaded;
+    }
+
+    private void OnLoaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController = new MouseUpdateController(this, Manager.FolderControl_MouseMove);
     }
 
     private void Grid_DragEnter(object sender, DragEventArgs e)

+ 25 - 6
src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml.cs

@@ -3,6 +3,7 @@ using System.Windows.Controls;
 using System.Windows.Input;
 using System.Windows.Media;
 using PixiEditor.Helpers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Enums;
 using PixiEditor.ViewModels.SubViewModels.Document;
 
@@ -21,12 +22,6 @@ internal partial class LayerControl : UserControl
         set => SetValue(LayerProperty, value);
     }
 
-    public LayerControl()
-    {
-        InitializeComponent();
-        highlightColor = (Brush?)App.Current.Resources["SoftSelectedLayerColor"];
-    }
-
     public static readonly DependencyProperty ControlButtonsVisibleProperty = DependencyProperty.Register(
         nameof(ControlButtonsVisible), typeof(Visibility), typeof(LayerControl), new PropertyMetadata(System.Windows.Visibility.Hidden));
 
@@ -39,6 +34,15 @@ internal partial class LayerControl : UserControl
     public static readonly DependencyProperty LayerColorProperty =
         DependencyProperty.Register(nameof(LayerColor), typeof(string), typeof(LayerControl), new PropertyMetadata("#00000000"));
 
+    public static readonly DependencyProperty ManagerProperty = DependencyProperty.Register(
+        nameof(Manager), typeof(LayersManager), typeof(LayerControl), new PropertyMetadata(default(LayersManager)));
+
+    public LayersManager Manager
+    {
+        get { return (LayersManager)GetValue(ManagerProperty); }
+        set { SetValue(ManagerProperty, value); }
+    }
+    
     public Visibility ControlButtonsVisible
     {
         get { return (Visibility)GetValue(ControlButtonsVisibleProperty); }
@@ -57,6 +61,21 @@ internal partial class LayerControl : UserControl
     public static readonly DependencyProperty MoveToFrontCommandProperty = DependencyProperty.Register(
         nameof(MoveToFrontCommand), typeof(RelayCommand), typeof(LayerControl), new PropertyMetadata(default(RelayCommand)));
 
+
+    private MouseUpdateController mouseUpdateController;
+    
+    public LayerControl()
+    {
+        InitializeComponent();
+        Loaded += LayerControl_Loaded;
+        highlightColor = (Brush?)App.Current.Resources["SoftSelectedLayerColor"];
+    }
+
+    private void LayerControl_Loaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController = new MouseUpdateController(this, Manager.LayerControl_MouseMove);
+    }
+
     public RelayCommand MoveToFrontCommand
     {
         get { return (RelayCommand)GetValue(MoveToFrontCommandProperty); }

+ 2 - 2
src/PixiEditor/Views/UserControls/Layers/LayersManager.xaml

@@ -153,15 +153,15 @@
                     <HierarchicalDataTemplate DataType="{x:Type docVm:FolderViewModel}" ItemsSource="{Binding Children}">
                         <layerUserControls:FolderControl
                             Folder="{Binding}"
+                            Manager="{Binding ElementName=layersManager}"
                             MouseDown="FolderControl_MouseDown"
-                            MouseMove="FolderControl_MouseMove"
                             MouseUp="FolderControl_MouseUp"/>
                     </HierarchicalDataTemplate>
                     <DataTemplate DataType="{x:Type docVm:LayerViewModel}">
                         <layerUserControls:LayerControl
                             Layer="{Binding}"
+                            Manager="{Binding ElementName=layersManager}"
                             MouseDown="LayerControl_MouseDown"
-                            MouseMove="LayerControl_MouseMove"
                             MouseUp="LayerControl_MouseUp"/>
                     </DataTemplate>
                 </TreeView.Resources>

+ 3 - 3
src/PixiEditor/Views/UserControls/Layers/LayersManager.xaml.cs

@@ -46,7 +46,7 @@ internal partial class LayersManager : UserControl
         }
     }
     
-    private void LayerControl_MouseMove(object? sender, System.Windows.Input.MouseEventArgs? e)
+    public void LayerControl_MouseMove(object? sender, System.Windows.Input.MouseEventArgs? e)
     {
         if (e is null)
             return;
@@ -82,8 +82,8 @@ internal partial class LayersManager : UserControl
             }
         }
     }
-    
-    private void FolderControl_MouseMove(object? sender, System.Windows.Input.MouseEventArgs? e)
+
+    public void FolderControl_MouseMove(object? sender, System.Windows.Input.MouseEventArgs? e)
     {
         if (e is null)
             return;

+ 7 - 2
src/PixiEditor/Views/UserControls/Overlays/BrushShapeOverlay/BrushShapeOverlay.cs

@@ -6,6 +6,7 @@ using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.Operations;
 using PixiEditor;
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Views;
 using PixiEditor.Views.UserControls;
 using PixiEditor.Views.UserControls.Overlays.BrushShapeOverlay;
@@ -64,6 +65,8 @@ internal class BrushShapeOverlay : Control
     private Pen whitePen = new Pen(Brushes.LightGray, 1);
     private Point lastMousePos = new();
 
+    private MouseUpdateController mouseUpdateController;
+
     public BrushShapeOverlay()
     {
         Loaded += ControlLoaded;
@@ -74,14 +77,16 @@ internal class BrushShapeOverlay : Control
     {
         if (MouseEventSource is null)
             return;
-        MouseEventSource.MouseMove -= SourceMouseMove;
+        
+        mouseUpdateController.Dispose();
     }
 
     private void ControlLoaded(object sender, RoutedEventArgs e)
     {
         if (MouseEventSource is null)
             return;
-        MouseEventSource.MouseMove += SourceMouseMove;
+        
+        mouseUpdateController = new MouseUpdateController(MouseEventSource, SourceMouseMove);
     }
 
     private void SourceMouseMove(object sender, MouseEventArgs args)

+ 12 - 3
src/PixiEditor/Views/UserControls/Overlays/LineToolOverlay/LineToolOverlay.cs

@@ -4,6 +4,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Views.UserControls.Overlays.TransformOverlay;
 
 namespace PixiEditor.Views.UserControls.Overlays.LineToolOverlay;
@@ -55,9 +56,17 @@ internal class LineToolOverlay : Control
             .ConvertFrom("M 0.50025839 0 0.4248062 0.12971572 0.34987079 0.25994821 h 0.1002584 V 0.45012906 H 0.25994831 V 0.34987066 L 0.12971577 0.42480604 0 0.5002582 0.12971577 0.57519373 0.25994831 0.65012926 V 0.5498709 H 0.45012919 V 0.74005175 H 0.34987079 L 0.42480619 0.87028439 0.50025839 1 0.57519399 0.87028439 0.65012959 0.74005175 H 0.54987119 V 0.5498709 H 0.74005211 V 0.65012926 L 0.87028423 0.57519358 1 0.5002582 0.87028423 0.42480604 0.74005169 0.34987066 v 0.1002584 H 0.54987077 V 0.25994821 h 0.1002584 L 0.5751938 0.12971572 Z"),
     };
 
+    private MouseUpdateController mouseUpdateController;
+
     public LineToolOverlay()
     {
         Cursor = Cursors.Arrow;
+        Loaded += OnLoaded;
+    }
+
+    private void OnLoaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController = new MouseUpdateController(this, MouseMoved);
     }
 
     private static void OnZoomboxScaleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
@@ -108,10 +117,10 @@ internal class LineToolOverlay : Control
         CaptureMouse();
     }
 
-    protected override void OnMouseMove(MouseEventArgs e)
+    protected void MouseMoved(object sender, MouseEventArgs e)
     {
-        base.OnMouseMove(e);
-        e.Handled = true;
+        /*base.OnMouseMove(e);
+        e.Handled = true;*/
 
         VecD pos = TransformHelper.ToVecD(e.GetPosition(this));
         if (capturedAnchor == LineToolOverlayAnchor.Start)

+ 15 - 2
src/PixiEditor/Views/UserControls/Overlays/SymmetryOverlay/SymmetryOverlay.cs

@@ -7,6 +7,7 @@ using ChunkyImageLib.DataHolders;
 using PixiEditor;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Views;
 using PixiEditor.Views.UserControls;
 using PixiEditor.Views.UserControls.Overlays.SymmetryOverlay;
@@ -116,6 +117,18 @@ internal class SymmetryOverlay : Control
     private int horizontalAxisY;
     private int verticalAxisX;
 
+    private MouseUpdateController mouseUpdateController;
+
+    public SymmetryOverlay()
+    {
+        Loaded += OnLoaded;
+    }
+
+    private void OnLoaded(object sender, RoutedEventArgs e)
+    {
+        mouseUpdateController = new MouseUpdateController(this, MouseMoved);
+    }
+
     protected override void OnRender(DrawingContext drawingContext)
     {
         base.OnRender(drawingContext);
@@ -358,9 +371,9 @@ internal class SymmetryOverlay : Control
         e.Handled = true;
     }
 
-    protected override void OnMouseMove(MouseEventArgs e)
+    protected void MouseMoved(object sender, MouseEventArgs e)
     {
-        base.OnMouseMove(e);
+        /*base.OnMouseMove(e);*/
 
         var pos = ToVecD(e.GetPosition(this));
         UpdateHovered(IsTouchingHandle(pos));

+ 6 - 2
src/PixiEditor/Views/UserControls/PreviewWindow.xaml.cs

@@ -4,6 +4,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using BackendColor = PixiEditor.DrawingApi.Core.ColorsImpl.Color;
 using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.Models.Controllers;
 using PixiEditor.ViewModels.SubViewModels.Document;
 using PixiEditor.Models.Enums;
 
@@ -46,12 +47,15 @@ internal partial class PreviewWindow : UserControl
         get => (Color)GetValue(PrimaryColorProperty);
         set => SetValue(PrimaryColorProperty, value);
     }
+    
+    private MouseUpdateController mouseUpdateController;
 
     public PreviewWindow()
     {
         InitializeComponent();
-
-        imageGrid.MouseMove += ImageGrid_MouseMove;
+        
+        mouseUpdateController = new MouseUpdateController(imageGrid, ImageGrid_MouseMove);
+        
         imageGrid.MouseRightButtonDown += ImageGrid_MouseRightButtonDown;
         imageGrid.MouseEnter += ImageGrid_MouseEnter;
         imageGrid.MouseLeave += ImageGrid_MouseLeave;

+ 0 - 1
src/PixiEditor/Views/UserControls/Viewport.xaml

@@ -27,7 +27,6 @@
     <Grid 
         x:Name="mainGrid"
         MouseDown="Image_MouseDown"
-        MouseMove="Image_MouseMove"
         MouseUp="Image_MouseUp"
         PreviewMouseDown="Grid_PreviewMouseDown">
         <i:Interaction.Triggers>

+ 5 - 0
src/PixiEditor/Views/UserControls/Viewport.xaml.cs

@@ -7,6 +7,7 @@ using System.Windows.Media.Imaging;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Helpers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Events;
 using PixiEditor.Models.Position;
 using PixiEditor.ViewModels.SubViewModels.Document;
@@ -282,6 +283,8 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
 
     public Guid GuidValue { get; } = Guid.NewGuid();
 
+    private MouseUpdateController mouseUpdateController;
+
     public Viewport()
     {
         InitializeComponent();
@@ -292,6 +295,8 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         MainImage!.Loaded += OnImageLoaded;
         Loaded += OnLoad;
         Unloaded += OnUnload;
+        
+        mouseUpdateController = new MouseUpdateController(this, Image_MouseMove);
     }
 
     public Image? MainImage => (Image?)((Grid?)((Border?)zoombox.AdditionalContent)?.Child)?.Children[1];