Skip to content

Commit

Permalink
WI00737678 : Remove DragNodeBehavior
Browse files Browse the repository at this point in the history
  • Loading branch information
gnawisetech committed May 28, 2024
1 parent 6478de3 commit 8692bac
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 55 deletions.
171 changes: 117 additions & 54 deletions src/Blazor.Diagrams.Core/Behaviors/DragMovablesBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
using Blazor.Diagrams.Core.Behaviors.Base;
using Blazor.Diagrams.Core.Events;
using Blazor.Diagrams.Core.Geometry;
using Blazor.Diagrams.Core.Models;
using Blazor.Diagrams.Core.Geometry;
using Blazor.Diagrams.Core.Models.Base;
using Blazor.Diagrams.Core.Events;
using System;
using System.Collections.Generic;
using Blazor.Diagrams.Core.Models;
using DiagramPoint = Blazor.Diagrams.Core.Geometry.Point;
using System.Linq;
using Blazor.Diagrams.Core.Behaviors.Base;

namespace Blazor.Diagrams.Core.Behaviors;

public class DragMovablesBehavior : Behavior
{
private readonly Dictionary<MovableModel, Point> _initialPositions;
record NodeMoveablePositions(Point position)
{
public Dictionary<NodeModel, DiagramPoint> ChildPositions { get; } = new();
}

private readonly Dictionary<NodeModel, NodeMoveablePositions> _initialPositions;
private double? _lastClientX;
private double? _lastClientY;
private bool _moved;
private double _totalMovedX = 0;
private double _totalMovedY = 0;
double _totalMovedX = 0;
double _totalMovedY = 0;

public const double CHILD_NODE_MIN_OFFSET_TOP = 40;
public const double CHILD_NODE_MIN_OFFSET_BOTTOM = 5;

public DragMovablesBehavior(Diagram diagram) : base(diagram)
{
_initialPositions = new Dictionary<MovableModel, Point>();
_initialPositions = new Dictionary<NodeModel, NodeMoveablePositions>();
Diagram.PointerDown += OnPointerDown;
Diagram.PointerMove += OnPointerMove;
Diagram.PointerUp += OnPointerUp;
Diagram.PanChanged += OnPanChanged;
}

private void OnPointerDown(Model? model, PointerEventArgs e)
{
if (model is not MovableModel)
if (model is not NodeModel)
return;

_initialPositions.Clear();
foreach (var sm in Diagram.GetSelectedModels())
{
if (sm is not MovableModel movable || movable.Locked)
continue;

// Special case: groups without auto size on
if (sm is NodeModel node && node.Group != null && !node.Group.AutoSize)
continue;

var position = movable.Position;
if (Diagram.Options.GridSnapToCenter && movable is NodeModel n)
if (sm is not NodeModel movable || movable.Locked)
{
position = new Point(movable.Position.X + (n.Size?.Width ?? 0) / 2,
movable.Position.Y + (n.Size?.Height ?? 0) / 2);
continue;
}

_initialPositions.Add(movable, position);
_initialPositions.Add(movable, new NodeMoveablePositions(movable.Position));
}

_lastClientX = e.ClientX;
Expand All @@ -58,50 +58,111 @@ private void OnPointerDown(Model? model, PointerEventArgs e)

private void OnPointerMove(Model? model, PointerEventArgs e)
{
if (!_moved)
{
foreach (var node in _initialPositions.Keys.ToArray())
{
if (node is NodeModel jobNode)
{
var parent = jobNode.ParentNode;
while (parent != null)
{
if (_initialPositions.ContainsKey(parent))
{
_initialPositions.Remove(jobNode);
break;
}

parent = parent.ParentNode;
}
}
}

foreach (var (node, positions) in _initialPositions)
{
if (node is NodeModel jobNode)
{
foreach (var child in jobNode.GetAllChildNodes())
{
if (!child.Selected)
{
Diagram.SelectModel(child, false);
}

positions.ChildPositions[child] = child.Position;
}
}
}
}
if (_initialPositions.Count == 0 || _lastClientX == null || _lastClientY == null)
{
return;
}

_moved = true;
var deltaX = (e.ClientX - _lastClientX.Value) / Diagram.Zoom;
var deltaY = (e.ClientY - _lastClientY.Value) / Diagram.Zoom;

_totalMovedX += deltaX;
_totalMovedY += deltaY;
var dx = (e.ClientX - _lastClientX.Value) / Diagram.Zoom;
var dy = (e.ClientY - _lastClientY.Value) / Diagram.Zoom;

_totalMovedX += dx;
_totalMovedY += dy;

MoveNodes(model, _totalMovedX, _totalMovedY);

_lastClientX = e.ClientX;
_lastClientY = e.ClientY;

}
public void OnPanChanged(double deltaX, double deltaY)

void MoveNodes(Model? model, double deltaX, double deltaY)
{
if (_initialPositions.Count == 0 || _lastClientX == null || _lastClientY == null)
return;
foreach (var (node, positions) in _initialPositions)
{
SetPosition(node, positions.position.X + deltaX, positions.position.Y + deltaY);
deltaX = node.Position.X - positions.position.X;
deltaY = node.Position.Y - positions.position.Y;

_moved = true;
foreach (var (childNode, childPosition) in positions.ChildPositions)
{
SetPosition(childNode, childPosition.X + deltaX, childPosition.Y + deltaY);
}

_totalMovedX += deltaX;
_totalMovedY += deltaY;
if (node is NodeModel movableNode)
{
movableNode.TriggerMoving();
}
}
}

MoveNodes(null, _totalMovedX, _totalMovedY);
void SetPosition(NodeModel node, double x, double y)
{
if (node is NodeModel nodeModel && nodeModel.ParentNode != null)
{
x = Clamp(x, nodeModel.Size?.Width, nodeModel.ParentNode.Position.X, nodeModel.ParentNode.Size?.Width);
var parentY = nodeModel.ParentNode.Position.Y + CHILD_NODE_MIN_OFFSET_TOP;
var parentH = nodeModel.ParentNode.Size?.Height - CHILD_NODE_MIN_OFFSET_TOP - CHILD_NODE_MIN_OFFSET_BOTTOM;
y = Clamp(y, nodeModel.Size?.Height, parentY, parentH);

nodeModel.SetPosition(x, y);
}
}

private void MoveNodes(Model? model, double deltaX, double deltaY)
double Clamp(double position, double? size, double? parentPosition, double? parentSize)
{
foreach (var (movable, initialPosition) in _initialPositions)
var clamped = position;

if (size != null && parentPosition != null && parentSize != null)
{
var ndx = ApplyGridSize(deltaX + initialPosition.X);
var ndy = ApplyGridSize(deltaY + initialPosition.Y);
if (Diagram.Options.GridSnapToCenter && movable is NodeModel node)
if (position < parentPosition)
{
node.SetPosition(ndx - (node.Size?.Width ?? 0) / 2, ndy - (node.Size?.Height ?? 0) / 2);
clamped = (double)parentPosition;
}
else
else if (position + size > parentPosition + parentSize)
{
movable.SetPosition(ndx, ndy);
clamped = (double)(parentPosition + parentSize - size);
}
}

return clamped;
}

private void OnPointerUp(Model? model, PointerEventArgs e)
Expand All @@ -111,33 +172,35 @@ private void OnPointerUp(Model? model, PointerEventArgs e)

if (_moved)
{
foreach (var (movable, _) in _initialPositions)
foreach (var (movable, childMovableNodes) in _initialPositions)
{
movable.TriggerMoved();
if (movable is NodeModel movableNode)
{
foreach (var child in movableNode.GetAllChildNodes())
{
if (childMovableNodes.ChildPositions.ContainsKey(child))
{
child.TriggerMoved();
}
}
}
}
}

_initialPositions.Clear();
_totalMovedX = 0;
_totalMovedY = 0;
_lastClientX = null;
_lastClientY = null;
}

private double ApplyGridSize(double n)
{
if (Diagram.Options.GridSize == null)
return n;

var gridSize = Diagram.Options.GridSize.Value;
return gridSize * Math.Floor((n + gridSize / 2.0) / gridSize);
}

public override void Dispose()
{
_initialPositions.Clear();

Diagram.PointerDown -= OnPointerDown;
Diagram.PointerMove -= OnPointerMove;
Diagram.PointerUp -= OnPointerUp;
Diagram.PanChanged -= OnPanChanged;
}
}
}
32 changes: 31 additions & 1 deletion src/Blazor.Diagrams.Core/Models/NodeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class NodeModel : MovableModel, IHasBounds, IHasShape, ILinkable
public event Action<NodeModel>? SizeChanged;
public event Action<NodeModel>? Moving;

internal NodeModel? ParentNode;

public NodeModel(Point? position = null) : base(position)
{
}
Expand Down Expand Up @@ -190,12 +192,40 @@ private void UpdatePortPositions(Size oldSize, Size newSize)
}
}

protected void TriggerMoving()
internal void TriggerMoving()
{
Moving?.Invoke(this);
}

void ILinkable.AddLink(BaseLinkModel link) => _links.Add(link);

void ILinkable.RemoveLink(BaseLinkModel link) => _links.Remove(link);

internal List<NodeModel> GetAllChildNodes()
{
var allChildren = new List<NodeModel>();
foreach (var child in childMovableNodes)
{
allChildren.Add(child);
if (child is NodeModel jobChild)
{
allChildren.AddRange(jobChild.GetAllChildNodes());
}
}
return allChildren;
}

internal void AddChildNode(NodeModel child)
{
child.ParentNode = this;
childMovableNodes.Add(child);
}

internal void RemoveChildNode(NodeModel child)
{
childMovableNodes.Remove(child);
child.ParentNode = null;
}

internal List<NodeModel> childMovableNodes = new List<NodeModel>();
}

0 comments on commit 8692bac

Please sign in to comment.