Browse Source

Tool fully implemented

flabbet 4 years ago
parent
commit
db3373f2f5

+ 9 - 4
PixiEditor/Helpers/GlobalMouseHook.cs

@@ -4,6 +4,7 @@ using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
 using System.Windows;
+using System.Windows.Input;
 
 namespace PixiEditor.Helpers
 {
@@ -32,7 +33,7 @@ namespace PixiEditor.Helpers
 
         public static void RaiseMouseUp()
         {
-            MouseUp?.Invoke(default, default);
+            MouseUp?.Invoke(default, default, default);
         }
 
         private static void Unsubscribe()
@@ -73,11 +74,13 @@ namespace PixiEditor.Helpers
             if (nCode >= 0)
             {
                 MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
-                if (wParam == WM_LBUTTONUP)
+                if (wParam == WM_LBUTTONUP || wParam == WM_MBUTTONUP || wParam == WM_RBUTTONUP)
                 {
                     if (MouseUp != null)
                     {
-                        MouseUp.Invoke(null, new Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y));
+                        MouseButton button = wParam == WM_LBUTTONUP ? MouseButton.Left
+                            : wParam == WM_MBUTTONUP ? MouseButton.Middle : MouseButton.Right;
+                        MouseUp.Invoke(null, new Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y), button);
                     }
                 }
             }
@@ -86,6 +89,8 @@ namespace PixiEditor.Helpers
 
         private const int WH_MOUSE_LL = 14;
         private const int WM_LBUTTONUP = 0x0202;
+        private const int WM_MBUTTONUP = 0x0208;
+        private const int WM_RBUTTONUP = 0x0205;
 
         [StructLayout(LayoutKind.Sequential)]
         private struct POINT
@@ -127,5 +132,5 @@ namespace PixiEditor.Helpers
         private static extern IntPtr GetModuleHandle(string name);
     }
 
-    public delegate void MouseUpEventHandler(object sender, Point p);
+    public delegate void MouseUpEventHandler(object sender, Point p, MouseButton button);
 }

+ 16 - 3
PixiEditor/Models/Controllers/BitmapManager.cs

@@ -12,6 +12,7 @@ using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools;
+using PixiEditor.Models.Tools.Tools;
 using PixiEditor.Models.Tools.ToolSettings.Settings;
 
 namespace PixiEditor.Models.Controllers
@@ -84,6 +85,8 @@ namespace PixiEditor.Models.Controllers
             MouseController.StartedRecordingChanges += MouseController_StartedRecordingChanges;
             MouseController.MousePositionChanged += Controller_MousePositionChanged;
             MouseController.StoppedRecordingChanges += MouseController_StoppedRecordingChanges;
+            MouseController.OnMouseDown += MouseController_OnMouseDown;
+            MouseController.OnMouseUp += MouseController_OnMouseUp;
             BitmapOperations = new BitmapOperationsUtility(this);
             ReadonlyToolUtility = new ReadonlyToolUtility();
         }
@@ -91,6 +94,16 @@ namespace PixiEditor.Models.Controllers
         public event EventHandler<LayersChangedEventArgs> LayersChanged;
         public event EventHandler<DocumentChangedEventArgs> DocumentChanged;
 
