From 340530db19f339b1fb377c81e4ee9c510c3c51f2 Mon Sep 17 00:00:00 2001 From: Renan Alvarenga Date: Wed, 12 Jun 2024 15:25:37 +1000 Subject: [PATCH 1/4] SelecrtionBos now updates when scrolling --- .../Behaviors/SelectionBoxBehavior.cs | 30 ++++++++++++++--- .../Behaviors/SelectionBoxBehaviorTests.cs | 32 +++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs index 3364becd..8bface1f 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs @@ -12,6 +12,9 @@ public class SelectionBoxBehavior : DragBehavior private Point? _initialClientPoint; public event EventHandler? SelectionBoundsChanged; + private double? _lastClientX; + private double? _lastClientY; + private Point? _initialPan; public SelectionBoxBehavior(Diagram diagram) : base(diagram) @@ -19,6 +22,7 @@ public SelectionBoxBehavior(Diagram diagram) Diagram.PointerDown += OnPointerDown; Diagram.PointerMove += OnPointerMove; Diagram.PointerUp += OnPointerUp; + Diagram.PanChanged += OnPanChanged; } public override void Dispose() @@ -26,6 +30,7 @@ public override void Dispose() Diagram.PointerDown -= OnPointerDown; Diagram.PointerMove -= OnPointerMove; Diagram.PointerUp -= OnPointerUp; + Diagram.PanChanged -= OnPanChanged; } protected override void OnPointerDown(Model? model, PointerEventArgs e) @@ -34,6 +39,9 @@ protected override void OnPointerDown(Model? model, PointerEventArgs e) return; _initialClientPoint = new Point(e.ClientX, e.ClientY); + _lastClientX = e.ClientX; + _lastClientY = e.ClientY; + _initialPan = Diagram.Pan; } protected override void OnPointerMove(Model? model, PointerEventArgs e) @@ -41,7 +49,10 @@ protected override void OnPointerMove(Model? model, PointerEventArgs e) if (_initialClientPoint == null) return; - UpdateSelectionBox(e); + _lastClientX = e.ClientX; + _lastClientY = e.ClientY; + + UpdateSelectionBox(e.ClientX, e.ClientY); var start = Diagram.GetRelativeMousePoint(_initialClientPoint.X, _initialClientPoint.Y); var end = Diagram.GetRelativeMousePoint(e.ClientX, e.ClientY); @@ -61,10 +72,10 @@ protected override void OnPointerMove(Model? model, PointerEventArgs e) } } - void UpdateSelectionBox(MouseEventArgs e) + void UpdateSelectionBox(double clientX, double clientY) { - var start = Diagram.GetRelativePoint(_initialClientPoint!.X, _initialClientPoint.Y); - var end = Diagram.GetRelativePoint(e.ClientX, e.ClientY); + var start = Diagram.GetRelativePoint(_initialClientPoint!.X + Diagram.Pan.X - _initialPan.X, _initialClientPoint.Y + Diagram.Pan.Y - _initialPan.Y); + var end = Diagram.GetRelativePoint(clientX, clientY); var (sX, sY) = (Math.Min(start.X, end.X), Math.Min(start.Y, end.Y)); var (eX, eY) = (Math.Max(start.X, end.X), Math.Max(start.Y, end.Y)); SelectionBoundsChanged?.Invoke(this, new Rectangle(sX, sY, eX, eY)); @@ -74,6 +85,17 @@ protected override void OnPointerUp(Model? model, PointerEventArgs e) { _initialClientPoint = null; SelectionBoundsChanged?.Invoke(this, null); + _lastClientX = null; + _lastClientY = null; + _initialPan = null; + } + + public void OnPanChanged(double deltaX, double deltaY) + { + if (_initialClientPoint == null || _lastClientX == null || _lastClientY == null) + return; + + UpdateSelectionBox((double) _lastClientX, (double) _lastClientY); } } } diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index ba0d94d6..9286d7ec 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -37,6 +37,38 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() Assert.Equal(50, lastBounds.Height); Assert.Equal(100, lastBounds.Top); Assert.Equal(100, lastBounds.Left); + } + + [Fact] + public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBoundsOnScroll() + { + // Arrange + var diagram = new TestDiagram(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramShiftDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + + var selectionBoxBehavior = diagram.GetBehavior()!; + bool boundsChangedEventInvoked = false; + Rectangle? lastBounds = null; + selectionBoxBehavior.SelectionBoundsChanged += (_, newBounds) => + { + boundsChangedEventInvoked = true; + lastBounds = newBounds; + }; + + // Act + diagram.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.TriggerWheel(new WheelEventArgs(100, 100,0,0,false,true,false,200,150,0,0)); + + // Assert + Assert.True(boundsChangedEventInvoked); + Assert.Equal(200, lastBounds!.Width); + Assert.Equal(150, lastBounds.Height); + Assert.Equal(-50, lastBounds.Top); + Assert.Equal(-100, lastBounds.Left); } [Fact] From 6583d528358b14e422a57d51769b0522b96701c8 Mon Sep 17 00:00:00 2001 From: Renan Alvarenga Date: Mon, 17 Jun 2024 14:23:06 +1000 Subject: [PATCH 2/4] Fixed PR comments --- .../Behaviors/SelectionBoxBehavior.cs | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs index 8bface1f..98a67974 100644 --- a/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs +++ b/src/Blazor.Diagrams.Core/Behaviors/SelectionBoxBehavior.cs @@ -53,28 +53,17 @@ protected override void OnPointerMove(Model? model, PointerEventArgs e) _lastClientY = e.ClientY; UpdateSelectionBox(e.ClientX, e.ClientY); - - var start = Diagram.GetRelativeMousePoint(_initialClientPoint.X, _initialClientPoint.Y); - var end = Diagram.GetRelativeMousePoint(e.ClientX, e.ClientY); - var (sX, sY) = (Math.Min(start.X, end.X), Math.Min(start.Y, end.Y)); - var (eX, eY) = (Math.Max(start.X, end.X), Math.Max(start.Y, end.Y)); - var bounds = new Rectangle(sX, sY, eX, eY); - - foreach (var node in Diagram.Nodes) - { - var nodeBounds = node.GetBounds(); - if (nodeBounds == null) - continue; - - if (bounds.Overlap(nodeBounds)) - Diagram.SelectModel(node, false); - else if (node.Selected) Diagram.UnselectModel(node); - } + SelectNodesInBounds(e.ClientX, e.ClientY); } void UpdateSelectionBox(double clientX, double clientY) { - var start = Diagram.GetRelativePoint(_initialClientPoint!.X + Diagram.Pan.X - _initialPan.X, _initialClientPoint.Y + Diagram.Pan.Y - _initialPan.Y); + if(_initialClientPoint == null || _initialPan == null) + { + return; + } + + var start = Diagram.GetRelativePoint(_initialClientPoint.X + Diagram.Pan.X - _initialPan.X, _initialClientPoint.Y + Diagram.Pan.Y - _initialPan.Y); var end = Diagram.GetRelativePoint(clientX, clientY); var (sX, sY) = (Math.Min(start.X, end.X), Math.Min(start.Y, end.Y)); var (eX, eY) = (Math.Max(start.X, end.X), Math.Max(start.Y, end.Y)); @@ -96,6 +85,31 @@ public void OnPanChanged(double deltaX, double deltaY) return; UpdateSelectionBox((double) _lastClientX, (double) _lastClientY); + SelectNodesInBounds((double) _lastClientX, (double) _lastClientY); + } + + void SelectNodesInBounds(double clientX, double clientY) + { + if(_initialClientPoint == null || _initialPan == null) + { + return; + } + + var start = Diagram.GetRelativeMousePoint(_initialClientPoint.X + Diagram.Pan.X - _initialPan.X, _initialClientPoint.Y + Diagram.Pan.Y - _initialPan.Y); + var end = Diagram.GetRelativeMousePoint(clientX, clientY); + var (sX, sY) = (Math.Min(start.X, end.X), Math.Min(start.Y, end.Y)); + var (eX, eY) = (Math.Max(start.X, end.X), Math.Max(start.Y, end.Y)); + var bounds = new Rectangle(sX, sY, eX, eY); + + foreach (var node in Diagram.Nodes) + { + var nodeBounds = node.GetBounds(); + if (nodeBounds == null) + continue; + if (bounds.Overlap(nodeBounds)) + Diagram.SelectModel(node, false); + else if (node.Selected) Diagram.UnselectModel(node); + } } } } From 7edf131252dc1b4696af7420af3eacd0ecb174c6 Mon Sep 17 00:00:00 2001 From: Renan Alvarenga Date: Wed, 19 Jun 2024 16:04:25 +1000 Subject: [PATCH 3/4] Added tests --- .../Behaviors/SelectionBoxBehaviorTests.cs | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index 9286d7ec..6aa11254 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -37,8 +37,8 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBounds() Assert.Equal(50, lastBounds.Height); Assert.Equal(100, lastBounds.Top); Assert.Equal(100, lastBounds.Left); - } - + } + [Fact] public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBoundsOnScroll() { @@ -61,7 +61,7 @@ public void Behavior_WhenBehaviorEnabled_ShouldUpdateSelectionBoundsOnScroll() // Act diagram.TriggerPointerDown(null, new PointerEventArgs(100, 100, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); - diagram.TriggerWheel(new WheelEventArgs(100, 100,0,0,false,true,false,200,150,0,0)); + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, true, false, 200, 150, 0, 0)); // Assert Assert.True(boundsChangedEventInvoked); @@ -131,6 +131,37 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideArea() Assert.False(node.Selected); } + [Fact] + public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideAreaWhenScrolling() + { + // Arrange + var diagram = new TestDiagram(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + + var selectionBoxBehavior = diagram.GetBehavior()!; + selectionBoxBehavior.SelectionBoundsChanged += (_, _) => { }; + + var node = new NodeModel() + { + Size = new Size(100, 100), + Position = new Point(150, 150) + }; + diagram.Nodes.Add(node); + + // Act + diagram.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, true, false, 200, 200, 0, 0)); + + // Assert + Assert.True(node.Selected); + + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, true, false, -200, -200, 0, 0)); + + Assert.False(node.Selected); + } + [Fact] public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea() { @@ -159,5 +190,34 @@ public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); Assert.False(node.Selected); } + + [Fact] + public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideAreaWhenScrolling() + { + // Arrange + var diagram = new TestDiagram(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); + + var node = new NodeModel() + { + Size = new Size(100, 100), + Position = new Point(150, 150) + }; + diagram.Nodes.Add(node); + + // Act + diagram.TriggerPointerDown(null, + new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, true, false, 200, 200, 0, 0)); + + + // Assert + Assert.False(node.Selected); + + diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, true, false, -200, -200, 0, 0)); + + Assert.False(node.Selected); + } } } From 63b8622ee2b33d3b6d038c41ccb6b22eb6c92166 Mon Sep 17 00:00:00 2001 From: Renan Alvarenga Date: Wed, 19 Jun 2024 16:13:10 +1000 Subject: [PATCH 4/4] Fixed test issue --- .../Behaviors/SelectionBoxBehaviorTests.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs index 6aa11254..a394e033 100644 --- a/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs +++ b/tests/Blazor.Diagrams.Core.Tests/Behaviors/SelectionBoxBehaviorTests.cs @@ -136,7 +136,9 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideAreaWhenSc { // Arrange var diagram = new TestDiagram(); - diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramShiftDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var selectionBoxBehavior = diagram.GetBehavior()!; @@ -151,7 +153,7 @@ public void Behavior_WithBoundsChangedDelegate_ShouldSelectNodesInsideAreaWhenSc // Act diagram.TriggerPointerDown(null, - new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + new PointerEventArgs(100, 100, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, true, false, 200, 200, 0, 0)); // Assert @@ -196,7 +198,9 @@ public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea { // Arrange var diagram = new TestDiagram(); - diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramShiftDragBehavior = diagram.GetBehavior(); + diagram.BehaviorOptions.DiagramWheelBehavior = diagram.GetBehavior(); diagram.SetContainer(new Rectangle(Point.Zero, new Size(100, 100))); var node = new NodeModel() @@ -208,7 +212,7 @@ public void Behavior_WithoutBoundsChangedDelegate_ShouldNotSelectNodesInsideArea // Act diagram.TriggerPointerDown(null, - new PointerEventArgs(100, 100, 0, 0, false, false, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); + new PointerEventArgs(100, 100, 0, 0, false, true, false, 0, 0, 0, 0, 0, 0, string.Empty, true)); diagram.TriggerWheel(new WheelEventArgs(100, 100, 0, 0, false, true, false, 200, 200, 0, 0));