JD2022-TU1/main/tools/framework/JD.Sequencers/Tools/DraggingTool.cs

160 lines
4.7 KiB
C#

using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using JD.Sequencers.Controls;
using JD.Sequencers.Windowlesses;
namespace JD.Sequencers.Tools
{
/// <summary>
/// Basic tool that moves controls.
/// </summary>
public class DraggingTool : Tool
{
#region Variables
private Point m_lastMovePosition;
private Point m_lastOriginalMovePosition;
#endregion
#region Constructor
/// <summary>
/// Constructor.
/// </summary>
/// <param name="owner"></param>
public DraggingTool(WindowlessContainer owner)
: base(owner)
{
}
#endregion
#region Properties
protected Point InitialMovePosition { get; set; }
#endregion
#region Methods
protected internal override bool CanStart(ToolStartingEventArgs e)
{
if (e.Button != MouseButtons.Left)
{
return false;
}
if (Selection.Count == 0 || Selection.Any(x => !x.CanDrag))
{
return false;
}
if (Container.LastMouseDownEventArgs == null)
{
return false;
}
Size size = SystemInformation.DragSize;
Point p1 = Container.LastMouseDownEventArgs.Location;
Point p2 = e.Location;
if ((System.Math.Abs(p1.X - p2.X) <= (size.Width / 2)) && (System.Math.Abs(p1.Y - p2.Y) <= (size.Height / 2)))
{
return false;
}
WindowlessControl control = Container.FindSelectableControl<WindowlessControl>(Container.LastMouseDownEventArgs.Location);
if (!Selection.Contains(control))
{
return false;
}
return base.CanStart(e);
}
protected internal override void Start()
{
base.Start();
InitialMovePosition = Container.LastMouseDownEventArgs.Location;
m_lastMovePosition = Container.LastMouseDownEventArgs.Location;
m_lastOriginalMovePosition = m_lastMovePosition;
// Find which control is the main "dragged one" in the current selection.
CurrentControl = Container.FindControl<WindowlessControl>(m_lastMovePosition, control => control.Selected) ?? Selection.FirstOrDefault();
foreach (WindowlessControl control in Selection)
{
control.OnBeginMoving();
}
Started?.Invoke(this, EventArgs.Empty);
}
protected internal override void End()
{
base.End();
foreach (WindowlessControl control in Selection)
{
control.OnEndMoving();
}
Ended?.Invoke(this, EventArgs.Empty);
}
protected internal override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
// Make sure selection contains something
if (Selection.Count == 0)
{
return;
}
// This avoids moving objects without any user impulsion. This can occur otherwise since
// we always compute the cursor delta by considering the last "snap" that altered the cursor location.
if (e.Location == m_lastOriginalMovePosition)
{
return;
}
m_lastOriginalMovePosition = e.Location;
Point newPosition = e.Location;
MoveSelection(ref newPosition, m_lastMovePosition);
var selectionMoved = new SelectionMovedEventArgs { NewLocation = newPosition, OriginalLocation = m_lastMovePosition };
SelectionMoved?.Invoke(this, selectionMoved);
m_lastMovePosition = selectionMoved.NewLocation;
}
protected virtual void MoveSelection(ref Point newPosition, Point oldPosition)
{
Point delta = new Point(newPosition.X - oldPosition.X,
newPosition.Y - oldPosition.Y);
Point location;
foreach (WindowlessControl control in Selection)
{
location = control.Location;
location.Offset(delta);
control.Location = location;
}
}
private static bool CanResizeControl(WindowlessControl control)
{
return control is IMovable movable &&
movable.IsMoveAllowed;
}
public event EventHandler<SelectionMovedEventArgs> SelectionMoved;
public event EventHandler Started;
public event EventHandler Ended;
#endregion
}
}