+        private void MouseController_OnMouseDown(object sender, MouseEventArgs e)
+        {
+            SelectedTool.OnMouseDown(e);
+        }
+
+        private void MouseController_OnMouseUp(object sender, MouseEventArgs e)
+        {
+            SelectedTool.OnMouseUp(e);
+        }
+
         public void SetActiveTool(Tool tool)
         {
             PreviewLayer = null;
@@ -174,18 +187,18 @@ namespace PixiEditor.Models.Controllers
 
         private bool IsDraggingViewport()
         {
-            return Keyboard.IsKeyDown(Key.LeftShift) && !(SelectedTool is ShapeTool);
+            return SelectedTool is MoveViewportTool;
         }
 
         private void MouseController_StartedRecordingChanges(object sender, EventArgs e)
         {
-            SelectedTool.OnMouseDown(new MouseEventArgs(Mouse.PrimaryDevice, (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
+            SelectedTool.OnRecordingLeftMouseDown(new MouseEventArgs(Mouse.PrimaryDevice, (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
             PreviewLayer = null;
         }
 
         private void MouseController_StoppedRecordingChanges(object sender, EventArgs e)
         {
-            SelectedTool.OnMouseUp(new MouseEventArgs(Mouse.PrimaryDevice, (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
+            SelectedTool.OnStoppedRecordingMouseUp(new MouseEventArgs(Mouse.PrimaryDevice, (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
             if (IsOperationTool(SelectedTool) && ((BitmapOperationTool) SelectedTool).RequiresPreviewLayer)
                 BitmapOperations.StopAction();
         }

+ 19 - 0
PixiEditor/Models/Controllers/MouseMovementController.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Windows.Input;
 using Accessibility;
 using PixiEditor.Models.Position;
 
@@ -11,6 +12,8 @@ namespace PixiEditor.Models.Controllers
         public bool IsRecordingChanges { get; private set; }
         public bool ClickedOnCanvas { get; set; }
         public event EventHandler StartedRecordingChanges;
+        public event EventHandler<MouseEventArgs> OnMouseDown;
+        public event EventHandler<MouseEventArgs> OnMouseUp;
         public event EventHandler<MouseMovementEventArgs> MousePositionChanged;
         public event EventHandler StoppedRecordingChanges;
 
@@ -44,6 +47,22 @@ namespace PixiEditor.Models.Controllers
             MousePositionChanged?.Invoke(this, new MouseMovementEventArgs(mouseCoordinates));
         }
 
+        /// <summary>
+        /// Plain mouse down, does not affect mouse recordings
+        /// </summary>
+        public void MouseDown(MouseEventArgs args)
+        {
+            OnMouseDown?.Invoke(this, args);
+        }
+
+        /// <summary>
+        /// Plain mouse up, does not affect mouse recordings
+        /// </summary>
+        public void MouseUp(MouseEventArgs args)
+        {
+            OnMouseUp?.Invoke(this, args);
+        }
+
         public void StopRecordingMouseMovementChanges()
         {
             if (IsRecordingChanges)

+ 4 - 1
PixiEditor/Models/Tools/Tool.cs

@@ -30,9 +30,12 @@ namespace PixiEditor.Models.Tools
         public bool CanStartOutsideCanvas { get; set; } = false;
 
         public virtual void OnMouseDown(MouseEventArgs e) { }
-
         public virtual void OnMouseUp(MouseEventArgs e) { }
 
+        public virtual void OnRecordingLeftMouseDown(MouseEventArgs e) { }
+
+        public virtual void OnStoppedRecordingMouseUp(MouseEventArgs e) { }
+
         public virtual void OnMouseMove(MouseEventArgs e) { }
 
         public virtual void AfterAddedUndo() { }

+ 1 - 1
PixiEditor/Models/Tools/Tools/BrightnessTool.cs

@@ -28,7 +28,7 @@ namespace PixiEditor.Models.Tools.Tools
             Toolbar = new BrightnessToolToolbar(CorrectionFactor);
         }
 
-        public override void OnMouseDown(MouseEventArgs e)
+        public override void OnRecordingLeftMouseDown(MouseEventArgs e)
         {
             _pixelsVisited.Clear();
         }

+ 1 - 1
PixiEditor/Models/Tools/Tools/MoveTool.cs

@@ -62,7 +62,7 @@ namespace PixiEditor.Models.Tools.Tools
             }
         }
 
-        public override void OnMouseUp(MouseEventArgs e) //This adds undo if there is no selection, reason why this isn't in AfterUndoAdded,
+        public override void OnStoppedRecordingMouseUp(MouseEventArgs e) //This adds undo if there is no selection, reason why this isn't in AfterUndoAdded,
         {   //is because it doesn't fire if no pixel changes were made.
             if (_currentSelection != null && _currentSelection.Length == 0)
             {

+ 14 - 2
PixiEditor/Models/Tools/Tools/MoveViewportTool.cs

@@ -14,16 +14,20 @@ namespace PixiEditor.Models.Tools.Tools
         {
             HideHighlight = true;
             Cursor = Cursors.SizeAll;
+            Tooltip = "Move viewport. (H)";
         }
 
         public override void OnMouseDown(MouseEventArgs e)
         {
-             _clickPoint = MousePositionConverter.GetCursorPosition();
+            if (e.LeftButton == MouseButtonState.Pressed || e.MiddleButton == MouseButtonState.Pressed)
+            {
+                _clickPoint = MousePositionConverter.GetCursorPosition();
+            }
         }
 
         public override void OnMouseMove(MouseEventArgs e)
         {
-            if (e.LeftButton == MouseButtonState.Pressed)
+            if (e.LeftButton == MouseButtonState.Pressed || e.MiddleButton == MouseButtonState.Pressed)
             {
                 var point = MousePositionConverter.GetCursorPosition();
                 ViewModelMain.Current.ViewportPosition = new System.Windows.Point(point.X - _clickPoint.X, 
@@ -31,6 +35,14 @@ namespace PixiEditor.Models.Tools.Tools
             }
         }
 
+        public override void OnMouseUp(MouseEventArgs e)
+        {
+            if (e.MiddleButton == MouseButtonState.Pressed)
+            {
+                ViewModelMain.Current.SetActiveTool(ViewModelMain.Current.LastActionTool);
+            }
+        }
+
         public override void Use(Coordinates[] pixels)
         {
         }

+ 2 - 2
PixiEditor/Models/Tools/Tools/SelectTool.cs

@@ -25,7 +25,7 @@ namespace PixiEditor.Models.Tools.Tools
             Toolbar = new SelectToolToolbar();
         }
 
-        public override void OnMouseDown(MouseEventArgs e)
+        public override void OnRecordingLeftMouseDown(MouseEventArgs e)
         {
             Enum.TryParse((Toolbar.GetSetting<DropdownSetting>("Mode")?.Value as ComboBoxItem)?.Content as string, out SelectionType);
 
@@ -35,7 +35,7 @@ namespace PixiEditor.Models.Tools.Tools
                 _oldSelection = ViewModelMain.Current.ActiveSelection;
         }
 
-        public override void OnMouseUp(MouseEventArgs e)
+        public override void OnStoppedRecordingMouseUp(MouseEventArgs e)
         {
             if (ViewModelMain.Current.ActiveSelection.SelectedPoints.Count() <= 1)
             {

+ 2 - 2
PixiEditor/Models/Tools/Tools/ZoomTool.cs

@@ -25,7 +25,7 @@ namespace PixiEditor.Models.Tools.Tools
             _pixelsPerZoomMultiplier = _workAreaWidth / ZoomSensitivityMultiplier;
         }
 
-        public override void OnMouseDown(MouseEventArgs e)
+        public override void OnRecordingLeftMouseDown(MouseEventArgs e)
         {
             _startingX = MousePositionConverter.GetCursorPosition().X;
             ViewModelMain.Current.ZoomPercentage = 100; //This resest the value, so callback in MainDrawingPanel can fire again later
@@ -43,7 +43,7 @@ namespace PixiEditor.Models.Tools.Tools
             }
         }
 
-        public override void OnMouseUp(MouseEventArgs e)
+        public override void OnStoppedRecordingMouseUp(MouseEventArgs e)
         {
             if (e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released && 
                 _startingX == MousePositionConverter.GetCursorPosition().X)

+ 13 - 5
PixiEditor/ViewModels/ViewModelMain.cs

@@ -237,7 +237,7 @@ namespace PixiEditor.ViewModels
         }
 
         private bool _restoreToolOnKeyUp = false;
-        private Tool _lastActionTool;
+        public Tool LastActionTool { get; private set; }
 
         public UpdateChecker UpdateChecker { get; set; }
 
@@ -306,6 +306,7 @@ namespace PixiEditor.ViewModels
                     new Shortcut(Key.V, SelectToolCommand, ToolType.Move),
                     new Shortcut(Key.M, SelectToolCommand, ToolType.Select),
                     new Shortcut(Key.Z, SelectToolCommand, ToolType.Zoom),
+                    new Shortcut(Key.H, SelectToolCommand, ToolType.MoveViewport),
                     new Shortcut(Key.OemPlus, ZoomCommand, 115),
                     new Shortcut(Key.OemMinus, ZoomCommand, 85),
                     new Shortcut(Key.OemOpenBrackets, ChangeToolSizeCommand, -1),
@@ -633,7 +634,7 @@ namespace PixiEditor.ViewModels
             if (_restoreToolOnKeyUp && ShortcutController.LastShortcut != null && ShortcutController.LastShortcut.ShortcutKey == args.Key)
             {
                 _restoreToolOnKeyUp = false;
-                SetActiveTool(_lastActionTool);
+                SetActiveTool(LastActionTool);
                 ShortcutController.BlockShortcutExecution = false;
             }
         }
@@ -737,7 +738,7 @@ namespace PixiEditor.ViewModels
             if (activeTool != null) activeTool.IsActive = false;
 
             tool.IsActive = true;
-            _lastActionTool = BitmapManager.SelectedTool;
+            LastActionTool = BitmapManager.SelectedTool;
             BitmapManager.SetActiveTool(tool);
             SetToolCursor(tool.ToolType);
         }
@@ -763,6 +764,8 @@ namespace PixiEditor.ViewModels
                     BitmapManager.MouseController.RecordMouseMovementChange(MousePositionConverter.CurrentCoordinates);
                 }
             }
+            BitmapManager.MouseController.MouseDown(new MouseEventArgs(Mouse.PrimaryDevice,
+                (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
 
             // Mouse down is guaranteed to only be raised from within this application, so by subscribing here we
             // only listen for mouse up events that occurred as a result of a mouse down within this application.
@@ -771,10 +774,15 @@ namespace PixiEditor.ViewModels
         }
 
         // this is public for testing.
-        public void MouseHook_OnMouseUp(object sender, Point p)
+        public void MouseHook_OnMouseUp(object sender, Point p, MouseButton button)
         {
             GlobalMouseHook.OnMouseUp -= MouseHook_OnMouseUp;
-            BitmapManager.MouseController.StopRecordingMouseMovementChanges();
+            if (button == MouseButton.Left)
+            {
+                BitmapManager.MouseController.StopRecordingMouseMovementChanges();
+            }
+            BitmapManager.MouseController.MouseUp(new MouseEventArgs(Mouse.PrimaryDevice, 
+                (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()));
         }
 
         /// <summary>

+ 1 - 1
PixiEditor/Views/MainDrawingPanel.xaml

@@ -10,7 +10,7 @@
              mc:Ignorable="d" PreviewMouseDown="mainDrawingPanel_MouseDown" PreviewMouseUp="mainDrawingPanel_PreviewMouseUp"
              d:DesignHeight="450" d:DesignWidth="800" x:Name="mainDrawingPanel" PreviewMouseWheel="Zoombox_MouseWheel">
     <xctk:Zoombox PreviewMouseDown="Zoombox_PreviewMouseDown" Cursor="{Binding Cursor}" Name="Zoombox" KeepContentInBounds="True"
-                  Loaded="Zoombox_Loaded" IsAnimated="False"
+                  Loaded="Zoombox_Loaded" IsAnimated="False" MouseDown="Zoombox_MouseDown"
                   CurrentViewChanged="Zoombox_CurrentViewChanged" DragModifiers="Blocked" ZoomModifiers="None">
         <i:Interaction.Triggers>
             <i:EventTrigger EventName="MouseMove">

+ 34 - 0
PixiEditor/Views/MainDrawingPanel.xaml.cs

@@ -116,6 +116,31 @@ namespace PixiEditor.Views
             set => SetValue(IsUsingZoomToolProperty, value);
         }
 
+        public ICommand MiddleMouseClickedCommand
+        {
+            get { return (ICommand)GetValue(MiddleMouseClickedCommandProperty); }
+            set { SetValue(MiddleMouseClickedCommandProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for MiddleMouseClickedCommand.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty MiddleMouseClickedCommandProperty =
+            DependencyProperty.Register("MiddleMouseClickedCommand", typeof(ICommand), typeof(MainDrawingPanel), new PropertyMetadata(default(ICommand)));
+
+
+
+        public object MiddleMouseClickedCommandParameter
+        {
+            get { return (object)GetValue(MiddleMouseClickedCommandParameterProperty); }
+            set { SetValue(MiddleMouseClickedCommandParameterProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for MiddleMouseClickedCommandParameter.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty MiddleMouseClickedCommandParameterProperty =
+            DependencyProperty.Register("MiddleMouseClickedCommandParameter", typeof(object), typeof(MainDrawingPanel), 
+                new PropertyMetadata(default(object)));
+
+
+
         private static void ZoomPercentegeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
         {
             MainDrawingPanel panel = (MainDrawingPanel)d;
@@ -213,5 +238,14 @@ namespace PixiEditor.Views
         {
             ((IInputElement)sender).ReleaseMouseCapture();
         }
+
+        private void Zoombox_MouseDown(object sender, MouseButtonEventArgs e)
+        {
+            if (e.MiddleButton == MouseButtonState.Pressed && 
+                MiddleMouseClickedCommand.CanExecute(MiddleMouseClickedCommandParameter))
+            {
+                MiddleMouseClickedCommand.Execute(MiddleMouseClickedCommandParameter);
+            }
+        }
     }
 }

+ 3 - 1
PixiEditor/Views/MainWindow.xaml

@@ -5,7 +5,7 @@
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:vm="clr-namespace:PixiEditor.ViewModels"
         xmlns:vws="clr-namespace:PixiEditor.Views"
-        xmlns:helpers="clr-namespace:PixiEditor.Helpers"
+        xmlns:tools="clr-namespace:PixiEditor.Models.Tools"
         xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
         xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
@@ -164,6 +164,8 @@
             <Grid>
                 <vws:MainDrawingPanel ZoomPercentage="{Binding ZoomPercentage, Mode=TwoWay}" Center="{Binding RecenterZoombox, Mode=TwoWay}" x:Name="DrawingPanel"
                                       CenterOnStart="True" Cursor="{Binding ToolCursor}" 
+                                      MiddleMouseClickedCommand="{Binding SelectToolCommand}" 
+                                      MiddleMouseClickedCommandParameter="{x:Static tools:ToolType.MoveViewport}"
                                       ViewportPosition="{Binding ViewportPosition, Mode=TwoWay}">
                     <i:Interaction.Triggers>
                         <i:EventTrigger EventName="MouseMove">

+ 1 - 1
PixiEditor/Views/MainWindow.xaml.cs

@@ -22,7 +22,7 @@ namespace PixiEditor
             InitializeComponent();
             StateChanged += MainWindowStateChangeRaised;
             MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
-            viewModel = ((ViewModelMain)DataContext);
+            viewModel = (ViewModelMain)DataContext;
             viewModel.CloseAction = Close;
         }