Skip to content

Commit

Permalink
Merge pull request #80 from PixiEditor/moveVPTool
Browse files Browse the repository at this point in the history
Added Move Viewport (Pan) Tool
  • Loading branch information
flabbet committed Oct 19, 2020
2 parents fd7cce9 + 7c288e9 commit 83ce96e
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 25 deletions.
13 changes: 9 additions & 4 deletions PixiEditor/Helpers/GlobalMouseHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;

namespace PixiEditor.Helpers
{
Expand Down Expand Up @@ -32,7 +33,7 @@ public static class GlobalMouseHook

public static void RaiseMouseUp()
{
MouseUp?.Invoke(default, default);
MouseUp?.Invoke(default, default, default);
}

private static void Unsubscribe()
Expand Down Expand Up @@ -73,11 +74,13 @@ private static int MouseHookProc(int nCode, int wParam, IntPtr lParam)
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);
}
}
}
Expand All @@ -86,6 +89,8 @@ private static int MouseHookProc(int nCode, int wParam, IntPtr lParam)

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
Expand Down Expand Up @@ -127,5 +132,5 @@ private struct MSLLHOOKSTRUCT
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);
}
19 changes: 16 additions & 3 deletions PixiEditor/Models/Controllers/BitmapManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
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
Expand Down Expand Up @@ -84,13 +85,25 @@ public BitmapManager()
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();
}

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;
Expand Down Expand Up @@ -174,18 +187,18 @@ public void ExecuteTool(Coordinates newPosition, bool clickedOnCanvas)

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();
}
Expand Down
19 changes: 19 additions & 0 deletions PixiEditor/Models/Controllers/MouseMovementController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Windows.Input;
using Accessibility;
using PixiEditor.Models.Position;

Expand All @@ -11,6 +12,8 @@ public class MouseMovementController
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;

Expand Down Expand Up @@ -44,6 +47,22 @@ public void MouseMoved(Coordinates mouseCoordinates)
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)
Expand Down
5 changes: 4 additions & 1 deletion PixiEditor/Models/Tools/Tool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ public bool IsActive
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() { }
Expand Down
1 change: 1 addition & 0 deletions PixiEditor/Models/Tools/ToolType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
public enum ToolType
{
None,
MoveViewport,
Move,
Pen,
Select,
Expand Down
2 changes: 1 addition & 1 deletion PixiEditor/Models/Tools/Tools/BrightnessTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public BrightnessTool()
Toolbar = new BrightnessToolToolbar(CorrectionFactor);
}

public override void OnMouseDown(MouseEventArgs e)
public override void OnRecordingLeftMouseDown(MouseEventArgs e)
{
_pixelsVisited.Clear();
}
Expand Down
2 changes: 1 addition & 1 deletion PixiEditor/Models/Tools/Tools/MoveTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public override void AfterAddedUndo()
}
}

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)
{
Expand Down
50 changes: 50 additions & 0 deletions PixiEditor/Models/Tools/Tools/MoveViewportTool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using PixiEditor.Models.Position;
using PixiEditor.ViewModels;
using System.Drawing;
using System.Windows.Input;

namespace PixiEditor.Models.Tools.Tools
{
public class MoveViewportTool : ReadonlyTool
{
public override ToolType ToolType => ToolType.MoveViewport;
private Point _clickPoint;

public MoveViewportTool()
{
HideHighlight = true;
Cursor = Cursors.SizeAll;
Tooltip = "Move viewport. (H)";
}

public override void OnMouseDown(MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed || e.MiddleButton == MouseButtonState.Pressed)
{
_clickPoint = MousePositionConverter.GetCursorPosition();
}
}

public override void OnMouseMove(MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed || e.MiddleButton == MouseButtonState.Pressed)
{
var point = MousePositionConverter.GetCursorPosition();
ViewModelMain.Current.ViewportPosition = new System.Windows.Point(point.X - _clickPoint.X,
point.Y - _clickPoint.Y);
}
}

public override void OnMouseUp(MouseEventArgs e)
{
if (e.MiddleButton == MouseButtonState.Pressed)
{
ViewModelMain.Current.SetActiveTool(ViewModelMain.Current.LastActionTool);
}
}

public override void Use(Coordinates[] pixels)
{
}
}
}
4 changes: 2 additions & 2 deletions PixiEditor/Models/Tools/Tools/SelectTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public SelectTool()
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);

Expand All @@ -35,7 +35,7 @@ public override void OnMouseDown(MouseEventArgs e)
_oldSelection = ViewModelMain.Current.ActiveSelection;
}

public override void OnMouseUp(MouseEventArgs e)
public override void OnStoppedRecordingMouseUp(MouseEventArgs e)
{
if (ViewModelMain.Current.ActiveSelection.SelectedPoints.Count() <= 1)
{
Expand Down
4 changes: 2 additions & 2 deletions PixiEditor/Models/Tools/Tools/ZoomTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public ZoomTool()
_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
Expand All @@ -43,7 +43,7 @@ public override void OnMouseMove(MouseEventArgs e)
}
}

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)
Expand Down
33 changes: 27 additions & 6 deletions PixiEditor/ViewModels/ViewModelMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,19 @@ public double ZoomPercentage
}
}

private Point _viewPortPosition;

public Point ViewportPosition
{
get => _viewPortPosition;
set
{
_viewPortPosition = value;
RaisePropertyChanged(nameof(ViewportPosition));
}
}


private bool _updateReadyToInstall = false;

public bool UpdateReadyToInstall
Expand Down Expand Up @@ -224,7 +237,7 @@ public Selection ActiveSelection
}

private bool _restoreToolOnKeyUp = false;
private Tool _lastActionTool;
public Tool LastActionTool { get; private set; }

public UpdateChecker UpdateChecker { get; set; }

Expand Down Expand Up @@ -273,7 +286,7 @@ public ViewModelMain()
RestartApplicationCommand = new RelayCommand(RestartApplication);
ToolSet = new ObservableCollection<Tool>
{
new MoveTool(), new PenTool(), new SelectTool(), new FloodFill(), new LineTool(),
new MoveViewportTool(), new MoveTool(), new PenTool(), new SelectTool(), new FloodFill(), new LineTool(),
new CircleTool(), new RectangleTool(), new EraserTool(), new ColorPickerTool(), new BrightnessTool(),
new ZoomTool()
};
Expand All @@ -293,6 +306,7 @@ public ViewModelMain()
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),
Expand Down Expand Up @@ -620,7 +634,7 @@ private void KeyUp(object parameter)
if (_restoreToolOnKeyUp && ShortcutController.LastShortcut != null && ShortcutController.LastShortcut.ShortcutKey == args.Key)
{
_restoreToolOnKeyUp = false;
SetActiveTool(_lastActionTool);
SetActiveTool(LastActionTool);
ShortcutController.BlockShortcutExecution = false;
}
}
Expand Down Expand Up @@ -724,7 +738,7 @@ public void SetActiveTool(Tool tool)
if (activeTool != null) activeTool.IsActive = false;

tool.IsActive = true;
_lastActionTool = BitmapManager.SelectedTool;
LastActionTool = BitmapManager.SelectedTool;
BitmapManager.SetActiveTool(tool);
SetToolCursor(tool.ToolType);
}
Expand All @@ -750,6 +764,8 @@ private void MouseDown(object parameter)
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.
Expand All @@ -758,10 +774,15 @@ private void MouseDown(object parameter)
}

// 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>
Expand Down
3 changes: 2 additions & 1 deletion PixiEditor/Views/MainDrawingPanel.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
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" CurrentViewChanged="Zoombox_CurrentViewChanged" DragModifiers="Shift" ZoomModifiers="None">
Loaded="Zoombox_Loaded" IsAnimated="False" MouseDown="Zoombox_MouseDown"
CurrentViewChanged="Zoombox_CurrentViewChanged" DragModifiers="Blocked" ZoomModifiers="None">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseMove">
<i:InvokeCommandAction Command="{Binding MouseMoveCommand, ElementName=mainDrawingPanel, Mode=OneWay}" />
Expand Down
Loading

0 comments on commit 83ce96e

Please sign in to comment.